galaxy-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: inithello: Explicitly uninstall all installed repositories after each set of tests has finished running. This prevents certain edge cases from interfering with subsequent tests.
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/324d023bbf59/
Changeset: 324d023bbf59
User: inithello
Date: 2013-05-03 21:25:20
Summary: Explicitly uninstall all installed repositories after each set of tests has finished running. This prevents certain edge cases from interfering with subsequent tests.
Affected #: 2 files
diff -r e5577cd833abbd0ad072d55f4b56d1458105991b -r 324d023bbf59aafb4be03cbb9842456aab0a1965 test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py
--- a/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py
+++ b/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py
@@ -3,8 +3,10 @@
from install_and_test_tool_shed_repositories.base.twilltestcase import InstallTestRepository
log = logging.getLogger(__name__)
+
class InstallTestRepositories( InstallTestRepository ):
"""Abstract test case that installs and uninstalls a predefined list of repositories."""
+
def do_installation( self, repository_info_dict ):
self.logout()
self.login( email='test(a)bx.psu.edu', username='test' )
@@ -73,7 +75,7 @@
return test_install_repository
test_method = make_uninstall_method( repository_dict )
test_method.__doc__ = "Uninstall the repository %s." % repository_dict[ 'name' ]
- namespace[ 'install_repository_%s' % repository_dict[ 'name' ] ] = test_method
+ namespace[ 'uninstall_repository_%s' % repository_dict[ 'name' ] ] = test_method
# The new.classobj function returns a new class object, with name name, derived
# from baseclasses (which should be a tuple of classes) and with namespace dict.
new_class_obj = new.classobj( name, baseclasses, namespace )
diff -r e5577cd833abbd0ad072d55f4b56d1458105991b -r 324d023bbf59aafb4be03cbb9842456aab0a1965 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -179,19 +179,26 @@
return passed_tests
return []
-def execute_uninstall_method( repository_dict ):
- # Delete any configured tool functional tests from the test_toolbox.__dict__, otherwise nose will find them
- # and try to re-run the tests after uninstalling the repository, which will cause false failure reports,
- # since the test data has been deleted from disk by now.
- tests_to_delete = []
- for key in test_toolbox.__dict__:
- if key.startswith( 'TestForTool_' ):
- log.info( 'Tool test found in test_toolbox, deleting: %s' % key )
- tests_to_delete.append( key )
- for key in tests_to_delete:
- del test_toolbox.__dict__[ key ]
- # Generate a test method to uninstall this repository through the embedded Galaxy application's web interface.
- test_install_repositories.generate_uninstall_method( repository_dict )
+def execute_uninstall_method( app ):
+ # Clean out any generated tests.
+ remove_generated_tests( app )
+ sa_session = app.model.context.current
+ repositories_to_uninstall = sa_session.query( app.model.ToolShedRepository ).all()
+ for repository in repositories_to_uninstall:
+ if repository.status == app.model.ToolShedRepository.states.UNINSTALLED:
+ continue
+ if repository.status not in [ app.model.ToolShedRepository.installation_status.UNINSTALLED,
+ app.model.ToolShedRepository.installation_status.ERROR,
+ app.model.ToolShedRepository.installation_status.INSTALLED ]:
+ repository.status = app.model.ToolShedRepository.installation_status.ERROR
+ sa_session.add( repository )
+ sa_session.flush()
+ name = str( repository.name )
+ owner = str( repository.owner )
+ changeset_revision = str( repository.installed_changeset_revision )
+ repository_dict = dict( name=name, owner=owner, changeset_revision=changeset_revision )
+ # Generate a test method to uninstall this repository through the embedded Galaxy application's web interface.
+ test_install_repositories.generate_uninstall_method( repository_dict )
# Set up nose to run the generated uninstall method as a functional test.
test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
test_config.configure( sys.argv )
@@ -309,6 +316,25 @@
else:
return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
+def remove_generated_tests( app ):
+ # Delete any configured tool functional tests from the test_toolbox.__dict__, otherwise nose will find them
+ # and try to re-run the tests after uninstalling the repository, which will cause false failure reports,
+ # since the test data has been deleted from disk by now.
+ tests_to_delete = []
+ global test_toolbox
+ for key in test_toolbox.__dict__:
+ if key.startswith( 'TestForTool_' ):
+ log.info( 'Tool test found in test_toolbox, deleting: %s' % key )
+ # We can't delete this test just yet, we're still iterating over __dict__.
+ tests_to_delete.append( key )
+ tool_id = key.replace( 'TestForTool_', '' )
+ if tool_id in app.toolbox.tools_by_id:
+ # But we can remove the relevant tool from app.toolbox.tools_by_id.
+ del app.toolbox.tools_by_id[ tool_id ]
+ for key in tests_to_delete:
+ # Now delete the tests found in the previous loop.
+ del test_toolbox.__dict__[ key ]
+
def run_tests( test_config ):
loader = nose.loader.TestLoader( config=test_config )
test_config.plugins.addPlugin( ReportResults() )
@@ -417,12 +443,12 @@
global_conf = { '__file__' : 'universe_wsgi.ini.sample' }
if not database_connection.startswith( 'sqlite://' ):
kwargs[ 'database_engine_option_max_overflow' ] = '20'
+ kwargs[ 'database_engine_option_pool_size' ] = '10'
app = UniverseApplication( admin_users = 'test(a)bx.psu.edu',
allow_user_creation = True,
allow_user_deletion = True,
allow_library_path_paste = True,
database_connection = database_connection,
- database_engine_option_pool_size = '10',
datatype_converters_config_file = "datatype_converters_conf.xml.sample",
file_path = galaxy_file_path,
global_conf = global_conf,
@@ -546,7 +572,14 @@
# it will record the result of the tests, and if any failed, the traceback and captured output of the tool that was run.
# After all tests have completed, the repository is uninstalled, so that the previous test cases don't interfere with
# the next repository's functional tests.
+ keep_skipping = True
for repository_info_dict in detailed_repository_list:
+ if repository_info_dict[ 'name' ] == 'simsearch' and repository_info_dict[ 'changeset_revision' ] == '430f55978191':
+ keep_skipping = False
+ if keep_skipping:
+ continue
+ if repository_info_dict[ 'name' ] == 'sortmerna':
+ continue
"""
Each repository_info_dict looks something like:
{
@@ -575,10 +608,13 @@
metadata_revision_id = repository_info_dict.get( 'id', None )
# Add the URL for the tool shed we're installing from, so the automated installation methods go to the right place.
repository_info_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
- log.info( "Installing and testing revision %s of repository id %s..." % ( str( changeset_revision ), str( repository_id ) ) )
# Get the name and owner out of the repository info dict.
- name = repository_info_dict[ 'name' ]
- owner = repository_info_dict[ 'owner' ]
+ name = str( repository_info_dict[ 'name' ] )
+ owner = str( repository_info_dict[ 'owner' ] )
+ log.info( "Installing and testing revision %s of repository id %s (%s/%s)..." % \
+ ( str( changeset_revision ), str( repository_id ), owner, name ) )
+ # Explicitly clear tests from twill's test environment.
+ remove_generated_tests( app )
# Use the repository information dict to generate an install method that will install the repository into the embedded
# Galaxy application, with tool dependencies and repository dependencies, if any.
test_install_repositories.generate_install_method( repository_info_dict )
@@ -661,7 +697,7 @@
register_test_result( galaxy_tool_shed_url, metadata_revision_id, repository_status, passed_tests=False )
# Run the cleanup method. This removes tool functional test methods from the test_toolbox module and uninstalls the
# repository using Twill.
- execute_uninstall_method( repository_info_dict )
+ execute_uninstall_method( app )
# Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
test_toolbox.toolbox = app.toolbox
repositories_failed.append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
@@ -675,6 +711,8 @@
os.environ[ 'GALAXY_TOOL_SHED_TEST_FILE' ] = galaxy_shed_tools_dict
os.environ[ 'GALAXY_TEST_HOST' ] = galaxy_test_host
os.environ[ 'GALAXY_TEST_PORT' ] = galaxy_test_port
+ # Explicitly clear tests from twill's test environment.
+ remove_generated_tests( app )
# Set the module-level variable 'toolbox', so that test.functional.test_toolbox will generate the appropriate test methods.
test_toolbox.toolbox = app.toolbox
# Generate the test methods for this installed repository. We need to pass in True here, or it will look
@@ -751,14 +789,23 @@
register_test_result( galaxy_tool_shed_url, metadata_revision_id, repository_status, passed_tests=False )
log.debug( 'Revision %s of repository %s installed successfully, but did not pass functional tests.' % \
( changeset_revision, name ) )
- # Run the cleanup method. This removes tool functional test methods from the test_toolbox module and uninstalls the
+ # Run the uninstall method. This removes tool functional test methods from the test_toolbox module and uninstalls the
# repository using Twill.
- success = execute_uninstall_method( repository_info_dict )
+ log.debug( 'Uninstalling changeset revision %s of repository %s' % \
+ ( repository_info_dict[ 'changeset_revision' ], repository_info_dict[ 'name' ] ) )
+ success = execute_uninstall_method( app )
+ if not success:
+ log.error( 'Repository %s failed to uninstall.' )
# Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
test_toolbox.toolbox = app.toolbox
else:
+ # Even if the repository failed to install, execute the uninstall method, in case a dependency did succeed.
+ log.debug( 'Uninstalling repository %s' % repository_info_dict[ 'name' ] )
+ success = execute_uninstall_method( app )
+ if not success:
+ log.error( 'Repository %s failed to uninstall.' )
repositories_failed_install.append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
- log.debug( 'Repository %s failed to install correctly.' % name )
+ log.debug( 'Repository %s failed to install correctly.' % repository_info_dict[ 'name' ] )
except:
log.exception( "Failure running tests" )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Make sure dependent eggs are loaded for sqlalchemy-migrate, regardless of entry point. This is a hack, and dependency management should/will eventually handle it.
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e5577cd833ab/
Changeset: e5577cd833ab
User: dannon
Date: 2013-05-03 18:55:55
Summary: Make sure dependent eggs are loaded for sqlalchemy-migrate, regardless of entry point. This is a hack, and dependency management should/will eventually handle it.
Affected #: 4 files
diff -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 -r e5577cd833abbd0ad072d55f4b56d1458105991b lib/galaxy/webapps/tool_shed/model/migrate/check.py
--- a/lib/galaxy/webapps/tool_shed/model/migrate/check.py
+++ b/lib/galaxy/webapps/tool_shed/model/migrate/check.py
@@ -3,6 +3,7 @@
from galaxy import eggs
import pkg_resources
+pkg_resources.require( "SQLAlchemy" )
pkg_resources.require( "decorator" )
pkg_resources.require( "sqlalchemy-migrate" )
pkg_resources.require( "Tempita" )
diff -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 -r e5577cd833abbd0ad072d55f4b56d1458105991b lib/tool_shed/galaxy_install/migrate/check.py
--- a/lib/tool_shed/galaxy_install/migrate/check.py
+++ b/lib/tool_shed/galaxy_install/migrate/check.py
@@ -1,7 +1,9 @@
import sys, os, logging, subprocess
from galaxy import eggs
import pkg_resources
+pkg_resources.require( "SQLAlchemy" )
pkg_resources.require( "decorator" )
+pkg_resources.require( "Tempita " )
pkg_resources.require( "sqlalchemy-migrate" )
from migrate.versioning import repository, schema
diff -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 -r e5577cd833abbd0ad072d55f4b56d1458105991b scripts/db_shell.py
--- a/scripts/db_shell.py
+++ b/scripts/db_shell.py
@@ -20,6 +20,7 @@
import pkg_resources
pkg_resources.require( "decorator" )
+pkg_resources.require( "Tempita" )
pkg_resources.require( "sqlalchemy-migrate" )
pkg_resources.require( "SQLAlchemy" )
diff -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 -r e5577cd833abbd0ad072d55f4b56d1458105991b scripts/manage_tools.py
--- a/scripts/manage_tools.py
+++ b/scripts/manage_tools.py
@@ -7,7 +7,9 @@
from galaxy import eggs
import pkg_resources
+pkg_resources.require( "SQLAlchemy" )
pkg_resources.require( "decorator" )
+pkg_resources.require( "Tempita " )
pkg_resources.require( "sqlalchemy-migrate" )
from migrate.versioning.shell import main
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Require decorator egg wherever we have sqlalchemy-migrate. Should be able to resolve dependencies and do this automatically
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5aec1f220d4f/
Changeset: 5aec1f220d4f
User: dannon
Date: 2013-05-03 18:31:20
Summary: Require decorator egg wherever we have sqlalchemy-migrate. Should be able to resolve dependencies and do this automatically
Affected #: 4 files
diff -r b908c9fa3c46f1b625a6d32d991392380c79685a -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 lib/galaxy/webapps/tool_shed/model/migrate/check.py
--- a/lib/galaxy/webapps/tool_shed/model/migrate/check.py
+++ b/lib/galaxy/webapps/tool_shed/model/migrate/check.py
@@ -3,6 +3,7 @@
from galaxy import eggs
import pkg_resources
+pkg_resources.require( "decorator" )
pkg_resources.require( "sqlalchemy-migrate" )
pkg_resources.require( "Tempita" )
diff -r b908c9fa3c46f1b625a6d32d991392380c79685a -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 lib/tool_shed/galaxy_install/migrate/check.py
--- a/lib/tool_shed/galaxy_install/migrate/check.py
+++ b/lib/tool_shed/galaxy_install/migrate/check.py
@@ -1,6 +1,7 @@
import sys, os, logging, subprocess
from galaxy import eggs
import pkg_resources
+pkg_resources.require( "decorator" )
pkg_resources.require( "sqlalchemy-migrate" )
from migrate.versioning import repository, schema
diff -r b908c9fa3c46f1b625a6d32d991392380c79685a -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 scripts/db_shell.py
--- a/scripts/db_shell.py
+++ b/scripts/db_shell.py
@@ -19,6 +19,7 @@
from galaxy import eggs
import pkg_resources
+pkg_resources.require( "decorator" )
pkg_resources.require( "sqlalchemy-migrate" )
pkg_resources.require( "SQLAlchemy" )
diff -r b908c9fa3c46f1b625a6d32d991392380c79685a -r 5aec1f220d4f1bccc9ac3f2b014d2727e0f0f907 scripts/manage_tools.py
--- a/scripts/manage_tools.py
+++ b/scripts/manage_tools.py
@@ -7,6 +7,7 @@
from galaxy import eggs
import pkg_resources
+pkg_resources.require( "decorator" )
pkg_resources.require( "sqlalchemy-migrate" )
from migrate.versioning.shell import main
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Require decorator egg in migrate/check to prevent sqlalchemy-migrate from dying in certain environments
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b908c9fa3c46/
Changeset: b908c9fa3c46
User: dannon
Date: 2013-05-03 18:26:40
Summary: Require decorator egg in migrate/check to prevent sqlalchemy-migrate from dying in certain environments
Affected #: 1 file
diff -r 4d4d8dd42491a81869642f1cfcb2f552e4af5a40 -r b908c9fa3c46f1b625a6d32d991392380c79685a lib/galaxy/model/migrate/check.py
--- a/lib/galaxy/model/migrate/check.py
+++ b/lib/galaxy/model/migrate/check.py
@@ -4,6 +4,7 @@
from galaxy import eggs
eggs.require( "SQLAlchemy" )
+eggs.require( "decorator" ) #Required by sqlalchemy-migrate
eggs.require( "Tempita " ) #Required by sqlalchemy-migrate
eggs.require( "sqlalchemy-migrate" )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Column cleanup in the repositories grid in the tool shed.
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4d4d8dd42491/
Changeset: 4d4d8dd42491
User: greg
Date: 2013-05-03 17:26:12
Summary: Column cleanup in the repositories grid in the tool shed.
Affected #: 2 files
diff -r 4a1a2b6b4e8a14db4a7689ef09b8a2db965ddc8f -r 4d4d8dd42491a81869642f1cfcb2f552e4af5a40 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -95,7 +95,9 @@
kwd[ 'id' ] = trans.security.encode_id( repository.id )
except:
pass
- return self.browse_repositories( trans, **kwd )
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repositories',
+ **kwd ) )
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
if operation in [ "repositories_by_category", "repositories_by_user" ]:
diff -r 4a1a2b6b4e8a14db4a7689ef09b8a2db965ddc8f -r 4d4d8dd42491a81869642f1cfcb2f552e4af5a40 lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -211,11 +211,7 @@
key="description",
attach_popup=False ),
MetadataRevisionColumn( "Metadata Revisions" ),
- TipRevisionColumn( "Tip Revision" ),
- CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False ),
+ ToolsFunctionallyCorrectColumn( "Tools Verified" ),
UserColumn( "Owner",
model_class=model.User,
link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fixes for rendering the Repository Actions menu in the tool shed.
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4a1a2b6b4e8a/
Changeset: 4a1a2b6b4e8a
User: greg
Date: 2013-05-03 17:10:45
Summary: Fixes for rendering the Repository Actions menu in the tool shed.
Affected #: 2 files
diff -r 15329256872bf03a3831bc5e3a970cbe8611a3fe -r 4a1a2b6b4e8a14db4a7689ef09b8a2db965ddc8f templates/webapps/tool_shed/common/repository_actions_menu.mako
--- a/templates/webapps/tool_shed/common/repository_actions_menu.mako
+++ b/templates/webapps/tool_shed/common/repository_actions_menu.mako
@@ -5,19 +5,55 @@
from tool_shed.util.review_util import can_browse_repository_reviews, changeset_revision_reviewed_by_user, get_review_by_repository_id_changeset_revision_user_id
from tool_shed.util.shed_util_common import changeset_is_malicious
- has_metadata = repository.metadata_revisions
- has_readme = metadata and 'readme' in metadata
+ if repository.metadata_revisions:
+ has_metadata = True
+ else:
+ has_metadata = False
+
is_admin = trans.user_is_admin()
- is_deprecated = repository.deprecated
- is_new = repository.is_new( trans.app )
- is_malicious = changeset_is_malicious( trans, trans.security.encode_id( repository.id ), repository.tip( trans.app ) )
+
+ if repository.deprecated:
+ is_deprecated = True
+ else:
+ is_deprecated = False
+
+ if repository.is_new( trans.app ):
+ is_new = True
+ else:
+ is_new = False
+
+ if changeset_is_malicious( trans, trans.security.encode_id( repository.id ), repository.tip( trans.app ) ):
+ is_malicious = True
+ else:
+ is_malicious = False
can_browse_contents = not is_new
- can_browse_reviews = can_browse_repository_reviews( trans, repository )
- can_contact_owner = trans.user and trans.user != repository.user
- can_deprecate = not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated
- can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_download = not is_deprecated and not is_new and ( not is_malicious or can_push )
+
+ if can_browse_repository_reviews( trans, repository ):
+ can_browse_reviews = True
+ else:
+ can_browse_reviews = False
+
+ if trans.user and trans.user != repository.user:
+ can_contact_owner = True
+ else:
+ can_contact_owner = False
+
+ if not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated:
+ can_deprecate = True
+ else:
+ can_deprecate = False
+
+ if not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository ):
+ can_push = True
+ else:
+ can_push = False
+
+ if not is_deprecated and not is_new and ( not is_malicious or can_push ):
+ can_download = True
+ else:
+ can_download = False
+
if not is_deprecated:
if repo and len( repo ) > 0:
can_reset_all_metadata = True
@@ -25,16 +61,30 @@
can_reset_all_metadata = False
else:
can_reset_all_metadata = False
- can_upload = can_push and not is_deprecated
- can_rate = not is_new and not is_deprecated and trans.user and repository.user != trans.user
- if changeset_revision:
- can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
- reviewed_by_user = changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
+
+ if can_push and not is_deprecated:
+ can_upload = True
+ else:
+ can_upload = False
+
+ if not is_new and not is_deprecated and trans.user and repository.user != trans.user:
+ can_rate = True
+ else:
+ can_rate = False
+
+ if changeset_revision is not None:
+ if has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ):
+ can_review_repository = True
+ else:
+ can_review_repository = False
+ if changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision ):
+ reviewed_by_user = True
+ else:
+ reviewed_by_user = False
else:
can_review_repository = False
reviewed_by_user = False
- # Determine if the current changeset revision has been reviewed by the current user.
if reviewed_by_user:
review = get_review_by_repository_id_changeset_revision_user_id( trans=trans,
repository_id=trans.security.encode_id( repository.id ),
@@ -44,17 +94,29 @@
else:
review_id = None
- can_set_metadata = not is_new and not is_deprecated
- if changeset_revision:
+ if not is_new and not is_deprecated:
+ can_set_metadata = True
+ else:
+ can_set_metadata = False
+
+ if changeset_revision is not None:
if changeset_revision == repository.tip( trans.app ):
changeset_revision_is_repository_tip = True
else:
changeset_revision_is_repository_tip = False
else:
changeset_revision_is_repository_tip = False
- can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision_is_repository_tip
- can_undeprecate = trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated
- can_manage = is_admin or repository.user == trans.user
+
+ if trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated:
+ can_undeprecate = True
+ else:
+ can_undeprecate = False
+
+ if is_admin or repository.user == trans.user:
+ can_manage = True
+ else:
+ can_manage = False
+
can_view_change_log = not is_new
if can_push:
@@ -69,6 +131,9 @@
%if can_upload:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
%endif
+ %if can_undeprecate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=False )}">Mark repository as not deprecated</a>
+ %endif
%else:
<li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup">
diff -r 15329256872bf03a3831bc5e3a970cbe8611a3fe -r 4a1a2b6b4e8a14db4a7689ef09b8a2db965ddc8f templates/webapps/tool_shed/repository/manage_repository.mako
--- a/templates/webapps/tool_shed/repository/manage_repository.mako
+++ b/templates/webapps/tool_shed/repository/manage_repository.mako
@@ -6,19 +6,56 @@
<%
from galaxy.web.framework.helpers import time_ago
+ from tool_shed.util.shed_util_common import changeset_is_malicious
- has_metadata = repository.metadata_revisions
- has_readme = metadata and 'readme' in metadata
+ if repository.metadata_revisions:
+ has_metadata = True
+ else:
+ has_metadata = False
+
is_admin = trans.user_is_admin()
is_new = repository.is_new( trans.app )
- is_deprecated = repository.deprecated
- can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_download = not is_deprecated and not is_new and ( not is_malicious or can_push )
- can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
- can_set_metadata = not is_new and not is_deprecated
- changeset_revision_is_repository_tip = changeset_revision == repository.tip( trans.app )
- can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision_is_repository_tip
+ if repository.deprecated:
+ is_deprecated = True
+ else:
+ is_deprecated = False
+
+ if changeset_is_malicious( trans, trans.security.encode_id( repository.id ), repository.tip( trans.app ) ):
+ is_malicious = True
+ else:
+ is_malicious = False
+
+ if not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository ):
+ can_push = True
+ else:
+ can_push = False
+
+ if not is_deprecated and not is_new and ( not is_malicious or can_push ):
+ can_download = True
+ else:
+ can_download = False
+
+ if has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ):
+ can_review_repository = True
+ else:
+ can_review_repository = False
+
+ if not is_new and not is_deprecated:
+ can_set_metadata = True
+ else:
+ can_set_metadata = False
+
+ if changeset_revision == repository.tip( trans.app ):
+ changeset_revision_is_repository_tip = True
+ else:
+ changeset_revision_is_repository_tip = False
+
+ if metadata and can_set_metadata and is_admin and changeset_revision_is_repository_tip:
+ can_set_malicious = True
+ else:
+ can_set_malicious = False
+
can_view_change_log = not is_new
if changeset_revision_is_repository_tip:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: only query feature tracks for feature locations.
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/15329256872b/
Changeset: 15329256872b
User: jgoecks
Date: 2013-05-03 16:52:11
Summary: Trackster: only query feature tracks for feature locations.
Affected #: 1 file
diff -r cf2db2f91c7f4ca284daea800aa9596c27ff809b -r 15329256872bf03a3831bc5e3a970cbe8611a3fe static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -438,6 +438,7 @@
this.obj_type = obj_dict.obj_type;
this.drawables = [];
};
+
extend(DrawableCollection.prototype, Drawable.prototype, {
/**
* Unpack and add drawables to the collection.
@@ -560,6 +561,26 @@
*/
get_drawables: function() {
return this.drawables;
+ },
+
+ /**
+ * Returns all <track_type> tracks in collection.
+ */
+ get_tracks: function(track_type) {
+ // Initialize queue with copy of drawables array.
+ var queue = this.drawables.slice(0),
+ tracks = [],
+ drawable;
+ while (queue.length !== 0) {
+ drawable = queue.shift();
+ if (drawable instanceof track_type) {
+ tracks.push(drawable);
+ }
+ else if (drawable.drawables) {
+ queue = queue.concat(drawable.drawables);
+ }
+ }
+ return tracks;
}
});
@@ -967,8 +988,8 @@
source: function(request, response) {
// Using current text, query each track and create list of all matching features.
var all_features = [],
- feature_search_deferreds = $.map(view.get_drawables(), function(drawable) {
- return drawable.data_manager.search_features(request.term).success(function(dataset_features) {
+ feature_search_deferreds = $.map(view.get_tracks(FeatureTrack), function(t) {
+ return t.data_manager.search_features(request.term).success(function(dataset_features) {
all_features = all_features.concat(dataset_features);
});
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Do not allow deleted datasets to be displayed.
by commits-noreply@bitbucket.org 03 May '13
by commits-noreply@bitbucket.org 03 May '13
03 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cf2db2f91c7f/
Changeset: cf2db2f91c7f
User: dan
Date: 2013-05-03 16:38:16
Summary: Do not allow deleted datasets to be displayed.
Affected #: 1 file
diff -r af7b3b73130b9288112fd06d2cecbcfe649703c5 -r cf2db2f91c7f4ca284daea800aa9596c27ff809b lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -290,6 +290,8 @@
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( hda_id ) )
if not self._can_access_dataset( trans, data ):
return trans.show_error_message( "You are not allowed to access this dataset" )
+ if data.deleted:
+ return trans.show_error_message( "The dataset you are attempting to view has been deleted." )
if data.state == trans.model.Dataset.states.UPLOAD:
return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." )
return data
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/259865426c21/
Changeset: 259865426c21
Branch: stable
User: dannon
Date: 2013-04-17 03:38:38
Summary: Disable select2 for Input Dataset steps on the run workflow page.
Affected #: 1 file
diff -r 47ddf167c9f11c903a438c0979e101fe7535f061 -r 259865426c21fbfcfdcf4f8279487fee86ad1736 templates/webapps/galaxy/workflow/run.mako
--- a/templates/webapps/galaxy/workflow/run.mako
+++ b/templates/webapps/galaxy/workflow/run.mako
@@ -40,12 +40,12 @@
select.val($('option:last', select).val());
}
select.closest('.form-row').children('label').children('span.mode-icon').hide();
- select.removeAttr('multiple').refresh_select2().removeAttr('size');
+ select.removeAttr('multiple').removeAttr('size');
placeholder = 'type to filter';
} else {
$('.multiinput', select.closest('.form-row')).removeClass('disabled');
select.closest('.form-row').children('label').children('span.mode-icon').show();
- select.attr('multiple', 'multiple').refresh_select2().attr('size', 8);
+ select.attr('multiple', 'multiple').attr('size', 8);
placeholder = 'type to filter, [enter] to select all';
}
$('input.multiinput-filter', select.parent()).attr(
@@ -79,7 +79,10 @@
$("#new_history_cbx").click(function(){
$("#new_history_input").toggle(this.checked);
});
- $('span.multiinput_wrap select[name*="|input"]').removeAttr('multiple').refresh_select2().each(function(i, s) {
+ // The destroy on the following line is temporary and prevents
+ // select2 use on Input Dataset Steps, but allows elsewhere. We
+ // need a new widget to better handle pairwise matching.
+ $('span.multiinput_wrap select[name*="|input"]').removeAttr('multiple').select2("destroy").each(function(i, s) {
var select = $(s);
var new_width = Math.max(200, select.width()) + 20;
// Find the label for this element.
https://bitbucket.org/galaxy/galaxy-central/commits/b22d70ad9404/
Changeset: b22d70ad9404
Branch: stable
User: dannon
Date: 2013-04-17 03:47:17
Summary: Update multiselect tooltip, now functional. Was still using tipsy's 'original-title' attribute.
Affected #: 1 file
diff -r 259865426c21fbfcfdcf4f8279487fee86ad1736 -r b22d70ad94044a8cadf32e49385f414e60459e9d templates/webapps/galaxy/workflow/run.mako
--- a/templates/webapps/galaxy/workflow/run.mako
+++ b/templates/webapps/galaxy/workflow/run.mako
@@ -91,7 +91,7 @@
if ($(this).hasClass('disabled')) return;
toggle_multiinput(select);
select.focus();
- }).attr('original-title',
+ }).attr('title',
'Enable/disable selection of multiple input ' +
'files. Each selected file will have an ' +
'instance of the workflow.').tooltip({placement: 'bottom'})
https://bitbucket.org/galaxy/galaxy-central/commits/fe1be67c576a/
Changeset: fe1be67c576a
Branch: stable
User: dannon
Date: 2013-04-17 04:27:07
Summary: Add tooltips for (un)linking icon on run workflow page.
Affected #: 1 file
diff -r b22d70ad94044a8cadf32e49385f414e60459e9d -r fe1be67c576af3bc6890912b63863694b9eceb8c templates/webapps/galaxy/workflow/run.mako
--- a/templates/webapps/galaxy/workflow/run.mako
+++ b/templates/webapps/galaxy/workflow/run.mako
@@ -141,13 +141,15 @@
$(function(){
$(".multi-mode").each(function(){
if($(this).val() == "matched") {
- $(this).closest('.form-row').children('label').append($('<span class="icon-button link mode-icon"></span>')
+ $(this).closest('.form-row').children('label').append($('<span class="icon-button link mode-icon" title="This input is linked and will be run in matched order with other input datasets (ex: use this for matching forward and reverse reads)."></span>')
.attr({id:$(this).attr("id")})
- .css("display", $(this).css("display")));
+ .css("display", $(this).css("display"))
+ .tooltip({placement: 'bottom'}));
} else {
- $(this).closest('.form-row').children('label').append($('<span class="icon-button link-broken mode-icon"></span>')
+ $(this).closest('.form-row').children('label').append($('<span class="icon-button link-broken mode-icon" title="This input is not linked and each selection will be run against *all* other inputs."></span>')
.attr({id:$(this).attr("id")})
- .css("display", $(this).css("display")));
+ .css("display", $(this).css("display"))
+ .tooltip({placement: 'bottom'}));
}
});
$("span.mode-icon").click(function(){
https://bitbucket.org/galaxy/galaxy-central/commits/0899ad383fba/
Changeset: 0899ad383fba
Branch: stable
User: dannon
Date: 2013-04-17 14:40:24
Summary: Fix more broken tooltips from the tipsy->bootstrap.tooltip() swap
Affected #: 1 file
diff -r fe1be67c576af3bc6890912b63863694b9eceb8c -r 0899ad383fba01c78077a3dfddb954bebaf6e72e templates/webapps/galaxy/workflow/editor.mako
--- a/templates/webapps/galaxy/workflow/editor.mako
+++ b/templates/webapps/galaxy/workflow/editor.mako
@@ -1015,7 +1015,7 @@
## Workflow name.
<div id="workflow-name-area" class="form-row"><label>Name:</label>
- <span id="workflow-name" class="tooltip editable-text" original-title="Click to rename workflow">${h.to_unicode( stored.name ) | h}</span>
+ <span id="workflow-name" class="tooltip editable-text" title="Click to rename workflow">${h.to_unicode( stored.name ) | h}</span></div>
## Workflow tags.
<%namespace file="/tagging_common.mako" import="render_individual_tagging_element" />
@@ -1037,7 +1037,7 @@
## Annotation elt.
<div id="workflow-annotation-area" class="form-row"><label>Annotation / Notes:</label>
- <div id="workflow-annotation" class="tooltip editable-text" original-title="Click to edit annotation">
+ <div id="workflow-annotation" class="tooltip editable-text" title="Click to edit annotation">
%if annotation:
${h.to_unicode( annotation ) | h}
%else:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix tool shed functional test I broke.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/af7b3b73130b/
Changeset: af7b3b73130b
User: greg
Date: 2013-05-02 22:44:49
Summary: Fix tool shed functional test I broke.
Affected #: 1 file
diff -r 1528410bbe976f425df16de8ee81c49c5a0432da -r af7b3b73130b9288112fd06d2cecbcfe649703c5 test/tool_shed/functional/test_0000_basic_repository_features.py
--- a/test/tool_shed/functional/test_0000_basic_repository_features.py
+++ b/test/tool_shed/functional/test_0000_basic_repository_features.py
@@ -99,7 +99,7 @@
tool_metadata_strings_displayed=tool_metadata_strings_displayed,
tool_page_strings_displayed=tool_page_strings_displayed )
self.check_repository_metadata( repository, tip_only=False )
- self.browse_repository( repository, strings_displayed=[ 'Browse %s revision' % repository.name, '(repository tip)' ] )
+ self.browse_repository( repository, strings_displayed=[ "Repository '%s' revision" % repository.name, '(repository tip)' ] )
self.display_repository_clone_page( common.test_user_1_name,
repository_name,
strings_displayed=[ 'Uploaded filtering 1.1.0', latest_changeset_revision ] )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Delete/stop jobs when a history is deleted.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1528410bbe97/
Changeset: 1528410bbe97
User: natefoo
Date: 2013-05-02 21:50:00
Summary: Delete/stop jobs when a history is deleted.
Affected #: 1 file
diff -r 3044a594eef9868f41d90b43f1c993def91abe9e -r 1528410bbe976f425df16de8ee81c49c5a0432da lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -562,6 +562,12 @@
history.purged = True
self.sa_session.add( history )
self.sa_session.flush()
+ for hda in history.datasets:
+ job = hda.creating_job_associations[0].job
+ if job.history_id == history.id and job.state in [ trans.app.model.Job.states.QUEUED, trans.app.model.Job.states.RUNNING, trans.app.model.Job.states.NEW ]:
+ # No need to check other outputs since the job's parent history is this history
+ job.mark_deleted( trans.app.config.track_jobs_in_database )
+ trans.app.job_manager.job_stop_queue.put( job.id )
# Regardless of whether it was previously deleted, we make a new history active
trans.new_history()
return trans.show_ok_message( "History deleted, a new history is active", refresh_frames=['history'] )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Display error to user when genomespace file browser tool is used with no imported datasets.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3044a594eef9/
Changeset: 3044a594eef9
User: dan
Date: 2013-05-02 21:46:06
Summary: Display error to user when genomespace file browser tool is used with no imported datasets.
Affected #: 1 file
diff -r 8d8368ab03ff95c2aa88861ed0284cf48ca73631 -r 3044a594eef9868f41d90b43f1c993def91abe9e tools/genomespace/genomespace_file_browser.py
--- a/tools/genomespace/genomespace_file_browser.py
+++ b/tools/genomespace/genomespace_file_browser.py
@@ -113,6 +113,10 @@
if name.startswith( file_url_prefix ):
name = name[len( file_url_prefix ):]
file_numbers.append( int( name ) )
+ if not file_numbers:
+ if output_filename:
+ open( output_filename, 'wb' ) #erase contents of file
+ raise Exception( "You must select at least one file to import into Galaxy." )
file_numbers.sort()
used_filenames = []
for file_num in file_numbers:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Re-add the ability to preview and install repositories from the Valid repositories grid in the tool shed.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8d8368ab03ff/
Changeset: 8d8368ab03ff
User: greg
Date: 2013-05-02 21:44:05
Summary: Re-add the ability to preview and install repositories from the Valid repositories grid in the tool shed.
Affected #: 1 file
diff -r d2a4a4e4165058439ad0ffb09003f8d57a19233e -r 8d8368ab03ff95c2aa88861ed0284cf48ca73631 lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -1424,7 +1424,7 @@
columns = [
RepositoryGrid.NameColumn( "Name",
key="name",
- attach_popup=False ),
+ attach_popup=True ),
RepositoryGrid.DescriptionColumn( "Synopsis",
key="description",
attach_popup=False ),
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
64 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d128613ae7c9/
Changeset: d128613ae7c9
User: dannon
Date: 2013-04-18 21:35:00
Summary: Postgres migrations successful, model updated
Affected #: 145 files
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 eggs.ini
--- a/eggs.ini
+++ b/eggs.ini
@@ -28,6 +28,7 @@
simplejson = 2.1.1
threadframe = 0.2
guppy = 0.1.8
+SQLAlchemy = 0.7.9
; msgpack_python = 0.2.4
[eggs:noplatform]
@@ -52,11 +53,10 @@
python_openid = 2.2.5
python_daemon = 1.5.5
Routes = 1.12.3
-SQLAlchemy = 0.5.6
-sqlalchemy_migrate = 0.5.4
+sqlalchemy_migrate = 0.7.2
ssh = 1.7.14
SVGFig = 1.1.6
-Tempita = 0.1
+Tempita = 0.5.1
twill = 0.9
WebError = 0.8a
WebHelpers = 0.2
@@ -75,7 +75,6 @@
MySQL_python = _5.1.41_static
bx_python = _7b95ff194725
GeneTrack = _dev_48da9e998f0caf01c5be731e926f4b0481f658f0
-SQLAlchemy = _dev_r6498
pysam = _kanwei_b10f6e722e9a
; dependency source urls, necessary for scrambling. for an explanation, see
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/datatypes/assembly.py
--- a/lib/galaxy/datatypes/assembly.py
+++ b/lib/galaxy/datatypes/assembly.py
@@ -5,14 +5,14 @@
"""
import data
+import logging
+import os
+import re
+import sys
from galaxy.datatypes import sequence
-import logging, os, sys, time, tempfile, shutil, string, glob, re
-import galaxy.model
-from galaxy.datatypes import metadata
+from galaxy.datatypes.images import Html
from galaxy.datatypes.metadata import MetadataElement
-from galaxy import util
-from galaxy.datatypes.images import Html
-from sniff import *
+
log = logging.getLogger(__name__)
@@ -174,7 +174,6 @@
gen_msg = ''
try:
efp = dataset.extra_files_path
- flist = os.listdir(efp)
log_path = os.path.join(efp,'Log')
f = open(log_path,'r')
log_content = f.read(1000)
@@ -223,5 +222,5 @@
self.regenerate_primary_file(dataset)
if __name__ == '__main__':
- import doctest, sys
+ import doctest
doctest.testmod(sys.modules[__name__])
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -2,18 +2,25 @@
Binary classes
"""
-import data, logging, binascii
+
+import binascii
+import data
+import gzip
+import logging
+import os
+import shutil
+import struct
+import subprocess
+import tempfile
+
+from galaxy import eggs
+eggs.require( "bx-python" )
+
+from bx.seq.twobit import TWOBIT_MAGIC_NUMBER, TWOBIT_MAGIC_NUMBER_SWAP, TWOBIT_MAGIC_SIZE
+
+from galaxy.datatypes import metadata
from galaxy.datatypes.metadata import MetadataElement
-from galaxy.datatypes import metadata
-from galaxy.datatypes.sniff import *
-from galaxy import eggs
-import pkg_resources
-pkg_resources.require( "bx-python" )
-from bx.seq.twobit import TWOBIT_MAGIC_NUMBER, TWOBIT_MAGIC_NUMBER_SWAP, TWOBIT_MAGIC_SIZE
-from urllib import urlencode, quote_plus
-import zipfile, gzip
-import os, subprocess, tempfile
-import struct
+
log = logging.getLogger(__name__)
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/datatypes/chrominfo.py
--- a/lib/galaxy/datatypes/chrominfo.py
+++ b/lib/galaxy/datatypes/chrominfo.py
@@ -1,7 +1,3 @@
-import data
-from galaxy import util
-from galaxy.datatypes.sniff import *
-from galaxy.web import url_for
from tabular import Tabular
from galaxy.datatypes import metadata
from galaxy.datatypes.metadata import MetadataElement
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/datatypes/coverage.py
--- a/lib/galaxy/datatypes/coverage.py
+++ b/lib/galaxy/datatypes/coverage.py
@@ -2,21 +2,14 @@
Coverage datatypes
"""
-import pkg_resources
-pkg_resources.require( "bx-python" )
-import logging, os, sys, time, tempfile, shutil
-import data
-from galaxy import util
-from galaxy.datatypes.sniff import *
-from galaxy.web import url_for
-from cgi import escape
-import urllib
-from bx.intervals.io import *
+import logging
+import math
+
+from galaxy import eggs
from galaxy.datatypes import metadata
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes.tabular import Tabular
-import math
log = logging.getLogger(__name__)
@@ -34,7 +27,7 @@
Assumes we have a numpy file.
"""
# Maybe if we import here people will still be able to use Galaxy when numpy kills it
- pkg_resources.require("numpy>=1.2.1")
+ eggs.require("numpy>=1.2.1")
#from numpy.lib import format
import numpy
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/datatypes/metadata.py
--- a/lib/galaxy/datatypes/metadata.py
+++ b/lib/galaxy/datatypes/metadata.py
@@ -1,17 +1,30 @@
-import sys, logging, copy, shutil, weakref, cPickle, tempfile, os
+"""
+Galaxy Metadata
+
+"""
+from galaxy import eggs
+eggs.require("simplejson")
+
+
+import copy
+import cPickle
+import logging
+import os
+import shutil
+import simplejson
+import sys
+import tempfile
+import weakref
+
from os.path import abspath
-from galaxy.util import string_as_bool, stringify_dictionary_keys, listify
+import galaxy.model
+from galaxy.util import listify, stringify_dictionary_keys, string_as_bool
from galaxy.util.odict import odict
from galaxy.web import form_builder
-import galaxy.model
from sqlalchemy.orm import object_session
-import pkg_resources
-pkg_resources.require("simplejson")
-import simplejson
-
-log = logging.getLogger( __name__ )
+log = logging.getLogger(__name__)
STATEMENTS = "__galaxy_statements__" #this is the name of the property in a Datatype class where new metadata spec element Statements are stored
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -4,6 +4,7 @@
import copy
import datetime
+import galaxy
import logging
import os
import pwd
@@ -14,17 +15,15 @@
import sys
import threading
import traceback
-
-import galaxy
-from galaxy import util, model
-from galaxy.util.bunch import Bunch
+from galaxy import model, util
from galaxy.datatypes import metadata
-from galaxy.util.json import from_json_string
-from galaxy.util.expressions import ExpressionContext
+from galaxy.exceptions import ObjectInvalid
from galaxy.jobs.actions.post import ActionBox
-from galaxy.exceptions import ObjectInvalid
from galaxy.jobs.mapper import JobRunnerMapper
from galaxy.jobs.runners import BaseJobRunner
+from galaxy.util.bunch import Bunch
+from galaxy.util.expressions import ExpressionContext
+from galaxy.util.json import from_json_string
log = logging.getLogger( __name__ )
@@ -917,7 +916,8 @@
return self.fail( "Job %s's output dataset(s) could not be read" % job.id )
job_context = ExpressionContext( dict( stdout = job.stdout, stderr = job.stderr ) )
-
+ #DBTODO unused
+ #job_tool = self.app.toolbox.tools_by_id.get( job.tool_id, None )
for dataset_assoc in job.output_datasets + job.output_library_datasets:
context = self.get_dataset_finish_context( job_context, dataset_assoc.dataset.dataset )
#should this also be checking library associations? - can a library item be added from a history before the job has ended? - lets not allow this to occur
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/jobs/actions/post.py
--- a/lib/galaxy/jobs/actions/post.py
+++ b/lib/galaxy/jobs/actions/post.py
@@ -1,4 +1,5 @@
-import logging, datetime
+import datetime
+import logging
from galaxy.util import send_mail
from galaxy.util.json import to_json_string
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/jobs/manager.py
--- a/lib/galaxy/jobs/manager.py
+++ b/lib/galaxy/jobs/manager.py
@@ -2,17 +2,16 @@
Top-level Galaxy job manager, moves jobs to handler(s)
"""
+import logging
import os
+import random
+import threading
import time
-import random
-import logging
-import threading
-from Queue import Queue, Empty
-from sqlalchemy.sql.expression import and_, or_
+from Queue import Empty, Queue
from galaxy import model
-from galaxy.jobs import handler, Sleeper, NoopQueue, JobWrapper
+from galaxy.jobs import handler, JobWrapper, NoopQueue, Sleeper
from galaxy.util.json import from_json_string
log = logging.getLogger( __name__ )
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -5,21 +5,32 @@
the relationship cardinalities are obvious (e.g. prefer Dataset to Data)
"""
-import pkg_resources
-pkg_resources.require("simplejson")
-pkg_resources.require("pexpect")
-import simplejson, os, errno, codecs, operator, socket, pexpect, logging, time
+from galaxy import eggs
+eggs.require("simplejson")
+eggs.require("pexpect")
+
+import codecs
+import errno
+import logging
+import operator
+import os
+import pexpect
+import simplejson
+import socket
+import time
+
import galaxy.datatypes
import galaxy.datatypes.registry
from galaxy.datatypes.metadata import MetadataCollection
+from galaxy.model.item_attrs import APIItem, UsesAnnotations
from galaxy.security import get_permitted_actions
-from galaxy import util
+from galaxy.util import is_multi_byte, nice_size, Params, restore_text, send_mail
from galaxy.util.bunch import Bunch
from galaxy.util.hash_util import new_secure_hash
from galaxy.web.framework.helpers import to_unicode
-from galaxy.web.form_builder import (AddressField, CheckboxField, PasswordField, SelectField, TextArea, TextField,
- WorkflowField, WorkflowMappingField, HistoryField)
-from galaxy.model.item_attrs import UsesAnnotations, APIItem
+from galaxy.web.form_builder import (AddressField, CheckboxField, HistoryField,
+ PasswordField, SelectField, TextArea, TextField, WorkflowField,
+ WorkflowMappingField)
from sqlalchemy.orm import object_session
from sqlalchemy.sql.expression import func
@@ -804,7 +815,7 @@
if self.bytes == -1:
return "unlimited"
else:
- return util.nice_size( self.bytes )
+ return nice_size( self.bytes )
class DefaultQuotaAssociation( Quota, APIItem ):
api_element_visible_keys = ( 'type', )
@@ -977,7 +988,7 @@
if not self.has_data():
return False
try:
- return util.is_multi_byte( codecs.open( self.file_name, 'r', 'utf-8' ).read( 100 ) )
+ return is_multi_byte( codecs.open( self.file_name, 'r', 'utf-8' ).read( 100 ) )
except UnicodeDecodeError:
return False
# FIXME: sqlalchemy will replace this
@@ -2275,7 +2286,7 @@
Return the list of widgets that comprise a form definition,
including field contents if any.
'''
- params = util.Params( kwd )
+ params = Params( kwd )
widgets = []
for index, field in enumerate( self.fields ):
field_type = field[ 'type' ]
@@ -2291,7 +2302,7 @@
if field_type == 'CheckboxField':
value = CheckboxField.is_checked( params.get( field_name, False ) )
else:
- value = util.restore_text( params.get( field_name, '' ) )
+ value = restore_text( params.get( field_name, '' ) )
elif contents:
try:
# This field has a saved value.
@@ -2506,7 +2517,7 @@
frm = 'galaxy-no-reply@' + host
subject = "Galaxy Sample Tracking notification: '%s' sequencing request" % self.name
try:
- util.send_mail( frm, to, subject, body, trans.app.config )
+ send_mail( frm, to, subject, body, trans.app.config )
comments = "Email notification sent to %s." % ", ".join( to ).strip().strip( ',' )
except Exception,e:
comments = "Email notification failed. (%s)" % str(e)
@@ -2548,7 +2559,7 @@
if data_transfer_protocol == self.data_transfer_protocol.SCP:
scp_configs = {}
automatic_transfer = data_transfer_obj.config.get( 'automatic_transfer', 'false' )
- scp_configs[ 'automatic_transfer' ] = util.string_as_bool( automatic_transfer )
+ scp_configs[ 'automatic_transfer' ] = galaxy.util.string_as_bool( automatic_transfer )
scp_configs[ 'host' ] = self.form_values.content.get( data_transfer_obj.config.get( 'host', '' ), '' )
scp_configs[ 'user_name' ] = self.form_values.content.get( data_transfer_obj.config.get( 'user_name', '' ), '' )
scp_configs[ 'password' ] = self.form_values.content.get( data_transfer_obj.config.get( 'password', '' ), '' )
@@ -2558,7 +2569,7 @@
if data_transfer_protocol == self.data_transfer_protocol.HTTP:
http_configs = {}
automatic_transfer = data_transfer_obj.config.get( 'automatic_transfer', 'false' )
- http_configs[ 'automatic_transfer' ] = util.string_as_bool( automatic_transfer )
+ http_configs[ 'automatic_transfer' ] = galaxy.util.string_as_bool( automatic_transfer )
self.data_transfer[ self.data_transfer_protocol.HTTP ] = http_configs
def populate_actions( self, trans, item, param_dict=None ):
return self.get_external_service_type( trans ).actions.populate( self, item, param_dict=param_dict )
diff -r c5c9a85e1bb88a609118d29d595e0136d44dff2a -r d128613ae7c9ef1387b749c7577a6631b649b048 lib/galaxy/model/custom_types.py
--- a/lib/galaxy/model/custom_types.py
+++ b/lib/galaxy/model/custom_types.py
@@ -11,9 +11,9 @@
from galaxy.util.aliaspickler import AliasPickleModule
# For monkeypatching BIGINT
-import sqlalchemy.databases.sqlite
-import sqlalchemy.databases.postgres
-import sqlalchemy.databases.mysql
+import sqlalchemy.dialects.sqlite
+import sqlalchemy.dialects.postgresql
+import sqlalchemy.dialects.mysql
import logging
log = logging.getLogger( __name__ )
@@ -39,7 +39,7 @@
Defines a JSONType for SQLAlchemy. Takes a primitive as input and
JSONifies it. This should replace PickleType throughout Galaxy.
"""
- impl = Binary
+ impl = LargeBinary
def process_bind_param( self, value, dialect ):
if value is None:
@@ -86,8 +86,6 @@
ret = None
return ret
-
-
class UUIDType(TypeDecorator):
"""
Platform-independent UUID type.
@@ -128,24 +126,24 @@
return value
-class BigInteger( Integer ):
- """
- A type for bigger ``int`` integers.
+#class BigInteger( Integer ):
+ #"""
+ #A type for bigger ``int`` integers.
- Typically generates a ``BIGINT`` in DDL, and otherwise acts like
- a normal :class:`Integer` on the Python side.
+ #Typically generates a ``BIGINT`` in DDL, and otherwise acts like
+ #a normal :class:`Integer` on the Python side.
- """
+ #"""
-class BIGINT( BigInteger ):
- """The SQL BIGINT type."""
+#class BIGINT( BigInteger ):
+ #"""The SQL BIGINT type."""
-class SLBigInteger( BigInteger ):
- def get_col_spec( self ):
- return "BIGINT"
+#class SLBigInteger( BigInteger ):
+ #def get_col_spec( self ):
+ #return "BIGINT"
-sqlalchemy.databases.sqlite.SLBigInteger = SLBigInteger
-sqlalchemy.databases.sqlite.colspecs[BigInteger] = SLBigInteger
-sqlalchemy.databases.sqlite.ischema_names['BIGINT'] = SLBigInteger
-sqlalchemy.databases.postgres.colspecs[BigInteger] = sqlalchemy.databases.postgres.PGBigInteger
-sqlalchemy.databases.mysql.colspecs[BigInteger] = sqlalchemy.databases.mysql.MSBigInteger
+#sqlalchemy.dialects.sqlite.SLBigInteger = SLBigInteger
+#sqlalchemy.dialects.sqlite.colspecs[BigInteger] = SLBigInteger
+#sqlalchemy.dialects.sqlite.ischema_names['BIGINT'] = SLBigInteger
+#sqlalchemy.dialects.postgres.colspecs[BigInteger] = sqlalchemy.dialects.postgres.PGBigInteger
+#sqlalchemy.dialects.mysql.colspecs[BigInteger] = sqlalchemy.dialects.mysql.MSBigInteger
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/8f0a3c34af31/
Changeset: 8f0a3c34af31
User: dannon
Date: 2013-04-18 21:35:22
Summary: Merge with central
Affected #: 77 files
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 buildbot_setup.sh
--- a/buildbot_setup.sh
+++ b/buildbot_setup.sh
@@ -93,26 +93,49 @@
JARS="/galaxy/software/jars"
-for link in $LINKS; do
- echo "Linking $link"
- rm -f tool-data/`basename $link`
- ln -sf $link tool-data
-done
-
-if [ -d "$HYPHY" ]; then
- echo "Linking $HYPHY"
- rm -f tool-data/HYPHY
- ln -sf $HYPHY tool-data/HYPHY
+if [ ! $1 ]; then
+ type="standard"
+elif [ $1 == "-ec2" ]; then
+ type="external-ec2"
+else
+ type="unknown"
fi
-if [ -d "$JARS" ]; then
- echo "Linking $JARS"
- rm -f tool-data/shared/jars
- ln -sf $JARS tool-data/shared/jars
-fi
+case $type in
+ external*)
+ echo "Running standalone buildbot setup..."
+ for sample in tool-data/*.sample; do
+ basename=${sample%.sample}
+ if [ ! -f $basename ]; then
+ echo "Copying $sample to $basename"
+ cp "$sample" "$basename"
+ fi
+ done
+ ;;
+ *)
+ echo "Running standard buildbot setup..."
+ for link in $LINKS; do
+ echo "Linking $link"
+ rm -f tool-data/`basename $link`
+ ln -sf $link tool-data
+ done
+
+ if [ -d "$HYPHY" ]; then
+ echo "Linking $HYPHY"
+ rm -f tool-data/HYPHY
+ ln -sf $HYPHY tool-data/HYPHY
+ fi
+
+ if [ -d "$JARS" ]; then
+ echo "Linking $JARS"
+ rm -f tool-data/shared/jars
+ ln -sf $JARS tool-data/shared/jars
+ fi
+ ;;
+esac
for sample in $SAMPLES; do
- file=`echo $sample | sed -e 's/\.sample$//'`
+ file=${sample%.sample}
echo "Copying $sample to $file"
cp $sample $file
done
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -159,7 +159,9 @@
<converter file="encodepeak_to_summary_tree_converter.xml" target_datatype="summary_tree"/></datatype><datatype extension="pdf" type="galaxy.datatypes.images:Pdf" mimetype="application/pdf"/>
- <datatype extension="pileup" type="galaxy.datatypes.tabular:Pileup" display_in_upload="true" />
+ <datatype extension="pileup" type="galaxy.datatypes.tabular:Pileup" display_in_upload="true">
+ <converter file="pileup_to_interval_index_converter.xml" target_datatype="interval_index"/>
+ </datatype><datatype extension="png" type="galaxy.datatypes.images:Png" mimetype="image/png"/><datatype extension="qual" type="galaxy.datatypes.qualityscore:QualityScore" /><datatype extension="qualsolexa" type="galaxy.datatypes.qualityscore:QualityScoreSolexa" display_in_upload="true"/>
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -166,6 +166,7 @@
self.enable_whoosh_library_search = string_as_bool( kwargs.get( 'enable_whoosh_library_search', False ) )
self.whoosh_index_dir = resolve_path( kwargs.get( "whoosh_index_dir", "database/whoosh_indexes" ), self.root )
self.ftp_upload_dir = kwargs.get( 'ftp_upload_dir', None )
+ self.ftp_upload_dir_identifier = kwargs.get( 'ftp_upload_dir_identifier', 'email' ) # attribute on user - email, username, id, etc...
self.ftp_upload_site = kwargs.get( 'ftp_upload_site', None )
self.allow_library_path_paste = kwargs.get( 'allow_library_path_paste', False )
self.disable_library_comptypes = kwargs.get( 'disable_library_comptypes', '' ).lower().split( ',' )
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -101,6 +101,9 @@
class Bam( Binary ):
"""Class describing a BAM binary file"""
file_ext = "bam"
+ track_type = "ReadTrack"
+ data_sources = { "data": "bai", "index": [ "bigwig", "summary_tree" ] }
+
MetadataElement( name="bam_index", desc="BAM Index File", param=metadata.FileParameter, file_ext="bai", readonly=True, no_value=None, visible=False, optional=True )
def _get_samtools_version( self ):
@@ -251,9 +254,7 @@
return dataset.peek
except:
return "Binary bam alignments file (%s)" % ( data.nice_size( dataset.get_size() ) )
- def get_track_type( self ):
- return "ReadTrack", { "data": "bai", "index": [ "bigwig", "summary_tree" ] }
-
+
Binary.register_sniffable_binary_format("bam", "bam", Bam)
class H5( Binary ):
@@ -331,6 +332,9 @@
The supplemental info in the paper has the binary details:
http://bioinformatics.oxfordjournals.org/cgi/content/abstract/btq351v1
"""
+ track_type = "LineTrack"
+ data_sources = { "data_standalone": "bigwig" }
+
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
self._magic = 0x888FFC26
@@ -355,19 +359,18 @@
return dataset.peek
except:
return "Binary UCSC %s file (%s)" % ( self._name, data.nice_size( dataset.get_size() ) )
- def get_track_type( self ):
- return "LineTrack", {"data_standalone": "bigwig"}
-
+
Binary.register_sniffable_binary_format("bigwig", "bigwig", BigWig)
class BigBed(BigWig):
"""BigBed support from UCSC."""
+
+ data_sources = { "data_standalone": "bigbed" }
+
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
self._magic = 0x8789F2EB
self._name = "BigBed"
- def get_track_type( self ):
- return "LineTrack", {"data_standalone": "bigbed"}
Binary.register_sniffable_binary_format("bigbed", "bigbed", BigBed)
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.py
--- /dev/null
+++ b/lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+"""
+Convert from pileup file to interval index file.
+
+usage: %prog <options> in_file out_file
+"""
+
+from __future__ import division
+
+import sys, fileinput, optparse
+from galaxy import eggs
+import pkg_resources; pkg_resources.require( "bx-python" )
+from galaxy.visualization.tracks.summary import *
+from galaxy.datatypes.util.gff_util import convert_gff_coords_to_bed
+from bx.interval_index_file import Indexes
+
+def main():
+
+ # Read options, args.
+ parser = optparse.OptionParser()
+ (options, args) = parser.parse_args()
+ input_fname, output_fname = args
+
+ # Do conversion.
+ index = Indexes()
+ offset = 0
+ for line in open( input_fname, "r" ):
+ chrom, start = line.split()[ 0:2 ]
+ # Pileup format is 1-based.
+ start = int( start ) - 1
+ index.add( chrom, start, start + 1, offset )
+ offset += len( line )
+
+ index.write( open(output_fname, "w") )
+
+if __name__ == "__main__":
+ main()
+
\ No newline at end of file
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.xml
--- /dev/null
+++ b/lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.xml
@@ -0,0 +1,15 @@
+<tool id="CONVERTER_pileup_to_interval_index_0" name="Convert Pileup to Interval Index" version="1.0.0" hidden="true">
+<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <command interpreter="python">pileup_to_interval_index_converter.py $input $output
+ </command>
+ <inputs>
+ <page>
+ <param format="pileup" name="input" type="data" label="Choose Pileup file"/>
+ </page>
+ </inputs>
+ <outputs>
+ <data format="interval_index" name="output"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -97,6 +97,12 @@
#A per datatype setting (inherited): max file size (in bytes) for setting optional metadata
_max_optional_metadata_filesize = None
+ # Trackster track type.
+ track_type = None
+
+ # Data sources.
+ data_sources = {}
+
def __init__(self, **kwd):
"""Initialize the datatype"""
object.__init__(self, **kwd)
@@ -539,21 +545,21 @@
return False
-
def merge( split_files, output_file):
"""
- TODO: Do we need to merge gzip files using gzjoin? cat seems to work,
- but might be brittle. Need to revisit this.
+ Merge files with copy.copyfileobj() will not hit the
+ max argument limitation of cat. gz and bz2 files are also working.
"""
if not split_files:
raise ValueError('Asked to merge zero files as %s' % output_file)
elif len(split_files) == 1:
- cmd = 'mv -f %s %s' % ( split_files[0], output_file )
+ shutil.copyfileobj(open(split_files[0], 'rb'), open(output_file, 'wb'))
else:
- cmd = 'cat %s > %s' % ( ' '.join(split_files), output_file )
- result = os.system(cmd)
- if result != 0:
- raise Exception('Result %s from %s' % (result, cmd))
+ fdst = open(output_file, 'wb')
+ for fsrc in split_files:
+ shutil.copyfileobj(open(fsrc, 'rb'), fdst)
+ fdst.close()
+
merge = staticmethod(merge)
def get_visualizations( self, dataset ):
@@ -561,7 +567,7 @@
Returns a list of visualizations for datatype.
"""
- if hasattr( self, 'get_track_type' ):
+ if self.track_type:
return [ 'trackster', 'circster' ]
return []
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/display_applications/application.py
--- a/lib/galaxy/datatypes/display_applications/application.py
+++ b/lib/galaxy/datatypes/display_applications/application.py
@@ -12,7 +12,7 @@
log = logging.getLogger( __name__ )
#Any basic functions that we want to provide as a basic part of parameter dict should be added to this dict
-BASE_PARAMS = { 'qp': quote_plus, 'url_for':url_for } #url_for has route memory...
+BASE_PARAMS = { 'qp': quote_plus, 'url_for':url_for }
class DisplayApplicationLink( object ):
@classmethod
@@ -40,7 +40,7 @@
self.name = None
def get_display_url( self, data, trans ):
dataset_hash, user_hash = encode_dataset_user( trans, data, None )
- return url_for( controller='/dataset',
+ return url_for( controller='dataset',
action="display_application",
dataset_id=dataset_hash,
user_id=user_hash,
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/display_applications/link_generator.py
--- a/lib/galaxy/datatypes/display_applications/link_generator.py
+++ /dev/null
@@ -1,161 +0,0 @@
-"""Classes to generate links for old-style display applications.
-
-Separating Transaction based elements of display applications from datatypes.
-"""
-
-#FIXME: The code contained within this file is for old-style display applications, but
-#this module namespace is intended to only handle the new-style display applications.
-
-import urllib
-
-# for the url_for hack
-import pkg_resources
-pkg_resources.require( "Routes" )
-import routes
-
-from galaxy import util
-from galaxy.web import url_for
-from galaxy.datatypes.interval import Interval, Gff, Wiggle, CustomTrack
-
-#TODO: Ideally, these classes would be instantiated in the trans (or some other semi-persistant fixture)
-# Currently, these are instantiated per HDA which is not the best solution
-
-#TODO: these could be extended to handle file_function and parse/contain the builds.txt files
-
-#HACK: these duplicate functionality from the individual datatype classes themselves
-
-def get_display_app_link_generator( display_app_name ):
- """Returns an instance of the proper link generator class
- based on the display_app_name or DisplayAppLinkGenerator
- if the display_app_name is unrecognized.
- """
- if display_app_name == 'ucsc':
- return UCSCDisplayAppLinkGenerator()
-
- elif display_app_name == 'gbrowse':
- return GBrowseDisplayAppLinkGenerator()
-
- return DisplayAppLinkGenerator()
-
-
-class DisplayAppLinkGenerator( object ):
- """Base class for display application link generators.
-
- This class returns an empty list of links for all datatypes.
- """
- def __init__( self ):
- self.display_app_name = ''
-
- def no_links_available( self, dataset, app, base_url, url_for=url_for ):
- """Called when no display application links are available
- for this display app name and datatype combination.
- """
- return []
-
- def _link_function_from_datatype( self, datatype ):
- """Dispatch to proper link generating function on datatype.
- """
- return self.no_links_available
-
- def generate_links( self, trans, dataset ):
- # here's the hack - which is expensive (time)
- web_url_for = routes.URLGenerator( trans.webapp.mapper, trans.environ )
-
- link_function = self._link_function_from_datatype( dataset.datatype )
- display_links = link_function( dataset, trans.app, trans.request.base, url_for=web_url_for )
-
- return display_links
-
-
-class UCSCDisplayAppLinkGenerator( DisplayAppLinkGenerator ):
- """Class for generating links to display data in the
- UCSC genome browser.
-
- This class returns links for the following datatypes and their subclasses:
- Interval, Wiggle, Gff, CustomTrack
- """
- def __init__( self ):
- self.display_app_name = 'ucsc'
-
- def _link_function_from_datatype( self, datatype ):
- """Dispatch to proper link generating function based on datatype.
- """
- if( ( isinstance( datatype, Interval ) )
- or ( isinstance( datatype, Wiggle ) )
- or ( isinstance( datatype, Gff ) )
- or ( isinstance( datatype, CustomTrack ) ) ):
- return self.ucsc_links
- else:
- return super( UCSCDisplayAppLinkGenerator, self )._link_function_from_datatype( datatype )
-
- def ucsc_links( self, dataset, app, base_url, url_for=url_for ):
- """Generate links to UCSC genome browser sites based on the dbkey
- and content of dataset.
- """
- # this is a refactor of Interval.ucsc_links, GFF.ucsc_links, Wiggle.ucsc_links, and CustomTrack.ucsc_links
- #TODO: app vars can be moved into init (and base_url as well)
- chrom, start, stop = dataset.datatype.get_estimated_display_viewport( dataset )
- if chrom is None:
- return []
- ret_val = []
- for site_name, site_url in util.get_ucsc_by_build(dataset.dbkey):
- if site_name in app.config.ucsc_display_sites:
- internal_url = url_for( controller='dataset', dataset_id=dataset.id,
- action='display_at', filename='%s_%s' % ( self.display_app_name, site_name ) )
- base_url = app.config.get( "display_at_callback", base_url )
- display_url = urllib.quote_plus( "%s%s/display_as?id=%i&display_app=%s&authz_method=display_at"
- % (base_url, url_for( controller='root' ), dataset.id, self.display_app_name) )
- redirect_url = urllib.quote_plus( "%sdb=%s&position=%s:%s-%s&hgt.customText=%%s"
- % (site_url, dataset.dbkey, chrom, start, stop ) )
-
- link = '%s?redirect_url=%s&display_url=%s' % ( internal_url, redirect_url, display_url )
- ret_val.append( ( site_name, link ) )
-
- return ret_val
-
-
-class GBrowseDisplayAppLinkGenerator( DisplayAppLinkGenerator ):
- """Class for generating links to display data in the
- GBrowse genome browser.
-
- This class returns links for the following datatypes and their subclasses:
- Gff, Wiggle
- """
- def __init__( self ):
- self.display_app_name = 'gbrowse'
-
- def _link_function_from_datatype( self, datatype ):
- """Dispatch to proper link generating function based on datatype.
- """
- if( ( isinstance( datatype, Gff ) )
- or ( isinstance( datatype, Wiggle ) ) ):
- return self.gbrowse_links
- else:
- return super( GBrowseDisplayAppLinkGenerator, self )._link_function_from_datatype( datatype )
-
- def gbrowse_links( self, dataset, app, base_url, url_for=url_for ):
- """Generate links to GBrowse genome browser sites based on the dbkey
- and content of dataset.
- """
- # when normalized for var names, Gff.gbrowse_links and Wiggle.gbrowse_links are the same
- # also: almost identical to ucsc_links except for the 'chr' stripping, sites_by_build, config key
- # could be refactored even more
- chrom, start, stop = dataset.datatype.get_estimated_display_viewport( dataset )
- if chrom is None:
- return []
- ret_val = []
- for site_name, site_url in util.get_gbrowse_sites_by_build( dataset.dbkey ):
- if site_name in app.config.gbrowse_display_sites:
- # strip chr from seqid
- if chrom.startswith( 'chr' ) and len ( chrom ) > 3:
- chrom = chrom[3:]
- internal_url = url_for( controller='dataset', dataset_id=dataset.id,
- action='display_at', filename='%s_%s' % ( self.display_app_name, site_name ) )
- redirect_url = urllib.quote_plus( "%s/?q=%s:%s..%s&eurl=%%s" % ( site_url, chrom, start, stop ) )
- base_url = app.config.get( "display_at_callback", base_url )
- display_url = urllib.quote_plus( "%s%s/display_as?id=%i&display_app=%s&authz_method=display_at"
- % ( base_url, url_for( controller='root' ), dataset.id, self.display_app_name ) )
- link = '%s?redirect_url=%s&display_url=%s' % ( internal_url, redirect_url, display_url )
- ret_val.append( ( site_name, link ) )
-
- return ret_val
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/display_applications/parameters.py
--- a/lib/galaxy/datatypes/display_applications/parameters.py
+++ b/lib/galaxy/datatypes/display_applications/parameters.py
@@ -163,7 +163,7 @@
if self.parameter.strip_https and base_url[ : 5].lower() == 'https':
base_url = "http%s" % base_url[ 5: ]
return "%s%s" % ( base_url,
- url_for( controller='/dataset',
+ url_for( controller='dataset',
action="display_application",
dataset_id=self._dataset_hash,
user_id=self._user_hash,
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py
+++ b/lib/galaxy/datatypes/interval.py
@@ -46,6 +46,8 @@
"""Tab delimited data containing interval information"""
file_ext = "interval"
line_class = "region"
+ track_type = "FeatureTrack"
+ data_sources = { "data": "tabix", "index": "summary_tree" }
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -242,7 +244,7 @@
# Accumulate links for valid sites
ret_val = []
for site_name, site_url in valid_sites:
- internal_url = url_for( controller='/dataset', dataset_id=dataset.id,
+ internal_url = url_for( controller='dataset', dataset_id=dataset.id,
action='display_at', filename='ucsc_' + site_name )
display_url = urllib.quote_plus( "%s%s/display_as?id=%i&display_app=%s&authz_method=display_at"
% (base_url, url_for( controller='root' ), dataset.id, type) )
@@ -328,17 +330,13 @@
def get_track_resolution( self, dataset, start, end):
return None
-
- def get_track_type( self ):
- return "FeatureTrack", {"data": "tabix", "index": "summary_tree"}
class BedGraph( Interval ):
"""Tab delimited chrom/start/end/datavalue dataset"""
file_ext = "bedgraph"
-
- def get_track_type( self ):
- return "LineTrack", { "data": "bigwig", "index": "bigwig" }
+ track_type = "LineTrack"
+ data_sources = { "data": "bigwig", "index": "bigwig" }
def as_ucsc_display_file( self, dataset, **kwd ):
"""
@@ -356,6 +354,7 @@
class Bed( Interval ):
"""Tab delimited data in BED format"""
file_ext = "bed"
+ data_sources = {"data": "tabix", "index": "summary_tree", "feature_search": "fli"}
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -510,9 +509,6 @@
else: return False
return True
except: return False
-
- def get_track_type( self ):
- return "FeatureTrack", {"data": "tabix", "index": "summary_tree", "feature_search": "fli"}
class BedStrict( Bed ):
"""Tab delimited data in strict BED format - no non-standard columns allowed"""
@@ -572,6 +568,7 @@
"""Tab delimited data in Gff format"""
file_ext = "gff"
column_names = [ 'Seqname', 'Source', 'Feature', 'Start', 'End', 'Score', 'Strand', 'Frame', 'Group' ]
+ data_sources = { "data": "interval_index", "index": "summary_tree", "feature_search": "fli" }
"""Add metadata elements"""
MetadataElement( name="columns", default=9, desc="Number of columns", readonly=True, visible=False )
@@ -783,10 +780,6 @@
return True
except:
return False
-
- def get_track_type( self ):
- return "FeatureTrack", {"data": "interval_index", "index": "summary_tree", "feature_search": "fli"}
-
class Gff3( Gff ):
"""Tab delimited data in Gff3 format"""
@@ -966,6 +959,8 @@
class Wiggle( Tabular, _RemoteCallMixin ):
"""Tab delimited data in wiggle format"""
file_ext = "wig"
+ track_type = "LineTrack"
+ data_sources = { "data": "bigwig", "index": "bigwig" }
MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True, visible=False )
@@ -1146,9 +1141,6 @@
resolution = min( resolution, 100000 )
resolution = max( resolution, 1 )
return resolution
-
- def get_track_type( self ):
- return "LineTrack", { "data": "bigwig", "index": "bigwig" }
class CustomTrack ( Tabular ):
"""UCSC CustomTrack"""
@@ -1292,6 +1284,7 @@
file_ext = "encodepeak"
column_names = [ 'Chrom', 'Start', 'End', 'Name', 'Score', 'Strand', 'SignalValue', 'pValue', 'qValue', 'Peak' ]
+ data_sources = { "data": "tabix", "index": "summary_tree" }
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -1303,15 +1296,14 @@
def sniff( self, filename ):
return False
- def get_track_type( self ):
- return "FeatureTrack", {"data": "tabix", "index": "summary_tree"}
-
class ChromatinInteractions( Interval ):
'''
Chromatin interactions obtained from 3C/5C/Hi-C experiments.
'''
file_ext = "chrint"
+ track_type = "DiagonalHeatmapTrack"
+ data_sources = { "data": "tabix", "index": "summary_tree" }
column_names = [ 'Chrom1', 'Start1', 'End1', 'Chrom2', 'Start2', 'End2', 'Value' ]
@@ -1328,11 +1320,6 @@
def sniff( self, filename ):
return False
-
- def get_track_type( self ):
- return "DiagonalHeatmapTrack", {"data": "tabix", "index": "summary_tree"}
-
-
if __name__ == '__main__':
import doctest, sys
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/registry.py
--- a/lib/galaxy/datatypes/registry.py
+++ b/lib/galaxy/datatypes/registry.py
@@ -163,7 +163,7 @@
# Use default mime type as per datatype spec
mimetype = self.datatypes_by_extension[ extension ].get_mime()
self.mimetypes_by_extension[ extension ] = mimetype
- if hasattr( datatype_class, "get_track_type" ):
+ if datatype_class.track_type:
self.available_tracks.append( extension )
if display_in_upload:
self.upload_file_formats.append( extension )
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -358,6 +358,9 @@
class Sam( Tabular ):
file_ext = 'sam'
+ track_type = "ReadTrack"
+ data_sources = { "data": "bam", "index": "summary_tree" }
+
def __init__(self, **kwd):
"""Initialize taxonomy datatype"""
Tabular.__init__( self, **kwd )
@@ -467,13 +470,11 @@
raise Exception('Result %s from %s' % (result, cmd))
merge = staticmethod(merge)
- def get_track_type( self ):
- return "ReadTrack", {"data": "bam", "index": "summary_tree"}
-
class Pileup( Tabular ):
"""Tab delimited data in pileup (6- or 10-column) format"""
file_ext = "pileup"
line_class = "genomic coordinate"
+ data_sources = { "data": "interval_index" }
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -525,8 +526,7 @@
return True
except:
return False
-
-
+
class ElandMulti( Tabular ):
file_ext = 'elandmulti'
@@ -535,13 +535,16 @@
class Vcf( Tabular ):
""" Variant Call Format for describing SNPs and other simple genome variations. """
+ track_type = "VariantTrack"
+ data_sources = { "data": "tabix", "index": "summary_tree" }
file_ext = 'vcf'
column_names = [ 'Chrom', 'Pos', 'ID', 'Ref', 'Alt', 'Qual', 'Filter', 'Info', 'Format', 'data' ]
MetadataElement( name="columns", default=10, desc="Number of columns", readonly=True, visible=False )
MetadataElement( name="column_types", default=['str','int','str','str','str','int','str','list','str','str'], param=metadata.ColumnTypesParameter, desc="Column types", readonly=True, visible=False )
- MetadataElement( name="viz_filter_cols", desc="Score column for visualization", default=[5], param=metadata.ColumnParameter, multiple=True )
+ MetadataElement( name="viz_filter_cols", desc="Score column for visualization", default=[5], param=metadata.ColumnParameter, multiple=True, visible=False )
+ MetadataElement( name="sample_names", default=[], desc="Sample names", readonly=True, visible=False, optional=True, no_value=[] )
def sniff( self, filename ):
headers = get_headers( filename, '\n', count=1 )
@@ -551,8 +554,20 @@
"""Returns formated html of peek"""
return Tabular.make_html_table( self, dataset, column_names=self.column_names )
- def get_track_type( self ):
- return "VcfTrack", { "data": "tabix", "index": "summary_tree" }
+ def set_meta( self, dataset, **kwd ):
+ Tabular.set_meta( self, dataset, **kwd )
+ source = open( dataset.file_name )
+
+ # Skip comments.
+ line = None
+ for line in source:
+ if not line.startswith( '##' ):
+ break
+
+ if line and line.startswith( '#' ):
+ # Found header line, get sample names.
+ dataset.metadata.sample_names = line.split()[ 9: ]
+
class Eland( Tabular ):
"""Support for the export.txt.gz file used by Illumina's ELANDv2e aligner"""
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -1470,6 +1470,14 @@
self.__galaxy_system_pwent = pwd.getpwuid(os.getuid())
return self.__galaxy_system_pwent
+ def get_output_destination( self, output_path ):
+ """
+ Destination for outputs marked as from_work_dir. This is the normal case,
+ just copy these files directly to the ulimate destination.
+ """
+ return output_path
+
+
class TaskWrapper(JobWrapper):
"""
Extension of JobWrapper intended for running tasks.
@@ -1691,6 +1699,15 @@
# There is no metadata setting for tasks. This is handled after the merge, at the job level.
return ""
+ def get_output_destination( self, output_path ):
+ """
+ Destination for outputs marked as from_work_dir. These must be copied with
+ the same basenme as the path for the ultimate output destination. This is
+ required in the task case so they can be merged.
+ """
+ return os.path.join( self.working_directory, os.path.basename( output_path ) )
+
+
class NoopQueue( object ):
"""
Implements the JobQueue / JobStopQueue interface but does nothing
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/jobs/runners/__init__.py
--- a/lib/galaxy/jobs/runners/__init__.py
+++ b/lib/galaxy/jobs/runners/__init__.py
@@ -226,7 +226,7 @@
# Copy from working dir to HDA.
# TODO: move instead of copy to save time?
source_file = os.path.join( os.path.abspath( job_wrapper.working_directory ), hda_tool_output.from_work_dir )
- destination = output_paths[ dataset.dataset_id ]
+ destination = job_wrapper.get_output_destination( output_paths[ dataset.dataset_id ] )
if in_directory( source_file, job_wrapper.working_directory ):
output_pairs.append( ( source_file, destination ) )
log.debug( "Copying %s to %s as directed by from_work_dir" % ( source_file, destination ) )
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1344,10 +1344,9 @@
with entries of type
(<datasource_type> : {<datasource_name>, <indexing_message>}).
"""
- track_type, data_sources = self.datatype.get_track_type()
data_sources_dict = {}
msg = None
- for source_type, source_list in data_sources.iteritems():
+ for source_type, source_list in self.datatype.data_sources.iteritems():
data_source = None
if source_type == "data_standalone":
# Nothing to do.
@@ -3305,16 +3304,16 @@
be installed in order for this repository to function correctly. However, those repository dependencies that are defined for this
repository with prior_installation_required set to True place them in a special category in that the required repositories must be
installed before this repository is installed. Among other things, this enables these "special" repository dependencies to include
- information that enables the successful intallation of this repository.
+ information that enables the successful intallation of this repository. This method is not used during the initial installation of
+ this repository, but only after it has been installed (metadata must be set for this repository in order for this method to be useful).
"""
required_rd_tups_that_must_be_installed = []
if self.has_repository_dependencies:
rd_tups = self.metadata[ 'repository_dependencies' ][ 'repository_dependencies' ]
for rd_tup in rd_tups:
if len( rd_tup ) == 4:
- # Metadata should have been reset on this installed tool_shed_repository, but it wasn't.
+ # For backward compatibility to the 12/20/12 Galaxy release, default prior_installation_required to False.
tool_shed, name, owner, changeset_revision = rd_tup
- # Default prior_installation_required to False.
prior_installation_required = False
elif len( rd_tup ) == 5:
tool_shed, name, owner, changeset_revision, prior_installation_required = rd_tup
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1094,7 +1094,7 @@
self.version_string_cmd = None
version_cmd = root.find("version_command")
if version_cmd is not None:
- self.version_string_cmd = version_cmd.text
+ self.version_string_cmd = version_cmd.text.strip()
version_cmd_interpreter = version_cmd.get( "interpreter", None )
if version_cmd_interpreter:
executable = self.version_string_cmd.split()[0]
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -475,7 +475,7 @@
if trans is None or trans.user is None:
user_ftp_dir = None
else:
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
return form_builder.FTPFileField( self.name, user_ftp_dir, trans.app.config.ftp_upload_site, value = value )
def from_html( self, value, trans=None, other_values={} ):
try:
@@ -623,6 +623,8 @@
def __init__( self, tool, elem, context=None ):
ToolParameter.__init__( self, tool, elem )
self.multiple = string_as_bool( elem.get( 'multiple', False ) )
+ # Multiple selects are optional by default, single selection is the inverse.
+ self.optional = string_as_bool( elem.get( 'optional', self.multiple ) )
self.display = elem.get( 'display', None )
self.separator = elem.get( 'separator', ',' )
self.legal_values = set()
@@ -712,6 +714,13 @@
rval.append( v )
return rval
else:
+ value_is_none = ( value == "None" and "None" not in legal_values )
+ if value_is_none:
+ if self.multiple:
+ if self.optional:
+ return []
+ else:
+ raise ValueError( "No option was selected but input is not optional." )
if value not in legal_values:
raise ValueError( "An invalid option was selected, please verify" )
return value
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/tools/parameters/dynamic_options.py
--- a/lib/galaxy/tools/parameters/dynamic_options.py
+++ b/lib/galaxy/tools/parameters/dynamic_options.py
@@ -129,6 +129,13 @@
rval.append( fields )
return rval
else:
+ if not self.dynamic_option.columns:
+ self.dynamic_option.columns = {
+ "name" : 0,
+ "value" : 1,
+ "selected" : 2
+ }
+ self.dynamic_option.largest_index = 2
if not isinstance( meta_value, list ):
meta_value = [meta_value]
for value in meta_value:
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/tools/parameters/grouping.py
--- a/lib/galaxy/tools/parameters/grouping.py
+++ b/lib/galaxy/tools/parameters/grouping.py
@@ -270,7 +270,7 @@
if file_bunch.path and ftp_files is not None:
warnings.append( "All FTP uploaded file selections were ignored." )
elif ftp_files is not None and trans.user is not None: # look for files uploaded via FTP
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
for filename in filenames:
for ftp_filename in ftp_files:
@@ -318,7 +318,7 @@
ftp_files = []
# TODO: warning to the user (could happen if session has become invalid)
else:
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
for filename in filenames:
path = relpath( os.path.join( dirpath, filename ), user_ftp_dir )
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/visualization/data_providers/genome.py
--- a/lib/galaxy/visualization/data_providers/genome.py
+++ b/lib/galaxy/visualization/data_providers/genome.py
@@ -2,7 +2,7 @@
Data providers for genome visualizations.
"""
-import os, sys, operator
+import os, sys, re
from math import ceil, log
import pkg_resources
pkg_resources.require( "bx-python" )
@@ -601,12 +601,22 @@
"""
Abstract class that processes VCF data from native format to payload format.
- Payload format: TODO
+ Payload format: An array of entries for each locus in the file. Each array
+ has the following entries:
+ 1. GUID (unused)
+ 2. location (0-based)
+ 3. reference base(s)
+ 4. alternative base(s)
+ 5. quality score
+ 6. whether variant passed filter
+ 7. sample genotypes -- a single string with samples separated by commas; empty string
+ denotes the reference genotype
+ 8-end: allele counts for each alternative
"""
col_name_data_attr_mapping = { 'Qual' : { 'index': 6 , 'name' : 'Qual' } }
- dataset_type = 'bai'
+ dataset_type = 'variant'
def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ):
"""
@@ -621,7 +631,7 @@
message - error/informative message
"""
- rval = []
+ data = []
message = None
def get_mapping( ref, alt ):
@@ -651,6 +661,7 @@
return ref_in_alt_index, alt[ ref_in_alt_index + 1: ], [ [ cig_ops.find( "I" ), alt_len - ref_len ] ]
# Pack data.
+ genotype_re = re.compile( '/|\|' )
for count, line in enumerate( iterator ):
if count < start_val:
continue
@@ -658,37 +669,66 @@
message = self.error_max_vals % ( max_vals, "features" )
break
+ # Split line and aggregate data.
feature = line.split()
- start = int( feature[1] ) - 1
- ref = feature[3]
- alts = feature[4]
+ pos, c_id, ref, alt, qual, c_filter, info = feature[ 1:8 ]
+ format = feature[ 8 ]
+ samples_data = feature [ 9: ]
+ # VCF is 1-based.
+ pos = int( pos ) - 1
+
+ # FIXME: OK to skip?
+ if alt == '.':
+ count -= 1
+ continue
- # HACK? alts == '.' --> monomorphism.
- if alts == '.':
- alts = ref
+ # Count number of samples matching each allele.
+ allele_counts = [ 0 for i in range ( alt.count( ',' ) + 1 ) ]
- # Pack variants.
- for alt in alts.split(","):
- offset, new_seq, cigar = get_mapping( ref, alt )
- start += offset
- end = start + len( new_seq )
+ # Process and pack sample genotype.
+ sample_gts = []
+ alleles_seen = {}
+ has_alleles = False
- # Pack line.
- payload = [
- hash( line ),
- start,
- end,
- # ID:
- feature[2],
- cigar,
- # TODO? VCF does not have strand, so default to positive.
- "+",
- new_seq,
- None if feature[5] == '.' else float( feature[5] )
- ]
- rval.append(payload)
+ for i, sample in enumerate( samples_data ):
+ # Parse and count alleles.
+ genotype = sample.split( ':' )[ 0 ]
+ has_alleles = False
+ alleles_seen.clear()
+ for allele in genotype_re.split( genotype ):
+ try:
+ # This may throw a ValueError if allele is missing.
+ allele = int( allele )
- return { 'data': rval, 'message': message }
+ # Only count allele if it hasn't been seen yet.
+ if allele != 0 and allele not in alleles_seen:
+ allele_counts[ allele - 1 ] += 1
+ alleles_seen[ allele ] = True
+ has_alleles = True
+ except ValueError:
+ pass
+
+ # If no alleles, use empty string as proxy.
+ if not has_alleles:
+ genotype = ''
+
+ sample_gts.append( genotype )
+
+ # Add locus data.
+ locus_data = [
+ -1,
+ pos,
+ c_id,
+ ref,
+ alt,
+ qual,
+ c_filter,
+ ','.join( sample_gts )
+ ]
+ locus_data.extend( allele_counts )
+ data.append( locus_data )
+
+ return { 'data': data, 'message': message }
def write_data_to_file( self, regions, filename ):
out = open( filename, "w" )
@@ -707,7 +747,8 @@
"""
Provides data from a VCF file indexed via tabix.
"""
- pass
+
+ dataset_type = 'variant'
class RawVcfDataProvider( VcfDataProvider ):
"""
@@ -718,29 +759,45 @@
"""
def get_iterator( self, chrom, start, end, **kwargs ):
- # Read first line in order to match chrom naming format.
- line = source.readline()
- dataset_chrom = line.split()[0]
- if not _chrom_naming_matches( chrom, dataset_chrom ):
- chrom = _convert_between_ucsc_and_ensemble_naming( chrom )
- # Undo read.
- source.seek( 0 )
+ source = open( self.original_dataset.file_name )
+
+ # Skip comments.
+ pos = 0
+ line = None
+ for line in source:
+ if not line.startswith("#"):
+ break
+ else:
+ pos = source.tell()
+
+ # If last line is a comment, there are no data lines.
+ if line.startswith( "#" ):
+ return []
+
+ # Match chrom naming format.
+ if line:
+ dataset_chrom = line.split()[0]
+ if not _chrom_naming_matches( chrom, dataset_chrom ):
+ chrom = _convert_between_ucsc_and_ensemble_naming( chrom )
+
+ def line_in_region( vcf_line, chrom, start, end ):
+ """ Returns true if line is in region. """
+ variant_chrom, variant_start = vcf_line.split()[ 0:2 ]
+ # VCF format is 1-based.
+ variant_start = int( variant_start ) - 1
+ return variant_chrom == chrom and variant_start >= start and variant_start <= end
def line_filter_iter():
- for line in open( self.original_dataset.file_name ):
- if line.startswith("#"):
- continue
- variant = line.split()
- variant_chrom, variant_start, id, ref, alts = variant[ 0:5 ]
- variant_start = int( variant_start )
- longest_alt = -1
- for alt in alts:
- if len( alt ) > longest_alt:
- longest_alt = len( alt )
- variant_end = variant_start + abs( len( ref ) - longest_alt )
- if variant_chrom != chrom or variant_start > end or variant_end < start:
- continue
+ """ Yields lines in source that are in region chrom:start-end """
+ # Yield data line read above.
+ if line_in_region( line, chrom, start, end ):
yield line
+
+ # Search for and yield other data lines.
+ for data_line in source:
+ if line_in_region( data_line, chrom, start, end ):
+ print chrom, start, end, ">>>", data_line,
+ yield data_line
return line_filter_iter()
@@ -1012,34 +1069,44 @@
# If there are results and reference data, transform read sequence and cigar.
if len( results ) != 0 and ref_seq:
+ def process_read( read, start_field, cigar_field, seq_field ):
+ '''
+ Process a read using the designated fields.
+ '''
+ read_seq, read_cigar = get_ref_based_read_seq_and_cigar( read[ seq_field ].upper(),
+ read[ start_field ],
+ ref_seq,
+ start,
+ read[ cigar_field ] )
+ read[ seq_field ] = read_seq
+ read[ cigar_field ] = read_cigar
+
def process_se_read( read ):
'''
Process single-end read.
'''
- read_seq, read_cigar = get_ref_based_read_seq_and_cigar( read[ 6 ].upper(), read[ 1 ],
- ref_seq, start, read[ 4 ] )
- read[ 6 ] = read_seq
- read[ 4 ] = read_cigar
-
+ process_read( read, 1, 4, 6)
+
def process_pe_read( read ):
'''
Process paired-end read.
'''
- process_se_read( read[ 4 ] )
- process_se_read( read[ 5 ] )
+ if len( read[4] ) > 2:
+ process_read( read[4], 0, 2, 4 )
+ if len( read[5] ) > 2:
+ process_read( read[5], 0, 2, 4 )
# Uppercase for easy comparison.
ref_seq = ref_seq.upper()
- # Choose correct function for processing reads.
- process_fn = process_se_read
- if isinstance( results[ 0 ][ 5 ], list ):
- process_fn = process_pe_read
-
# Process reads.
for read in results:
- process_fn( read )
-
+ # Use correct function for processing reads.
+ if isinstance( read[ 5 ], list ):
+ process_pe_read( read )
+ else:
+ process_se_read( read )
+
max_low, max_high = get_bounds( results, 1, 2 )
return { 'data': results, 'message': message, 'max_low': max_low, 'max_high': max_high }
@@ -1050,14 +1117,16 @@
def __init__( self, converted_dataset=None, original_dataset=None, dependencies=None ):
""" Create SamDataProvider. """
+ super( SamDataProvider, self ).__init__( converted_dataset=converted_dataset,
+ original_dataset=original_dataset,
+ dependencies=dependencies )
- # HACK: to use BamDataProvider, original dataset must be BAM and
+ # To use BamDataProvider, original dataset must be BAM and
# converted dataset must be BAI. Use BAI from BAM metadata.
if converted_dataset:
+ self.original_dataset = converted_dataset
self.converted_dataset = converted_dataset.metadata.bam_index
- self.original_dataset = converted_dataset
- self.dependencies = dependencies
-
+
class BBIDataProvider( GenomeDataProvider ):
"""
BBI data provider for the Galaxy track browser.
@@ -1207,7 +1276,7 @@
class IntervalIndexDataProvider( FilterableMixin, GenomeDataProvider ):
"""
- Interval index files used only for GFF files.
+ Interval index files used for GFF, Pileup files.
"""
col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } }
@@ -1217,20 +1286,26 @@
source = open( self.original_dataset.file_name )
index = Indexes( self.converted_dataset.file_name )
out = open( filename, 'w' )
-
+
for region in regions:
# Write data from region.
chrom = region.chrom
start = region.start
end = region.end
- for start, end, offset in index.find(chrom, start, end):
+ for start, end, offset in index.find( chrom, start, end ):
source.seek( offset )
-
- reader = GFFReaderWrapper( source, fix_strand=True )
- feature = reader.next()
- for interval in feature.intervals:
- out.write( '\t'.join( interval.fields ) + '\n' )
-
+
+ # HACK: write differently depending on original dataset format.
+ if self.original_dataset.ext not in [ 'gff', 'gff3', 'gtf' ]:
+ line = source.readline()
+ out.write( line )
+ else:
+ reader = GFFReaderWrapper( source, fix_strand=True )
+ feature = reader.next()
+ for interval in feature.intervals:
+ out.write( '\t'.join( interval.fields ) + '\n' )
+
+ source.close()
out.close()
def get_iterator( self, chrom, start, end, **kwargs ):
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/visualization/data_providers/registry.py
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -83,12 +83,12 @@
elif original_dataset:
# No name, so look up a provider name from datatype's information.
- # Dataset must have get_track_type function to get data.
- if not hasattr( original_dataset.datatype, 'get_track_type'):
+ # Dataset must have data sources to get data.
+ if not original_dataset.datatype.data_sources:
return None
# Get data provider mapping and data provider.
- _ , data_provider_mapping = original_dataset.datatype.get_track_type()
+ data_provider_mapping = original_dataset.datatype.data_sources
if 'data_standalone' in data_provider_mapping:
data_provider = self.get_data_provider( trans,
name=data_provider_mapping[ 'data_standalone' ],
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/visualization/genome/visual_analytics.py
--- a/lib/galaxy/visualization/genome/visual_analytics.py
+++ b/lib/galaxy/visualization/genome/visual_analytics.py
@@ -76,5 +76,5 @@
# If tool has parameters that can be interactively modified, return tool.
if len( tool_params ) != 0:
- return { 'name' : tool.name, 'params' : tool_params }
+ return { 'id': tool.id, 'name' : tool.name, 'params' : tool_params }
return None
\ No newline at end of file
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -32,8 +32,6 @@
from galaxy.datatypes.display_applications import util as da_util
from galaxy.datatypes.metadata import FileParameter
-from galaxy.datatypes.display_applications.link_generator import get_display_app_link_generator
-
log = logging.getLogger( __name__ )
# States for passing messages
@@ -392,28 +390,18 @@
})
def get_display_apps( self, trans, hda ):
- #TODO: make more straightforward (somehow)
display_apps = []
+ for display_app in hda.get_display_applications( trans ).itervalues():
- def get_display_app_url( display_app_link, hda, trans ):
- web_url_for = routes.URLGenerator( trans.webapp.mapper, trans.environ )
- dataset_hash, user_hash = da_util.encode_dataset_user( trans, hda, None )
- return web_url_for( controller='dataset',
- action="display_application",
- dataset_id=dataset_hash,
- user_id=user_hash,
- app_name=urllib.quote_plus( display_app_link.display_application.id ),
- link_name=urllib.quote_plus( display_app_link.id ) )
-
- for display_app in hda.get_display_applications( trans ).itervalues():
app_links = []
- for display_app_link in display_app.links.itervalues():
+ for link_app in display_app.links.itervalues():
app_links.append({
- 'target' : display_app_link.url.get( 'target_frame', '_blank' ),
- 'href' : get_display_app_url( display_app_link, hda, trans ),
- 'text' : gettext( display_app_link.name )
+ 'target': link_app.url.get( 'target_frame', '_blank' ),
+ 'href' : link_app.get_display_url( hda, trans ),
+ 'text' : gettext( link_app.name )
})
- display_apps.append( dict( label=display_app.name, links=app_links ) )
+ if app_links:
+ display_apps.append( dict( label=display_app.name, links=app_links ) )
return display_apps
@@ -421,19 +409,23 @@
display_apps = []
if not trans.app.config.enable_old_display_applications:
return display_apps
- for display_app_name in hda.datatype.get_display_types():
- link_generator = get_display_app_link_generator( display_app_name )
- display_links = link_generator.generate_links( trans, hda )
+
+ for display_app in hda.datatype.get_display_types():
+ target_frame, display_links = hda.datatype.get_display_links( hda,
+ display_app, trans.app, trans.request.base )
- app_links = []
- for display_name, display_link in display_links:
- app_links.append({
- 'target' : '_blank',
- 'href' : display_link,
- 'text' : display_name
- })
- if app_links:
- display_apps.append( dict( label=hda.datatype.get_display_label( display_app_name ), links=app_links ) )
+ if len( display_links ) > 0:
+ display_label = hda.datatype.get_display_label( display_app )
+
+ app_links = []
+ for display_name, display_link in display_links:
+ app_links.append({
+ 'target': target_frame,
+ 'href' : display_link,
+ 'text' : gettext( display_name )
+ })
+ if app_links:
+ display_apps.append( dict( label=display_label, links=app_links ) )
return display_apps
@@ -590,15 +582,13 @@
except KeyError:
prefs = {}
- track_type, _ = dataset.datatype.get_track_type()
track_data_provider = trans.app.data_provider_registry.get_data_provider( trans,
original_dataset=dataset,
source='data' )
return {
- "track_type": track_type,
+ "track_type": dataset.datatype.track_type,
+ "dataset": trans.security.encode_dict_ids( dataset.get_api_value() ),
"name": track_dict['name'],
- "hda_ldda": track_dict.get("hda_ldda", "hda"),
- "dataset_id": trans.security.encode_id( dataset.id ),
"prefs": prefs,
"mode": track_dict.get( 'mode', 'Auto' ),
"filters": track_dict.get( 'filters', { 'filters' : track_data_provider.get_filters() } ),
@@ -666,10 +656,8 @@
Returns track configuration dict for a dataset.
"""
# Get data provider.
- track_type, _ = dataset.datatype.get_track_type()
track_data_provider = trans.app.data_provider_registry.get_data_provider( trans, original_dataset=dataset )
-
if isinstance( dataset, trans.app.model.HistoryDatasetAssociation ):
hda_ldda = "hda"
elif isinstance( dataset, trans.app.model.LibraryDatasetDatasetAssociation ):
@@ -677,10 +665,9 @@
# Get track definition.
return {
- "track_type": track_type,
+ "track_type": dataset.datatype.track_type,
"name": dataset.name,
- "hda_ldda": hda_ldda,
- "dataset_id": trans.security.encode_id( dataset.id ),
+ "dataset": trans.security.encode_dict_ids( dataset.get_api_value() ),
"prefs": {},
"filters": { 'filters' : track_data_provider.get_filters() },
"tool": get_tool_def( trans, dataset ),
@@ -967,7 +954,7 @@
return state
- def get_history_dict( self, trans, history ):
+ def get_history_dict( self, trans, history, hda_dictionaries=None ):
"""Returns history data in the form of a dictionary.
"""
history_dict = history.get_api_value( view='element', value_mapper={ 'id':trans.security.encode_id })
@@ -979,8 +966,7 @@
if not history_dict[ 'annotation' ]:
history_dict[ 'annotation' ] = ''
- #TODO: allow passing as arg
- hda_summaries = self.get_hda_summary_dicts( trans, history )
+ hda_summaries = hda_dictionaries if hda_dictionaries else self.get_hda_summary_dicts( trans, history )
#TODO remove the following in v2
( state_counts, state_ids ) = self._get_hda_state_summaries( trans, hda_summaries )
history_dict[ 'state_details' ] = state_counts
diff -r d128613ae7c9ef1387b749c7577a6631b649b048 -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -112,34 +112,25 @@
def expose_api_anonymous( func, to_json=True ):
"""
- Expose this function via the API but don't require an API key.
+ Expose this function via the API but don't require a set user.
"""
- return expose_api( func, to_json=to_json, key_required=False )
+ return expose_api( func, to_json=to_json, user_required=False )
-def expose_api( func, to_json=True, key_required=True ):
+def expose_api( func, to_json=True, user_required=True ):
+ """
+ Expose this function via the API.
+ """
@wraps(func)
def decorator( self, trans, *args, **kwargs ):
def error( environ, start_response ):
start_response( error_status, [('Content-type', 'text/plain')] )
return error_message
error_status = '403 Forbidden'
- #If no key supplied, we use the existing session which may be an anonymous user.
- if key_required and not trans.user:
- try:
- if 'key' not in kwargs:
- raise NoResultFound( 'No key provided' )
- provided_key = trans.sa_session.query( trans.app.model.APIKeys ).filter( trans.app.model.APIKeys.table.c.key == kwargs['key'] ).one()
- except NoResultFound:
- error_message = 'Provided API key is not valid.'
- return error
- if provided_key.user.deleted:
- error_message = 'User account is deactivated, please contact an administrator.'
- return error
- newest_key = provided_key.user.api_keys[0]
- if newest_key.key != provided_key.key:
- error_message = 'Provided API key has expired.'
- return error
- trans.set_user( provided_key.user )
+ if trans.error_message:
+ return trans.error_message
+ if user_required and trans.user is None:
+ error_message = "API Authentication Required for this request"
+ return error
if trans.request.body:
def extract_payload_from_request(trans, func, kwargs):
content_type = trans.request.headers['content-type']
@@ -238,6 +229,7 @@
def form( *args, **kwargs ):
return FormBuilder( *args, **kwargs )
+
class WebApplication( base.WebApplication ):
def __init__( self, galaxy_app, session_cookie='galaxysession', name=None ):
@@ -326,6 +318,7 @@
controller_name = getattr( T, "controller_name", name )
self.add_api_controller( controller_name, T( app ) )
+
class GalaxyWebTransaction( base.DefaultWebTransaction ):
"""
Encapsulates web transaction specific state for the Galaxy application
@@ -346,13 +339,26 @@
# Flag indicating whether this is an API call and the API key user is an administrator
self.api_inherit_admin = False
self.__user = None
- # Always have a valid galaxy session
- self._ensure_valid_session( session_cookie )
- # Prevent deleted users from accessing Galaxy
- if self.app.config.use_remote_user and self.galaxy_session.user.deleted:
- self.response.send_redirect( url_for( '/static/user_disabled.html' ) )
- if self.app.config.require_login:
- self._ensure_logged_in_user( environ, session_cookie )
+ self.galaxy_session = None
+ self.error_message = None
+ if self.environ.get('is_api_request', False):
+ # With API requests, if there's a key, use it and associate the
+ # user with the transaction.
+ # If not, check for an active session but do not create one.
+ # If an error message is set here, it's sent back using
+ # trans.show_error in the response -- in expose_api.
+ self.error_message = self._authenticate_api( session_cookie )
+ else:
+ #This is a web request, get or create session.
+ self._ensure_valid_session( session_cookie )
+ if self.galaxy_session:
+ # When we've authenticated by session, we have to check the
+ # following.
+ # Prevent deleted users from accessing Galaxy
+ if self.app.config.use_remote_user and self.galaxy_session.user.deleted:
+ self.response.send_redirect( url_for( '/static/user_disabled.html' ) )
+ if self.app.config.require_login:
+ self._ensure_logged_in_user( environ, session_cookie )
def setup_i18n( self ):
locales = []
@@ -382,16 +388,17 @@
def get_user( self ):
"""Return the current user if logged in or None."""
- if self.__user:
+ if self.galaxy_session:
+ return self.galaxy_session.user
+ else:
return self.__user
- else:
- return self.galaxy_session.user
def set_user( self, user ):
"""Set the current user."""
- self.galaxy_session.user = user
- self.sa_session.add( self.galaxy_session )
- self.sa_session.flush()
+ if self.galaxy_session:
+ self.galaxy_session.user = user
+ self.sa_session.add( self.galaxy_session )
+ self.sa_session.flush()
self.__user = user
user = property( get_user, set_user )
@@ -473,6 +480,33 @@
except CookieError, e:
log.warning( "Error setting httponly attribute in cookie '%s': %s" % ( name, e ) )
+ def _authenticate_api( self, session_cookie ):
+ """
+ Authenticate for the API via key or session (if available).
+ """
+ api_key = self.request.params.get('key', None)
+ secure_id = self.get_cookie( name=session_cookie )
+ if self.environ.get('is_api_request', False) and api_key:
+ # Sessionless API transaction, we just need to associate a user.
+ try:
+ provided_key = self.sa_session.query( self.app.model.APIKeys ).filter( self.app.model.APIKeys.table.c.key == api_key ).one()
+ except NoResultFound:
+ return 'Provided API key is not valid.'
+ if provided_key.user.deleted:
+ return 'User account is deactivated, please contact an administrator.'
+ newest_key = provided_key.user.api_keys[0]
+ if newest_key.key != provided_key.key:
+ return 'Provided API key has expired.'
+ self.set_user( provided_key.user )
+ elif secure_id:
+ # API authentication via active session
+ # Associate user using existing session
+ self._ensure_valid_session( session_cookie )
+ else:
+ # Anonymous API interaction -- anything but @expose_api_anonymous will fail past here.
+ self.user = None
+ self.galaxy_session = None
+
def _ensure_valid_session( self, session_cookie, create=True):
"""
Ensure that a valid Galaxy session exists and is available as
@@ -505,8 +539,11 @@
.filter( and_( self.app.model.GalaxySession.table.c.session_key==session_key,
self.app.model.GalaxySession.table.c.is_valid==True ) ) \
.first()
- # If remote user is in use it can invalidate the session, so we need to to check some things now.
+ # If remote user is in use it can invalidate the session and in some
+ # cases won't have a cookie set above, so we need to to check some
+ # things now.
if self.app.config.use_remote_user:
+ #If this is an api request, and they've passed a key, we let this go.
assert "HTTP_REMOTE_USER" in self.environ, \
"use_remote_user is set but no HTTP_REMOTE_USER variable"
remote_user_email = self.environ[ 'HTTP_REMOTE_USER' ]
@@ -605,6 +642,7 @@
pass
if self.request.path not in allowed_paths:
self.response.send_redirect( url_for( controller='root', action='index' ) )
+
def __create_new_session( self, prev_galaxy_session=None, user_for_new_session=None ):
"""
Create a new GalaxySession for this request, possibly with a connection
@@ -627,6 +665,7 @@
# The new session should be associated with the user
galaxy_session.user = user_for_new_session
return galaxy_session
+
def get_or_create_remote_user( self, remote_user_email ):
"""
Create a remote user with the email remote_user_email and return it
@@ -671,11 +710,14 @@
self.app.security_agent.user_set_default_permissions( user )
#self.log_event( "Automatically created account '%s'", user.email )
return user
+
def __update_session_cookie( self, name='galaxysession' ):
"""
Update the session cookie to match the current session.
"""
- self.set_cookie( self.security.encode_guid( self.galaxy_session.session_key ), name=name, path=self.app.config.cookie_path )
+ self.set_cookie( self.security.encode_guid(self.galaxy_session.session_key ),
+ name=name, path=self.app.config.cookie_path )
+
def handle_user_login( self, user ):
"""
Login a new user (possibly newly created)
@@ -701,9 +743,9 @@
except:
users_last_session = None
last_accessed = False
- if prev_galaxy_session.current_history and \
- not prev_galaxy_session.current_history.deleted and \
- prev_galaxy_session.current_history.datasets:
+ if (prev_galaxy_session.current_history and not
+ prev_galaxy_session.current_history.deleted and
+ prev_galaxy_session.current_history.datasets):
if prev_galaxy_session.current_history.user is None or prev_galaxy_session.current_history.user == user:
# If the previous galaxy session had a history, associate it with the new
# session, but only if it didn't belong to a different user.
@@ -714,10 +756,9 @@
user.total_disk_usage += hda.quota_amount( user )
elif self.galaxy_session.current_history:
history = self.galaxy_session.current_history
- if not history and \
- users_last_session and \
- users_last_session.current_history and \
- not users_last_session.current_history.deleted:
+ if (not history and users_last_session and
+ users_last_session.current_history and not
+ users_last_session.current_history.deleted):
history = users_last_session.current_history
elif not history:
history = self.get_history( create=True )
@@ -736,6 +777,8 @@
self.sa_session.flush()
# This method is not called from the Galaxy reports, so the cookie will always be galaxysession
self.__update_session_cookie( name=cookie_name )
+
+
def handle_user_logout( self, logout_all=False ):
"""
Logout the current user:
@@ -760,31 +803,38 @@
self.__update_session_cookie( name='galaxysession' )
elif self.webapp.name == 'tool_shed':
self.__update_session_cookie( name='galaxycommunitysession' )
+
def get_galaxy_session( self ):
"""
Return the current galaxy session
"""
return self.galaxy_session
+
def get_history( self, create=False ):
"""
Load the current history, creating a new one only if there is not
- current history and we're told to create"
+ current history and we're told to create.
+ Transactions will not always have an active history (API requests), so
+ None is a valid response.
"""
- history = self.galaxy_session.current_history
- if not history:
- if util.string_as_bool( create ):
- history = self.new_history()
- else:
- # Perhaps a bot is running a tool without having logged in to get a history
- log.debug( "This request returned None from get_history(): %s" % self.request.browser_url )
- return None
+ history = None
+ if self.galaxy_session:
+ history = self.galaxy_session.current_history
+ if not history and util.string_as_bool( create ):
+ history = self.new_history()
+ else:
+ # Perhaps a bot is running a tool without having logged in to get a history
+ log.debug( "This request returned None from get_history(): %s" % self.request.browser_url )
return history
+
def set_history( self, history ):
if history and not history.deleted:
self.galaxy_session.current_history = history
self.sa_session.add( self.galaxy_session )
self.sa_session.flush()
+
history = property( get_history, set_history )
+
def new_history( self, name=None ):
"""
Create a new history and associate it with the current session and
@@ -809,6 +859,7 @@
self.sa_session.add_all( ( self.galaxy_session, history ) )
self.sa_session.flush()
return history
+
def get_current_user_roles( self ):
user = self.get_user()
if user:
@@ -816,27 +867,34 @@
else:
roles = []
return roles
+
def user_is_admin( self ):
if self.api_inherit_admin:
return True
admin_users = [ x.strip() for x in self.app.config.get( "admin_users", "" ).split( "," ) ]
return self.user and admin_users and self.user.email in admin_users
+
def user_can_do_run_as( self ):
run_as_users = self.app.config.get( "api_allow_run_as", "" ).split( "," )
return self.user and run_as_users and self.user.email in run_as_users
+
def get_toolbox(self):
"""Returns the application toolbox"""
return self.app.toolbox
+
@base.lazy_property
def template_context( self ):
return dict()
+
@property
def model( self ):
return self.app.model
+
def make_form_data( self, name, **kwargs ):
rval = self.template_context[name] = FormData()
rval.values.update( kwargs )
return rval
+
def set_message( self, message, type=None ):
"""
Convenience method for setting the 'message' and 'message_type'
@@ -845,12 +903,14 @@
self.template_context['message'] = message
if type:
self.template_context['status'] = type
+
def get_message( self ):
"""
Convenience method for getting the 'message' element of the template
context.
"""
return self.template_context['message']
+
def show_message( self, message, type='info', refresh_frames=[], cont=None, use_panels=False, active_view="" ):
"""
Convenience method for displaying a simple page with a single message.
@@ -862,21 +922,25 @@
refreshed when the message is displayed
"""
return self.fill_template( "message.mako", status=type, message=message, refresh_frames=refresh_frames, cont=cont, use_panels=use_panels, active_view=active_view )
+
def show_error_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an error message. See `show_message`.
"""
return self.show_message( message, 'error', refresh_frames, use_panels=use_panels, active_view=active_view )
+
def show_ok_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an ok message. See `show_message`.
"""
return self.show_message( message, 'done', refresh_frames, use_panels=use_panels, active_view=active_view )
+
def show_warn_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an warn message. See `show_message`.
"""
return self.show_message( message, 'warning', refresh_frames, use_panels=use_panels, active_view=active_view )
+
def show_form( self, form, header=None, template="form.mako", use_panels=False, active_view="" ):
"""
Convenience method for displaying a simple page with a single HTML
@@ -884,6 +948,7 @@
"""
return self.fill_template( template, form=form, header=header, use_panels=( form.use_panels or use_panels ),
active_view=active_view )
+
def fill_template(self, filename, **kwargs):
"""
Fill in a template, putting any keyword arguments on the context.
@@ -897,6 +962,7 @@
template = Template( file=os.path.join(self.app.config.template_path, filename),
searchList=[kwargs, self.template_context, dict(caller=self, t=self, h=helpers, util=util, request=self.request, response=self.response, app=self.app)] )
return str( template )
+
def fill_template_mako( self, filename, **kwargs ):
template = self.webapp.mako_template_lookup.get_template( filename )
template.output_encoding = 'utf-8'
@@ -904,6 +970,7 @@
data.update( self.template_context )
data.update( kwargs )
return template.render( **data )
+
def stream_template_mako( self, filename, **kwargs ):
template = self.webapp.mako_template_lookup.get_template( filename )
template.output_encoding = 'utf-8'
@@ -921,6 +988,7 @@
template.render_context( context )
return []
return render
+
def fill_template_string(self, template_string, context=None, **kwargs):
"""
Fill in a template, putting any keyword arguments on the context.
@@ -960,6 +1028,11 @@
def ncbi_builds( self ):
return util.dlnames['ncbi']
+ @property
+ def user_ftp_dir( self ):
+ identifier = self.app.config.ftp_upload_dir_identifier
+ return os.path.join( self.app.config.ftp_upload_dir, getattr(self.user, identifier) )
+
def db_dataset_for( self, dbkey ):
"""
Returns the db_file dataset associated/needed by `dataset`, or `None`.
@@ -983,6 +1056,7 @@
return True
return False
+
class FormBuilder( object ):
"""
Simple class describing an HTML form
@@ -994,17 +1068,22 @@
self.submit_text = submit_text
self.inputs = []
self.use_panels = use_panels
+
def add_input( self, type, name, label, value=None, error=None, help=None, use_label=True ):
self.inputs.append( FormInput( type, label, name, value, error, help, use_label ) )
return self
+
def add_text( self, name, label, value=None, error=None, help=None ):
return self.add_input( 'text', label, name, value, error, help )
+
def add_password( self, name, label, value=None, error=None, help=None ):
return self.add_input( 'password', label, name, value, error, help )
+
def add_select( self, name, label, value=None, options=[], error=None, help=None, use_label=True ):
self.inputs.append( SelectInput( name, label, value=value, options=options, error=error, help=help, use_label=use_label ) )
return self
+
class FormInput( object ):
"""
Simple class describing a form input element
@@ -1018,12 +1097,14 @@
self.help = help
self.use_label = use_label
+
class SelectInput( FormInput ):
""" A select form input. """
def __init__( self, name, label, value=None, options=[], error=None, help=None, use_label=True ):
FormInput.__init__( self, "select", name, label, value=value, error=error, help=help, use_label=use_label )
self.options = options
+
class FormData( object ):
"""
Class for passing data about a form to a template, very rudimentary, could
@@ -1033,6 +1114,7 @@
self.values = Bunch()
self.errors = Bunch()
+
class Bunch( dict ):
"""
Bunch based on a dict
@@ -1042,3 +1124,4 @@
return self[key]
def __setattr__( self, key, value ):
self[key] = value
+
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/90e18fe3eb82/
Changeset: 90e18fe3eb82
User: dannon
Date: 2013-04-18 23:57:52
Summary: Merge
Affected #: 4 files
diff -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 -r 90e18fe3eb822d7b9380b554cd7464f083f0e931 static/scripts/packed/viz/trackster/painters.js
--- a/static/scripts/packed/viz/trackster/painters.js
+++ b/static/scripts/packed/viz/trackster/painters.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<=second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height,delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-0.5)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":seq_offset+=cig_len;break;case"M":case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_center+5,b2_start,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8)}}return[0,0]}});var RefBasedReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){ReadPainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn)};extend(RefBasedReadPainter.prototype,ReadPainter.prototype,FeaturePainter,{draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),drawing_blocks=[];var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){var s_start=Math.floor(Math.max(-0.5*w_scale,(feature_start+block[0]-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(feature_start+block[1]-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};var VariantPainter=function(data,view_start,view_end,prefs,mode,base_color_fn){Painter.call(this,data,view_start,view_end,prefs,mode);this.base_color_fn=base_color_fn;this.divider_height=1};extend(VariantPainter.prototype,Painter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}return height},get_required_height:function(rows_required,width){var height=this.prefs.summary_height;if(this.prefs.show_sample_data){height+=this.divider_height;if(this.data.length!==0){height+=(this.data[0][7].match(/,/g).length+1)*this.get_row_height()}}return height},draw:function(ctx,width,height,w_scale){var locus_data,pos,id,ref,alt,qual,filter,sample_gts,allele_counts,variant,draw_x_start,char_x_start,draw_y_start,genotype,base_px=Math.max(1,Math.floor(w_scale)),row_height=(this.mode==="Squish"?SQUISH_TRACK_HEIGHT:PACK_TRACK_HEIGHT),feature_height=(w_scale<0.1?row_height:(this.mode==="Squish"?SQUISH_FEATURE_HEIGHT:PACK_FEATURE_HEIGHT)),j;if(this.prefs.show_sample_data){ctx.fillStyle="#F3F3F3";ctx.globalAlpha=1;ctx.fillRect(0,this.prefs.summary_height-this.divider_height,width,this.divider_height)}ctx.textAlign="center";for(var i=0;i<this.data.length;i++){locus_data=this.data[i];pos=locus_data[1];alt=locus_data[4].split(",");sample_gts=locus_data[7].split(",");allele_counts=locus_data.slice(8);draw_x_start=Math.floor(Math.max(-0.5*w_scale,(pos-this.view_start-0.5)*w_scale));char_x_start=Math.floor(Math.max(0,(pos-this.view_start)*w_scale));ctx.fillStyle="#999999";ctx.fillRect(draw_x_start,0,base_px,this.prefs.summary_height);draw_y_start=this.prefs.summary_height;for(j=0;j<alt.length;j++){ctx.fillStyle=this.base_color_fn(alt[j]);allele_frac=allele_counts/sample_gts.length;draw_height=Math.ceil(this.prefs.summary_height*allele_frac);ctx.fillRect(draw_x_start,draw_y_start-draw_height,base_px,draw_height);draw_y_start-=draw_height}if(!this.prefs.show_sample_data){continue}draw_y_start=this.prefs.summary_height+this.divider_height;for(j=0;j<sample_gts.length;j++,draw_y_start+=row_height){genotype=(sample_gts[j]?sample_gts[j].split(/\/|\|/):["0","0"]);variant=null;if(genotype[0]===genotype[1]){if(genotype[0]==="."){}else{if(genotype[0]!=="0"){variant=alt[parseInt(genotype[0],10)-1];ctx.globalAlpha=1}}}else{variant=(genotype[0]!=="0"?genotype[0]:genotype[1]);variant=alt[parseInt(variant,10)-1];ctx.globalAlpha=0.4}if(variant){ctx.fillStyle=this.base_color_fn(variant);if(this.mode==="Squish"||w_scale<ctx.canvas.manager.char_width_px){ctx.fillRect(draw_x_start,draw_y_start+1,base_px,feature_height)}else{ctx.fillText(variant,char_x_start,draw_y_start+row_height)}}}}}});return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,RefBasedReadPainter:RefBasedReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter,VariantPainter:VariantPainter}});
\ No newline at end of file
+define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<=second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height,delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-0.5)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":seq_offset+=cig_len;break;case"M":case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_center+5,b2_start,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8)}}return[0,0]}});var RefBasedReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){ReadPainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn)};extend(RefBasedReadPainter.prototype,ReadPainter.prototype,FeaturePainter,{draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),drawing_blocks=[];var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){var s_start=Math.floor(Math.max(-0.5*w_scale,(feature_start+block[0]-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(feature_start+block[1]-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};var VariantPainter=function(data,view_start,view_end,prefs,mode,base_color_fn){Painter.call(this,data,view_start,view_end,prefs,mode);this.base_color_fn=base_color_fn;this.divider_height=1};extend(VariantPainter.prototype,Painter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}return height},get_required_height:function(rows_required,width){var height=this.prefs.summary_height;if(this.prefs.show_sample_data){height+=this.divider_height;if(this.data.length!==0){var comma_match=this.data[0][7].match(/,/g);if(comma_match===null){comma_match=1}else{comma_match=comma_match.length+1}height+=(comma_match*this.get_row_height())}}return height},draw:function(ctx,width,height,w_scale){var locus_data,pos,id,ref,alt,qual,filter,sample_gts,allele_counts,variant,draw_x_start,char_x_start,draw_y_start,genotype,base_px=Math.max(1,Math.floor(w_scale)),row_height=(this.mode==="Squish"?SQUISH_TRACK_HEIGHT:PACK_TRACK_HEIGHT),feature_height=(w_scale<0.1?row_height:(this.mode==="Squish"?SQUISH_FEATURE_HEIGHT:PACK_FEATURE_HEIGHT)),j;if(this.prefs.show_sample_data){ctx.fillStyle="#F3F3F3";ctx.globalAlpha=1;ctx.fillRect(0,this.prefs.summary_height-this.divider_height,width,this.divider_height)}ctx.textAlign="center";for(var i=0;i<this.data.length;i++){locus_data=this.data[i];pos=locus_data[1];alt=locus_data[4].split(",");sample_gts=locus_data[7].split(",");allele_counts=locus_data.slice(8);draw_x_start=Math.floor(Math.max(-0.5*w_scale,(pos-this.view_start-0.5)*w_scale));char_x_start=Math.floor(Math.max(0,(pos-this.view_start)*w_scale));ctx.fillStyle="#999999";ctx.fillRect(draw_x_start,0,base_px,this.prefs.summary_height);draw_y_start=this.prefs.summary_height;for(j=0;j<alt.length;j++){ctx.fillStyle=this.base_color_fn(alt[j]);allele_frac=allele_counts/sample_gts.length;draw_height=Math.ceil(this.prefs.summary_height*allele_frac);ctx.fillRect(draw_x_start,draw_y_start-draw_height,base_px,draw_height);draw_y_start-=draw_height}if(!this.prefs.show_sample_data){continue}draw_y_start=this.prefs.summary_height+this.divider_height;for(j=0;j<sample_gts.length;j++,draw_y_start+=row_height){genotype=(sample_gts[j]?sample_gts[j].split(/\/|\|/):["0","0"]);variant=null;if(genotype[0]===genotype[1]){if(genotype[0]==="."){}else{if(genotype[0]!=="0"){variant=alt[parseInt(genotype[0],10)-1];ctx.globalAlpha=1}}}else{variant=(genotype[0]!=="0"?genotype[0]:genotype[1]);variant=alt[parseInt(variant,10)-1];ctx.globalAlpha=0.4}if(variant){ctx.fillStyle=this.base_color_fn(variant);if(this.mode==="Squish"||w_scale<ctx.canvas.manager.char_width_px){ctx.fillRect(draw_x_start,draw_y_start+1,base_px,feature_height)}else{ctx.fillText(variant,char_x_start,draw_y_start+row_height)}}}}}});return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,RefBasedReadPainter:RefBasedReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter,VariantPainter:VariantPainter}});
\ No newline at end of file
diff -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 -r 90e18fe3eb822d7b9380b554cd7464f083f0e931 static/scripts/packed/viz/trackster/tracks.js
--- a/static/scripts/packed/viz/trackster/tracks.js
+++ b/static/scripts/packed/viz/trackster/tracks.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,x,l,u,L,X,i){var q=ab.extend;var U=function(ac){return("isResolved" in ac)};var n={};var k=function(ac,ad){n[ac.attr("id")]=ad};var m=function(ac,ae,ag,af){ag=".group";var ad={};n[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=n[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}n[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);n[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));n[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,A=100,I=12000,R=400,K=5000,w=100,o="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",T="Ready for display",Q=10,H=20;function V(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var r=function(ad,ac,af){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];q(r.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(ad,ac,ae){r.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=p(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac]._draw()}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(ad,ac,af){q(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw(true)}ac.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var af=[];for(var ad=0;ad<this.drawables.length;ad++){af.push(this.drawables[ad].name)}var ae=new f(this.view,this.view,{name:this.name,drawables:this.drawables});var ac=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){z.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac,ae){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].request_draw(ac,ae)}}});var Y=Backbone.View.extend({initialize:function(ac){q(ac,{obj_type:"View"});z.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new x.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ac.prefs,onchange:function(){track.request_redraw(false,true)}})},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){x.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(p(ah,ac,ac))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-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/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").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_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_drawables(),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ac){return this.config.values[ac.toLowerCase()+"_color"]}});q(Y.prototype,z.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=w;var ac=this,ad=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+w+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+w+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-w});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+w});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();ae.request_redraw(true);for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad&&aj){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/,/g,"");ag=ag.replace(/:|\-/g," ");var ad=ag.split(/\s+/),af=ad[0],ae=(ad[1]?parseInt(ad[1],10):null),ac=(ad[2]?parseInt(ad[2],10):null);if(!ac){ae=ae-15;ac=ae+15}this.change_chrom(af,ae,ac)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw();var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){z.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ak,ac,aj,al){var ai=this,ah=(al?[al]:ai.drawables),ae;var ad;for(var ag=0;ag<ah.length;ag++){ad=ah[ag];ae=-1;for(var af=0;af<ai.tracks_to_be_redrawn.length;af++){if(ai.tracks_to_be_redrawn[af][0]===ad){ae=af;break}}if(ae<0){ai.tracks_to_be_redrawn.push([ad,ac,aj])}else{ai.tracks_to_be_redrawn[ag][1]=ac;ai.tracks_to_be_redrawn[ag][2]=aj}}if(!this.requested_redraw){requestAnimationFrame(function(){ai._redraw(ak)});this.requested_redraw=true}},_redraw:function(am){this.requested_redraw=false;var aj=this.low,af=this.high;if(aj<this.max_low){aj=this.max_low}if(af>this.max_high){af=this.max_high}var al=this.high-this.low;if(this.high!==0&&al<this.min_separation){af=aj+this.min_separation}this.low=Math.floor(aj);this.high=Math.ceil(af);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ac=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=13;this.overview_box.css({left:ac,width:Math.max(an,ai)}).show();if(ai<an){this.overview_box.css("left",ac-(an-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ac,width:ai})}if(!am){var ae,ad,ak;for(var ag=0,ah=this.tracks_to_be_redrawn.length;ag<ah;ag++){ae=this.tracks_to_be_redrawn[ag][0];ad=this.tracks_to_be_redrawn[ag][1];ak=this.tracks_to_be_redrawn[ag][2];if(ae){ae._draw(ad,ak)}}this.tracks_to_be_redrawn=[];for(ag=0,ah=this.label_tracks.length;ag<ah;ag++){this.label_tracks[ag]._draw()}}},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ae){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ae.dataset_id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").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();view.resize_window();view.overview_drawable=null}});var s=function(ae,aj,af){this.track=ae;this.id=aj.id;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new N(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.dataset_id,action:"rerun",tool_id:ac.id},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new x.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.dataset_id,action:"rerun",tool_id:this.id,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new P(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new X.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(y+ag.message)}else{af(ag)}}})}});var N=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){N.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};q(F.prototype,{restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(l.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="float"){ag=parseFloat(ag)}else{if(ah.type==="int"){ag=parseInt(ag,10)}else{if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}}}if(ag!==ae.values[ah.key]){ae.values[ah.key]=ag;ad=true}}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ac,ah,ae,ad,af,ag){b.call(this,ac,ah,ae,ad,af);this.max_val=ag};q(j.prototype,b.prototype);var O=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new x.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?V(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){q(ae,{drag_handle_class:"draghandle"});r.call(this,ad,ac,ae);this.dataset=new X.Dataset(ae.dataset);this.dataset_id=this.dataset.get("id");this.hda_ldda=this.dataset.get("hda_ldda");this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new x.GenomeDataManager({dataset:this.dataset,genome:new x.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ae)||ae.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new x.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ac.dataset_id,hda_ldda:ac.hda_ldda,regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},set_dataset:function(ac){this.dataset=ac;this.data_manager.set("dataset",ac);this.dataset_id=ac.get("id");this.hda_ldda=ac.get("hda_ldda")},on_resize:function(){},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){r.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof S){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.content_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset_id){return}var ac=$.Deferred(),af={hda_ldda:ad.hda_ldda,data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(o);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(v);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(T);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when(ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;m(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new s(this,af.tool,af.tool_state):null);this.tile_cache=new x.Cache(Q);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(af.mode){this.change_mode(af.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw(true)},hide:true}]),copy:function(ac){var ad=this.to_dict();q(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;ac.tile_cache.clear();ac.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ad,ac){this.view.request_redraw(false,ad,ac,this)},before_draw:function(){},_draw:function(ad,ao){if(!this.can_draw()){return}var al=this.view.low,ah=this.view.high,aj=ah-al,ae=this.view.container.width(),aq=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;aq=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(al/(ag*R)),ak=true,ap=[],ai=function(ar){return(ar&&"track" in ar)};while((ac*R*ag)<ah){var am=this._get_tile_bounds(ac,ag),an=this.draw_helper(ad,am,ag,this.tiles_div,aq);if(ai(an)){ap.push(an)}else{ak=false}ac+=1}if(!ao){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;if(ak){this.tiles_div.children(".remove").remove();af.postdraw_actions(ap,ae,aq,ao)}},postdraw_actions:function(ad,ae,ag,ac){var af=ab.find(ad,function(ah){return ah.has_icons});if(af){ab.each(ad,function(ah){if(!ah.has_icons){ah.html_elt.css("padding-top",D)}})}},draw_helper:function(ac,af,ar,ah,ai,ao){var an=this,aw=this._gen_tile_cache_key(ai,af);if(!ao){ao={}}var av=(ac?undefined:an.tile_cache.get_elt(aw));if(av){an.show_tile(av,ah,ai);return av}var al=true;var at=an.data_manager.get_data(af,an.mode,ar,an.data_url_extra_params);if(U(at)){al=false}var aj;if(view.reference_track){aj=view.reference_track.data_manager.get_data(af,an.mode,ar,view.reference_track.data_url_extra_params);if(U(aj)){al=false}else{aj=view.reference_track.data_manager.subset_entry(aj,af)}}if(al){q(at,ao.more_tile_data);var ak=an.mode;if(ak==="Auto"&&an.get_mode){ak=an.get_mode(at);an.update_auto_mode(ak)}var ae=an.view.canvas_manager.new_canvas(),au=af.get("start"),ad=af.get("end"),ap=Math.ceil((ad-au)*ai)+an.left_offset,am=an.get_canvas_height(at,ak,ai,ap);ae.width=ap;ae.height=am;var aq=ae.getContext("2d");aq.translate(this.left_offset,0);var av=an.draw_tile(at,aq,ak,ar,af,ai,aj);if(av!==undefined){an.tile_cache.set_elt(aw,av);an.show_tile(av,ah,ai)}return av}var ag=$.Deferred();$.when(at,aj).then(function(){view.request_redraw(false,false,false,an);ag.resolve()});return ag},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},_draw_summary_tree_tile:function(ac,ae,ag,af,ah){var ad=new L.SummaryTreePainter(ac,ag.get("start"),ag.get("end"),this.prefs);ad.draw(ae,ae.canvas.width,ae.canvas.height,ah);return new j(this,ag,af,ae.canvas,ac.data,ac.max)},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah,ai){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{ah.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*R*ad),ag=Math.ceil(R*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){return true},can_subset:function(ac){return false},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new l.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset_id,hda_ldda:ad.hda_ldda},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var W=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};q(W.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ae=this.view,af=ae.high-ae.low,ai=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/ai)*ai,ag=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ah=(ac-ae.low)/af*ag;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ah-1}));ac+=ai}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){M.call(this,ad,ac,ag);this.drawables=[];if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=p(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ac){M.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:r.prototype.can_draw,draw_helper:function(ad,ah,av,aj,al,at){var aq=this,aB=this._gen_tile_cache_key(al,ah);if(!at){at={}}var aA=(ad?undefined:aq.tile_cache.get_elt(aB));if(aA){aq.show_tile(aA,aj,al);return aA}var ak=[],aq,ao=true,aw,am;for(var ax=0;ax<this.drawables.length;ax++){aq=this.drawables[ax];aw=aq.data_manager.get_data(ah,aq.mode,av,aq.data_url_extra_params);if(U(aw)){ao=false}ak.push(aw);am=null;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ah,aq.mode,av,view.reference_track.data_url_extra_params);if(U(am)){ao=false}}ak.push(am)}if(ao){q(aw,at.more_tile_data);this.tile_predraw_init();var ag=aq.view.canvas_manager.new_canvas(),ay=ah.get("start"),ae=ah.get("end"),az=0,ar=Math.ceil((ae-ay)*al)+this.left_offset,ap=0,af=[],ax;var ac=0;for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}af.push(an);ac=aq.get_canvas_height(aw,an,al,ar);if(ac>ap){ap=ac}}ag.width=ar;ag.height=(at.height?at.height:ap);az=0;var au=ag.getContext("2d");au.translate(this.left_offset,0);au.globalAlpha=0.5;au.globalCompositeOperation="source-over";for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];am=ak[az+1];aA=aq.draw_tile(aw,au,af[ax],av,ah,al,am)}this.tile_cache.set_elt(aB,aA);this.show_tile(aA,aj,al);return aA}var ai=$.Deferred(),aq=this;$.when.apply($,ak).then(function(){view.request_redraw(false,false,false,aq);ai.resolve()});return ai},show_group:function(){var af=new P(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw()},tile_predraw_init:function(){var af=Number.MAX_VALUE,ac=-af,ad;for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];if(ad instanceof h){if(ad.prefs.min_value<af){af=ad.prefs.min_value}if(ad.prefs.max_value>ac){ac=ad.prefs.max_value}}}for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];ad.prefs.min_value=af;ad.prefs.max_value=ac}},postdraw_actions:function(ae,ah,aj,ad){M.prototype.postdraw_actions.call(this,ae,ah,aj,ad);var ag=-1;for(var af=0;af<ae.length;af++){var ac=ae[af].html_elt.find("canvas").height();if(ac>ag){ag=ac}}for(var af=0;af<ae.length;af++){var ai=ae[af];if(ai.html_elt.find("canvas").height()!==ag){this.draw_helper(true,ai.index,ai.resolution,ai.html_elt.parent(),aj,{height:ag});ai.html_elt.remove()}}}});var B=function(ac){M.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ae,af,ac,ag,ah,ad){if(ah>this.view.canvas_manager.char_width_px){this.tiles_div.show();return M.prototype.draw_helper.call(this,ae,af,ac,ag,ah,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ac){return true},draw_tile:function(af,al,ag,ad,ai,am){var ae=this.data_manager.subset_entry(af,ai),ak=ae.data;var ac=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";for(var ah=0,aj=ak.length;ah<aj;ah++){al.fillStyle=this.view.get_base_color(ak[ah]);al.fillText(ak[ah],Math.floor(ah*am),10)}return new b(this,ai,ad,ac,ae)}});var h=function(ae,ad,af){var ac=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:l.get_random_color()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ac=this;ac.vertical_range=undefined;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.hda_ldda},function(ad){ac.container_div.addClass("line-track");var ag=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=ag.min,ai=ag.max;ae=Math.floor(Math.min(0,Math.max(ae,ag.mean-2*ag.sd)));ai=Math.ceil(Math.max(0,Math.min(ai,ag.mean+2*ag.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ai;$("#track_"+ac.dataset_id+"_minval").val(ac.prefs.min_value);$("#track_"+ac.dataset_id+"_maxval").val(ac.prefs.max_value)}ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.total_frequency=ag.total_frequency;ac.container_div.find(".yaxislabel").remove();var ah=$("<div/>").text(V(ac.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_min_value(aj)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ac.dataset_id+"_minval").prependTo(ac.container_div),af=$("<div/>").text(V(ac.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_max_value(aj)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ac.dataset_id+"_maxval").prependTo(ac.container_div)})},draw_tile:function(al,aj,ae,ad,ag,ak){var ac=aj.canvas,af=ag.get("start"),ai=ag.get("end"),ah=new L.LinePainter(al.data,af,ai,this.prefs,ae);ah.draw(aj,ac.width,ac.height,ak);return new b(this,ag,ad,ac,al.data)},can_subset:function(ac){return(ac.data[1][0]-ac.data[0][0]===1)}});var t=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;this.tile_cache.clear();this.request_draw()},draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,af,ae,ah);var ag=l.get_random_color(),ac=l.get_random_color([ag,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.tile_cache.clear();ad.set_painter_from_config();ad.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};q(c.prototype,r.prototype,M.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ar,am,ah,ag){M.prototype.postdraw_actions.call(this,ar,ag);var al=this,ao;if(al.mode==="Coverage"){var ad=-1;for(ao=0;ao<ar.length;ao++){var an=ar[ao].max_val;if(an>ad){ad=an}}for(ao=0;ao<ar.length;ao++){var au=ar[ao];if(au.max_val!==ad){au.html_elt.remove();al.draw_helper(true,au.index,au.resolution,au.html_elt.parent(),ah,{more_tile_data:{max:ad}})}}}if(al.filters_manager){var ai=al.filters_manager.filters;for(var aq=0;aq<ai.length;aq++){ai[aq].update_ui_elt()}var at=false,ac,aj;for(ao=0;ao<ar.length;ao++){if(ar[ao].data.length){ac=ar[ao].data[0];for(var aq=0;aq<ai.length;aq++){aj=ai[aq];if(aj.applies_to(ac)&&aj.min!==aj.max){at=true;break}}}}if(al.filters_available!==at){al.filters_available=at;if(!al.filters_available){al.filters_manager.hide()}al.update_icons()}}this.container_div.find(".yaxislabel").remove();var af=ar[0];if(af instanceof j){var ak=(this.prefs.histogram_max?this.prefs.histogram_max:af.max_val),ae=$("<div/>").text(ak).make_text_editable({num_cols:12,on_finish:function(av){$(".bs-tooltip").remove();var av=parseFloat(av);al.prefs.histogram_max=(!isNaN(av)?av:null);al.tile_cache.clear();al.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ae)}if(af instanceof O){var ap=true;for(ao=0;ao<ar.length;ao++){if(!ar[ao].all_slotted){ap=false;break}}if(!ap){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}else{if(ac==="summary_tree"){ac="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (u.FeatureSlotter)(ag,af,A,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ac.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(ac,ag,ah,ad){if(ag==="summary_tree"||ag==="Coverage"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(ao==="summary_tree"||ao==="Coverage"){return this._draw_summary_tree_tile(am,aq,af,ar,aj)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae,function(aD){return ap.view.get_base_color(aD)});var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new O(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="summary_tree"}else{if(ac.extra_info==="no_detail"||ac.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="summary_tree"||ac.message||ac.extra_info==="no_detail"){return false}return true}});var Z=function(ad,ac,ae){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,ad,ac,ae);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};q(Z.prototype,r.prototype,M.prototype,{draw_tile:function(ac,af,ai,ag,ah,aj){if(ac.dataset_type==="summary_tree"){return this._draw_summary_tree_tile(ac,af,ah,ag,aj)}else{var ae=this.view,ad=new (this.painter)(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai,function(ak){return ae.get_base_color(ak)});ad.draw(af,af.canvas.width,af.canvas.height,aj);return new b(this,ah,ag,af.canvas,ac.data)}},get_canvas_height:function(ac,af,ag,ad){if(ac.dataset_type==="summary_tree"){return this.summary_draw_height}else{var ae=new (this.painter)(ac.data,null,null,this.prefs,af);return ae.get_required_height()}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ai,ad,ak,ag){M.prototype.postdraw_actions.call(this,ai,ad,ak,ag);if(this.prefs.show_labels){if(this.container_div.find(".yaxislabel").length===0){var ac=10,aj=$("<div/>").text("Summary").addClass("yaxislabel top").css({"font-size":ac+"px"});this.container_div.prepend(aj);var ah=aj.position().top;aj.css("top",ah+(this.prefs.summary_height-ac)/2+"px");if(this.prefs.show_sample_data){var ae="";ab.each(this.dataset.get("metadata").get("sample_names"),function(al){ae+=(al+"<br>")});var af=$("<div/>").html(ae).addClass("yaxislabel top sample").css({top:ah+this.prefs.summary_height+2,});this.container_div.prepend(af)}}$(this.container_div).find(".sample").css("font-size",(this.mode==="Squish"?5:10)+"px");$(this.container_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel").remove()}}});var S=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=l.get_random_color(),ac=l.get_random_color([af,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=(ae.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};q(S.prototype,r.prototype,M.prototype,c.prototype);var d={CompositeTrack:f,DrawableGroup:P,DiagonalHeatmapTrack:t,FeatureTrack:c,LineTrack:h,ReadTrack:S,VariantTrack:Z,VcfTrack:Z};var p=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Y,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:S,VariantTrack:Z,CompositeTrack:f,object_from_template:p}});
\ No newline at end of file
+define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,x,l,u,L,X,i){var q=ab.extend;var U=function(ac){return("isResolved" in ac)};var n={};var k=function(ac,ad){n[ac.attr("id")]=ad};var m=function(ac,ae,ag,af){ag=".group";var ad={};n[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=n[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}n[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);n[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));n[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,A=100,I=12000,R=400,K=5000,w=100,o="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",T="Ready for display",Q=10,H=20;function V(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var r=function(ad,ac,af){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];q(r.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(ad,ac,ae){r.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=p(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac]._draw()}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(ad,ac,af){q(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw(true)}ac.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var af=[];for(var ad=0;ad<this.drawables.length;ad++){af.push(this.drawables[ad].name)}var ae=new f(this.view,this.view,{name:this.name,drawables:this.drawables});var ac=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){z.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac,ae){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].request_draw(ac,ae)}}});var Y=Backbone.View.extend({initialize:function(ac){q(ac,{obj_type:"View"});z.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new x.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ac.prefs,onchange:function(){track.request_redraw(false,true)}})},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){x.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(p(ah,ac,ac))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-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/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").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_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_drawables(),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ac){return this.config.values[ac.toLowerCase()+"_color"]||this.config.values.n_color}});q(Y.prototype,z.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=w;var ac=this,ad=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+w+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+w+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-w});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+w});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();ae.request_redraw(true);for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad&&aj){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/,/g,"");ag=ag.replace(/:|\-/g," ");var ad=ag.split(/\s+/),af=ad[0],ae=(ad[1]?parseInt(ad[1],10):null),ac=(ad[2]?parseInt(ad[2],10):null);if(!ac){ae=ae-15;ac=ae+15}this.change_chrom(af,ae,ac)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw();var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){z.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ak,ac,aj,al){var ai=this,ah=(al?[al]:ai.drawables),ae;var ad;for(var ag=0;ag<ah.length;ag++){ad=ah[ag];ae=-1;for(var af=0;af<ai.tracks_to_be_redrawn.length;af++){if(ai.tracks_to_be_redrawn[af][0]===ad){ae=af;break}}if(ae<0){ai.tracks_to_be_redrawn.push([ad,ac,aj])}else{ai.tracks_to_be_redrawn[ag][1]=ac;ai.tracks_to_be_redrawn[ag][2]=aj}}if(!this.requested_redraw){requestAnimationFrame(function(){ai._redraw(ak)});this.requested_redraw=true}},_redraw:function(am){this.requested_redraw=false;var aj=this.low,af=this.high;if(aj<this.max_low){aj=this.max_low}if(af>this.max_high){af=this.max_high}var al=this.high-this.low;if(this.high!==0&&al<this.min_separation){af=aj+this.min_separation}this.low=Math.floor(aj);this.high=Math.ceil(af);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ac=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=13;this.overview_box.css({left:ac,width:Math.max(an,ai)}).show();if(ai<an){this.overview_box.css("left",ac-(an-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ac,width:ai})}if(!am){var ae,ad,ak;for(var ag=0,ah=this.tracks_to_be_redrawn.length;ag<ah;ag++){ae=this.tracks_to_be_redrawn[ag][0];ad=this.tracks_to_be_redrawn[ag][1];ak=this.tracks_to_be_redrawn[ag][2];if(ae){ae._draw(ad,ak)}}this.tracks_to_be_redrawn=[];for(ag=0,ah=this.label_tracks.length;ag<ah;ag++){this.label_tracks[ag]._draw()}}},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ae){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ae.dataset_id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").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();view.resize_window();view.overview_drawable=null}});var s=function(ae,aj,af){this.track=ae;this.id=aj.id;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new N(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.dataset_id,action:"rerun",tool_id:ac.id},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new x.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.dataset_id,action:"rerun",tool_id:this.id,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new P(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new X.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(y+ag.message)}else{af(ag)}}})}});var N=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){N.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};q(F.prototype,{restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(l.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="float"){ag=parseFloat(ag)}else{if(ah.type==="int"){ag=parseInt(ag,10)}else{if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}}}if(ag!==ae.values[ah.key]){ae.values[ah.key]=ag;ad=true}}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ac,ah,ae,ad,af,ag){b.call(this,ac,ah,ae,ad,af);this.max_val=ag};q(j.prototype,b.prototype);var O=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new x.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?V(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){q(ae,{drag_handle_class:"draghandle"});r.call(this,ad,ac,ae);this.dataset=new X.Dataset(ae.dataset);this.dataset_id=this.dataset.get("id");this.hda_ldda=this.dataset.get("hda_ldda");this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new x.GenomeDataManager({dataset:this.dataset,genome:new x.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ae)||ae.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new x.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ac.dataset_id,hda_ldda:ac.hda_ldda,regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},set_dataset:function(ac){this.dataset=ac;this.data_manager.set("dataset",ac);this.dataset_id=ac.get("id");this.hda_ldda=ac.get("hda_ldda")},on_resize:function(){},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){r.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof S){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.content_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset_id){return}var ac=$.Deferred(),af={hda_ldda:ad.hda_ldda,data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(o);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(v);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(T);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when(ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;m(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new s(this,af.tool,af.tool_state):null);this.tile_cache=new x.Cache(Q);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(af.mode){this.change_mode(af.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw(true)},hide:true}]),copy:function(ac){var ad=this.to_dict();q(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;ac.tile_cache.clear();ac.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ad,ac){this.view.request_redraw(false,ad,ac,this)},before_draw:function(){},_draw:function(ad,ao){if(!this.can_draw()){return}var al=this.view.low,ah=this.view.high,aj=ah-al,ae=this.view.container.width(),aq=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;aq=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(al/(ag*R)),ak=true,ap=[],ai=function(ar){return(ar&&"track" in ar)};while((ac*R*ag)<ah){var am=this._get_tile_bounds(ac,ag),an=this.draw_helper(ad,am,ag,this.tiles_div,aq);if(ai(an)){ap.push(an)}else{ak=false}ac+=1}if(!ao){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;if(ak){this.tiles_div.children(".remove").remove();af.postdraw_actions(ap,ae,aq,ao)}},postdraw_actions:function(ad,ae,ag,ac){var af=ab.find(ad,function(ah){return ah.has_icons});if(af){ab.each(ad,function(ah){if(!ah.has_icons){ah.html_elt.css("padding-top",D)}})}},draw_helper:function(ac,af,ar,ah,ai,ao){var an=this,aw=this._gen_tile_cache_key(ai,af);if(!ao){ao={}}var av=(ac?undefined:an.tile_cache.get_elt(aw));if(av){an.show_tile(av,ah,ai);return av}var al=true;var at=an.data_manager.get_data(af,an.mode,ar,an.data_url_extra_params);if(U(at)){al=false}var aj;if(view.reference_track){aj=view.reference_track.data_manager.get_data(af,an.mode,ar,view.reference_track.data_url_extra_params);if(U(aj)){al=false}else{aj=view.reference_track.data_manager.subset_entry(aj,af)}}if(al){q(at,ao.more_tile_data);var ak=an.mode;if(ak==="Auto"&&an.get_mode){ak=an.get_mode(at);an.update_auto_mode(ak)}var ae=an.view.canvas_manager.new_canvas(),au=af.get("start"),ad=af.get("end"),ap=Math.ceil((ad-au)*ai)+an.left_offset,am=an.get_canvas_height(at,ak,ai,ap);ae.width=ap;ae.height=am;var aq=ae.getContext("2d");aq.translate(this.left_offset,0);var av=an.draw_tile(at,aq,ak,ar,af,ai,aj);if(av!==undefined){an.tile_cache.set_elt(aw,av);an.show_tile(av,ah,ai)}return av}var ag=$.Deferred();$.when(at,aj).then(function(){view.request_redraw(false,false,false,an);ag.resolve()});return ag},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},_draw_summary_tree_tile:function(ac,ae,ag,af,ah){var ad=new L.SummaryTreePainter(ac,ag.get("start"),ag.get("end"),this.prefs);ad.draw(ae,ae.canvas.width,ae.canvas.height,ah);return new j(this,ag,af,ae.canvas,ac.data,ac.max)},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah,ai){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{ah.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*R*ad),ag=Math.ceil(R*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){return true},can_subset:function(ac){return false},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new l.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset_id,hda_ldda:ad.hda_ldda},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var W=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};q(W.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ae=this.view,af=ae.high-ae.low,ai=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/ai)*ai,ag=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ah=(ac-ae.low)/af*ag;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ah-1}));ac+=ai}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){M.call(this,ad,ac,ag);this.drawables=[];if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=p(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ac){M.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:r.prototype.can_draw,draw_helper:function(ad,ah,av,aj,al,at){var aq=this,aB=this._gen_tile_cache_key(al,ah);if(!at){at={}}var aA=(ad?undefined:aq.tile_cache.get_elt(aB));if(aA){aq.show_tile(aA,aj,al);return aA}var ak=[],aq,ao=true,aw,am;for(var ax=0;ax<this.drawables.length;ax++){aq=this.drawables[ax];aw=aq.data_manager.get_data(ah,aq.mode,av,aq.data_url_extra_params);if(U(aw)){ao=false}ak.push(aw);am=null;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ah,aq.mode,av,view.reference_track.data_url_extra_params);if(U(am)){ao=false}}ak.push(am)}if(ao){q(aw,at.more_tile_data);this.tile_predraw_init();var ag=aq.view.canvas_manager.new_canvas(),ay=ah.get("start"),ae=ah.get("end"),az=0,ar=Math.ceil((ae-ay)*al)+this.left_offset,ap=0,af=[],ax;var ac=0;for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}af.push(an);ac=aq.get_canvas_height(aw,an,al,ar);if(ac>ap){ap=ac}}ag.width=ar;ag.height=(at.height?at.height:ap);az=0;var au=ag.getContext("2d");au.translate(this.left_offset,0);au.globalAlpha=0.5;au.globalCompositeOperation="source-over";for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];am=ak[az+1];aA=aq.draw_tile(aw,au,af[ax],av,ah,al,am)}this.tile_cache.set_elt(aB,aA);this.show_tile(aA,aj,al);return aA}var ai=$.Deferred(),aq=this;$.when.apply($,ak).then(function(){view.request_redraw(false,false,false,aq);ai.resolve()});return ai},show_group:function(){var af=new P(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw()},tile_predraw_init:function(){var af=Number.MAX_VALUE,ac=-af,ad;for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];if(ad instanceof h){if(ad.prefs.min_value<af){af=ad.prefs.min_value}if(ad.prefs.max_value>ac){ac=ad.prefs.max_value}}}for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];ad.prefs.min_value=af;ad.prefs.max_value=ac}},postdraw_actions:function(ae,ah,aj,ad){M.prototype.postdraw_actions.call(this,ae,ah,aj,ad);var ag=-1;for(var af=0;af<ae.length;af++){var ac=ae[af].html_elt.find("canvas").height();if(ac>ag){ag=ac}}for(var af=0;af<ae.length;af++){var ai=ae[af];if(ai.html_elt.find("canvas").height()!==ag){this.draw_helper(true,ai.index,ai.resolution,ai.html_elt.parent(),aj,{height:ag});ai.html_elt.remove()}}}});var B=function(ac){M.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.reference_track=this;this.left_offset=200;this.visible_height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ae,af,ac,ag,ah,ad){if(ah>this.view.canvas_manager.char_width_px){this.tiles_div.show();return M.prototype.draw_helper.call(this,ae,af,ac,ag,ah,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ac){return true},draw_tile:function(af,al,ag,ad,ai,am){var ae=this.data_manager.subset_entry(af,ai),ak=ae.data;var ac=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";for(var ah=0,aj=ak.length;ah<aj;ah++){al.fillStyle=this.view.get_base_color(ak[ah]);al.fillText(ak[ah],Math.floor(ah*am),10)}return new b(this,ai,ad,ac,ae)}});var h=function(ae,ad,af){var ac=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:l.get_random_color()},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ac=this;ac.vertical_range=undefined;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.hda_ldda},function(ad){ac.container_div.addClass("line-track");var ag=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=ag.min,ai=ag.max;ae=Math.floor(Math.min(0,Math.max(ae,ag.mean-2*ag.sd)));ai=Math.ceil(Math.max(0,Math.min(ai,ag.mean+2*ag.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ai;$("#track_"+ac.dataset_id+"_minval").val(ac.prefs.min_value);$("#track_"+ac.dataset_id+"_maxval").val(ac.prefs.max_value)}ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.total_frequency=ag.total_frequency;ac.container_div.find(".yaxislabel").remove();var ah=$("<div/>").text(V(ac.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_min_value(aj)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ac.dataset_id+"_minval").prependTo(ac.container_div),af=$("<div/>").text(V(ac.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_max_value(aj)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ac.dataset_id+"_maxval").prependTo(ac.container_div)})},draw_tile:function(al,aj,ae,ad,ag,ak){var ac=aj.canvas,af=ag.get("start"),ai=ag.get("end"),ah=new L.LinePainter(al.data,af,ai,this.prefs,ae);ah.draw(aj,ac.width,ac.height,ak);return new b(this,ag,ad,ac,al.data)},can_subset:function(ac){return(ac.data[1][0]-ac.data[0][0]===1)}});var t=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;this.tile_cache.clear();this.request_draw()},draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,af,ae,ah);var ag=l.get_random_color(),ac=l.get_random_color([ag,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.tile_cache.clear();ad.set_painter_from_config();ad.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};q(c.prototype,r.prototype,M.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ar,am,ah,ag){M.prototype.postdraw_actions.call(this,ar,ag);var al=this,ao;if(al.mode==="Coverage"){var ad=-1;for(ao=0;ao<ar.length;ao++){var an=ar[ao].max_val;if(an>ad){ad=an}}for(ao=0;ao<ar.length;ao++){var au=ar[ao];if(au.max_val!==ad){au.html_elt.remove();al.draw_helper(true,au.index,au.resolution,au.html_elt.parent(),ah,{more_tile_data:{max:ad}})}}}if(al.filters_manager){var ai=al.filters_manager.filters;for(var aq=0;aq<ai.length;aq++){ai[aq].update_ui_elt()}var at=false,ac,aj;for(ao=0;ao<ar.length;ao++){if(ar[ao].data.length){ac=ar[ao].data[0];for(var aq=0;aq<ai.length;aq++){aj=ai[aq];if(aj.applies_to(ac)&&aj.min!==aj.max){at=true;break}}}}if(al.filters_available!==at){al.filters_available=at;if(!al.filters_available){al.filters_manager.hide()}al.update_icons()}}this.container_div.find(".yaxislabel").remove();var af=ar[0];if(af instanceof j){var ak=(this.prefs.histogram_max?this.prefs.histogram_max:af.max_val),ae=$("<div/>").text(ak).make_text_editable({num_cols:12,on_finish:function(av){$(".bs-tooltip").remove();var av=parseFloat(av);al.prefs.histogram_max=(!isNaN(av)?av:null);al.tile_cache.clear();al.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ae)}if(af instanceof O){var ap=true;for(ao=0;ao<ar.length;ao++){if(!ar[ao].all_slotted){ap=false;break}}if(!ap){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}else{if(ac==="summary_tree"){ac="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (u.FeatureSlotter)(ag,af,A,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ac.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(ac,ag,ah,ad){if(ag==="summary_tree"||ag==="Coverage"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(ao==="summary_tree"||ao==="Coverage"){return this._draw_summary_tree_tile(am,aq,af,ar,aj)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae,function(aD){return ap.view.get_base_color(aD)});var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new O(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="summary_tree"}else{if(ac.extra_info==="no_detail"||ac.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="summary_tree"||ac.message||ac.extra_info==="no_detail"){return false}return true}});var Z=function(ad,ac,ae){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,ad,ac,ae);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"show_labels",label:"Show summary and sample labels",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};q(Z.prototype,r.prototype,M.prototype,{draw_tile:function(ac,af,ai,ag,ah,aj){if(ac.dataset_type==="summary_tree"){return this._draw_summary_tree_tile(ac,af,ah,ag,aj)}else{var ae=this.view,ad=new (this.painter)(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai,function(ak){return ae.get_base_color(ak)});ad.draw(af,af.canvas.width,af.canvas.height,aj);return new b(this,ah,ag,af.canvas,ac.data)}},get_canvas_height:function(ac,af,ag,ad){if(ac.dataset_type==="summary_tree"){return this.summary_draw_height}else{var ae=new (this.painter)(ac.data,null,null,this.prefs,af);return ae.get_required_height()}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ai,ad,ak,ag){M.prototype.postdraw_actions.call(this,ai,ad,ak,ag);if(this.prefs.show_labels){if(this.container_div.find(".yaxislabel").length===0){var ac=10,aj=$("<div/>").text("Summary").addClass("yaxislabel top").css({"font-size":ac+"px"});this.container_div.prepend(aj);var ah=aj.position().top;aj.css("top",ah+(this.prefs.summary_height-ac)/2+"px");if(this.prefs.show_sample_data){var ae="";ab.each(this.dataset.get("metadata").get("sample_names"),function(al){ae+=(al+"<br>")});var af=$("<div/>").html(ae).addClass("yaxislabel top sample").css({top:ah+this.prefs.summary_height+2,});this.container_div.prepend(af)}}$(this.container_div).find(".sample").css("font-size",(this.mode==="Squish"?5:10)+"px");$(this.container_div).find(".yaxislabel").css("color",this.prefs.label_color)}else{this.container_div.find(".yaxislabel").remove()}}});var S=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=l.get_random_color(),ac=l.get_random_color([af,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=(ae.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};q(S.prototype,r.prototype,M.prototype,c.prototype);var d={CompositeTrack:f,DrawableGroup:P,DiagonalHeatmapTrack:t,FeatureTrack:c,LineTrack:h,ReadTrack:S,VariantTrack:Z,VcfTrack:Z};var p=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Y,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:S,VariantTrack:Z,CompositeTrack:f,object_from_template:p}});
\ No newline at end of file
diff -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 -r 90e18fe3eb822d7b9380b554cd7464f083f0e931 static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -1577,7 +1577,14 @@
height += this.divider_height;
if (this.data.length !== 0) {
// Sample data is separated by commas, so this computes # of samples:
- height += (this.data[0][7].match(/,/g).length + 1) * this.get_row_height();
+ var comma_match = this.data[0][7].match(/,/g);
+ if ( comma_match === null ) {
+ comma_match = 1;
+ }
+ else {
+ comma_match = comma_match.length + 1;
+ }
+ height += ( comma_match * this.get_row_height() );
}
}
return height;
diff -r 8f0a3c34af315d5e5b47c6762a0241bca7c7df64 -r 90e18fe3eb822d7b9380b554cd7464f083f0e931 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -1120,7 +1120,7 @@
},
get_base_color: function(base) {
- return this.config.values[ base.toLowerCase() + '_color' ];
+ return this.config.values[ base.toLowerCase() + '_color' ] || this.config.values[ 'n_color' ];
}
});
https://bitbucket.org/galaxy/galaxy-central/commits/93e4d0e6f1fe/
Changeset: 93e4d0e6f1fe
User: dannon
Date: 2013-04-22 15:19:54
Summary: Merge.
Affected #: 43 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a456f964cef1/
Changeset: a456f964cef1
User: dannon
Date: 2013-04-29 19:09:15
Summary: Additional migration changes necessary to start w/ a clean sqlite database.
Affected #: 11 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/d4edf64c9a19/
Changeset: d4edf64c9a19
User: dannon
Date: 2013-04-29 19:23:44
Summary: Merge
Affected #: 66 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/ccc0c58e25f6/
Changeset: ccc0c58e25f6
User: dannon
Date: 2013-04-29 22:38:02
Summary: Drop cloud tables in order to avoid hacky cascade drop.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/3b7cd8cedca1/
Changeset: 3b7cd8cedca1
User: dannon
Date: 2013-04-30 15:32:19
Summary: History API: Import sanitize_html directly instead of using util reference
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/107e465405ff/
Changeset: 107e465405ff
User: dannon
Date: 2013-04-30 20:53:17
Summary: Migration script 0003, prevent sqlite from attempting to add a ForeignKey
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/b956501df7ee/
Changeset: b956501df7ee
User: dannon
Date: 2013-04-30 20:53:48
Summary: Migration script 0020, prevent sqlite from attempting to add a ForeignKey
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/6c28563c709f/
Changeset: 6c28563c709f
User: dannon
Date: 2013-04-30 20:55:04
Summary: Migration script 0036, 0038, use '0' as boolean for sqlite.
Affected #: 2 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/45682ff7f6e9/
Changeset: 45682ff7f6e9
User: dannon
Date: 2013-04-30 20:56:43
Summary: Sqlalchemy-migrate doesn't properly handle alter table add column w/ nullable=false in sqlite, skip constraint for dialect
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/6712944bc955/
Changeset: 6712944bc955
User: dannon
Date: 2013-04-30 20:57:56
Summary: Migration scripts 0037, 0068, 0073 -- skip foreign key creation for sqlite
Affected #: 3 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/0a3965f5953e/
Changeset: 0a3965f5953e
User: dannon
Date: 2013-04-30 20:58:06
Summary: merge
Affected #: 16 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/207271b8a75c/
Changeset: 207271b8a75c
User: dannon
Date: 2013-05-01 00:56:34
Summary: Update migration script 100 to use the new dialect name 'postgresql' -- still compatible with older versions too with 'postgres'.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/27328200c337/
Changeset: 27328200c337
User: dannon
Date: 2013-05-01 01:08:44
Summary: Remove assignmapper imports from migration 0080 -- it's gone now.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/2c0552e5e65d/
Changeset: 2c0552e5e65d
User: dannon
Date: 2013-05-01 01:09:17
Summary: Migration 0084 -- don't add ForeignKey for sqlite.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/d39d9b951ce3/
Changeset: d39d9b951ce3
User: dannon
Date: 2013-05-01 01:10:56
Summary: Fix conflicting util.sanitize_text import in controllers/admin.py
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/825cf4130d0e/
Changeset: 825cf4130d0e
User: dannon
Date: 2013-05-01 01:11:56
Summary: Use migrate_engine.execute() instead of the nonexistent db_session -- migration 0100
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/905d2c745ea2/
Changeset: 905d2c745ea2
User: dannon
Date: 2013-05-01 01:12:59
Summary: Remove commented out db_session creations.
Affected #: 35 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/01680aede3b8/
Changeset: 01680aede3b8
User: dannon
Date: 2013-05-01 01:18:37
Summary: Migration 0062 -- fix db_session/migrate_engine change.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/921d6de41db0/
Changeset: 921d6de41db0
User: dannon
Date: 2013-05-01 01:54:45
Summary: Migration script 0102, skip dropping uninstalled column in tool_dependency table under sqlite -- sqlalchemy_migrate check constraint boolean issue causes total failure, dropping of the table.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/c46d23ca1fba/
Changeset: c46d23ca1fba
User: dannon
Date: 2013-05-01 02:18:29
Summary: Prevent ambiguous util import in requests_common.py, clean up other imports.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a576bc133d10/
Changeset: a576bc133d10
User: dannon
Date: 2013-05-01 02:19:00
Summary: Sort imports.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/15741f359890/
Changeset: 15741f359890
User: dannon
Date: 2013-05-01 02:22:46
Summary: Async controller -- clean up imports, remove *'s, fix potentially ambiguous util import.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a0f0be48b6ae/
Changeset: a0f0be48b6ae
User: dannon
Date: 2013-05-01 05:24:55
Summary: Functional test setup fix for sqlite -- pool_size is an invalid option in sqlalchemy7+.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a0b42d693905/
Changeset: a0b42d693905
User: dannon
Date: 2013-05-01 06:04:56
Summary: Admin controller -- fix ambiguous 'util' import; remove all import *'s and refactor
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/34e803f4780e/
Changeset: 34e803f4780e
User: dannon
Date: 2013-05-01 06:05:14
Summary: History controller -- fix ambiguous 'util' import; remove all import *'s and refactor
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/1e056f107ed8/
Changeset: 1e056f107ed8
User: dannon
Date: 2013-05-01 06:14:41
Summary: LibraryAdmin controller - fix ambiguous util imports, remove * imports.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/40859e3e342f/
Changeset: 40859e3e342f
User: dannon
Date: 2013-05-01 06:16:08
Summary: LibraryAdmin: Remove python 2.5 'set' compatability cruft.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a3aefe9c4e12/
Changeset: a3aefe9c4e12
User: dannon
Date: 2013-05-01 06:24:08
Summary: Remove import * in base admin controller. Also fixes ambiguous 'util'
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/83d68671f55f/
Changeset: 83d68671f55f
User: dannon
Date: 2013-05-01 06:24:56
Summary: Remove commented cruft left over from refactoring.
Affected #: 2 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/bc525c2a6324/
Changeset: bc525c2a6324
User: dannon
Date: 2013-05-01 06:25:25
Summary: Merge
Affected #: 8 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/8a41333e136e/
Changeset: 8a41333e136e
User: dannon
Date: 2013-05-01 06:51:30
Summary: Refactor import *'s in library_common; fixes ambiguous util in namespace
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/06ada1cc941b/
Changeset: 06ada1cc941b
User: dannon
Date: 2013-05-01 06:52:57
Summary: Eliminate year old debugging code for library timing.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/7eb20069db80/
Changeset: 7eb20069db80
User: dannon
Date: 2013-05-01 20:01:35
Summary: Silence log.debug outputs for get_history() returning None, since it's both valid and fairly common.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/8b6a0c0f1fa8/
Changeset: 8b6a0c0f1fa8
User: dannon
Date: 2013-05-01 22:28:34
Summary: Remove * import, fixes duplicate 'util' import from sqlalchemy
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/6a0bbaec9518/
Changeset: 6a0bbaec9518
User: dannon
Date: 2013-05-01 22:29:18
Summary: Fix quota manager to flush properly when 'flush_needed' is set.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/556cf543e6b5/
Changeset: 556cf543e6b5
User: dannon
Date: 2013-05-01 22:59:29
Summary: Remove spurious 'Tool did not define error code...' debug statement -- not useful, almost nothing defines one.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/992d80a121d2/
Changeset: 992d80a121d2
User: dannon
Date: 2013-05-01 23:13:42
Summary: Remove duplicate imports from tags controller
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/867a491271c9/
Changeset: 867a491271c9
User: dannon
Date: 2013-05-02 04:32:57
Summary: library_common: Fix StreamBall import mangled previously.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/8decea3601cf/
Changeset: 8decea3601cf
User: dannon
Date: 2013-05-02 05:16:57
Summary: Tag controller: Fix abstract query to correctly map to item_class.id instead of strings. This resolves 'ambiguous column' issues.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/86ec749724eb/
Changeset: 86ec749724eb
User: dannon
Date: 2013-05-02 05:19:36
Summary: Library Security, update query for retrieving items.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a8affc656b7a/
Changeset: a8affc656b7a
User: dannon
Date: 2013-05-02 06:41:04
Summary: Update toolshed migrations to work with recent sqlalchemy-migrate.
Affected #: 18 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/42b8b46051ff/
Changeset: 42b8b46051ff
User: dannon
Date: 2013-05-02 06:44:01
Summary: Strip trailing whitespace from toolshed migrations.
Affected #: 16 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/f0913a8a851f/
Changeset: f0913a8a851f
User: dannon
Date: 2013-05-02 06:46:28
Summary: Strip trailing whitespace from galaxy migrations.
Affected #: 64 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/013988cc1252/
Changeset: 013988cc1252
User: dannon
Date: 2013-05-02 15:15:24
Summary: Remove assign_mapper usage in migrate0005 -- was succeeding previously due to a left-behind assign_mapper.pyc
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/8ff0e63b00ac/
Changeset: 8ff0e63b00ac
User: dannon
Date: 2013-05-02 16:01:35
Summary: Update toolshed mappings to use regular mapper, vs assign_mapper
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/93469936a3c0/
Changeset: 93469936a3c0
User: dannon
Date: 2013-05-02 16:45:44
Summary: Fix toolshed functional tests to not use 'pool_size' with sqlite
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a32f714d8b1d/
Changeset: a32f714d8b1d
User: dannon
Date: 2013-05-02 17:52:23
Summary: Fix category queries in toolshed repository controller
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/3d69ec4cf0e2/
Changeset: 3d69ec4cf0e2
User: dannon
Date: 2013-05-02 18:22:12
Summary: Merge with -central
Affected #: 37 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/44a7f7d0f607/
Changeset: 44a7f7d0f607
User: dannon
Date: 2013-05-02 18:51:50
Summary: Fix (hack) for a suspected circular import preventing tool shed functional tests from running in some environments
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/62c7b3379f10/
Changeset: 62c7b3379f10
User: dannon
Date: 2013-05-02 19:23:57
Summary: Model: galaxy.util.as_bool absolute import, fix from bad merge.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/ee075fec3e42/
Changeset: ee075fec3e42
User: dannon
Date: 2013-05-02 19:26:20
Summary: viz/genomes: Fix query.get()
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/cfb896a3558e/
Changeset: cfb896a3558e
User: dannon
Date: 2013-05-02 19:27:52
Summary: base admin controller: Fix query.get()
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/732ad82a75f0/
Changeset: 732ad82a75f0
User: dannon
Date: 2013-05-02 19:29:02
Summary: data manager controller: Fix query.get()
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/3c0497c86f98/
Changeset: 3c0497c86f98
User: dannon
Date: 2013-05-02 19:30:47
Summary: root controller: Fix query.get()
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/259949f32a32/
Changeset: 259949f32a32
User: dannon
Date: 2013-05-02 19:32:26
Summary: library common: Fix query.get()
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/9dfa253aa709/
Changeset: 9dfa253aa709
User: dannon
Date: 2013-05-02 19:34:06
Summary: visualization controller: Fix query.get()
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/872a9e3780d3/
Changeset: 872a9e3780d3
User: dannon
Date: 2013-05-02 19:48:56
Summary: Fix all but the metadata.py assign_mapper-> object.get() query issue -- should be the last one
Affected #: 3 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/07e265b822e8/
Changeset: 07e265b822e8
User: dannon
Date: 2013-05-02 19:55:34
Summary: Remove commented out debugging cruft in model/mapping.py
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/8149ff6f163d/
Changeset: 8149ff6f163d
User: dannon
Date: 2013-05-02 20:30:25
Summary: Model whitespace cleanup.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/fcdb1361eb71/
Changeset: fcdb1361eb71
User: dannon
Date: 2013-05-02 20:30:40
Summary: merge
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/d2a4a4e41650/
Changeset: d2a4a4e41650
User: dannon
Date: 2013-05-02 21:33:15
Summary: Merge
Affected #: 9 files
Diff not available.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Attempt to standardize the main page title for repository pages in the tool shed by displaying the repository name.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2de7ce3e39fd/
Changeset: 2de7ce3e39fd
User: greg
Date: 2013-05-02 21:20:02
Summary: Attempt to standardize the main page title for repository pages in the tool shed by displaying the repository name.
Affected #: 8 files
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/browse_repository.mako
--- a/templates/webapps/tool_shed/repository/browse_repository.mako
+++ b/templates/webapps/tool_shed/repository/browse_repository.mako
@@ -39,7 +39,7 @@
%if can_browse_contents:
<div class="toolForm">
- <div class="toolFormTitle">Browse ${repository.name | h} revision ${repository.tip( trans.app ) | h} (repository tip)</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}' revision ${repository.tip( trans.app ) | h} (repository tip)</div>
%if can_download:
<div class="form-row"><label>Clone this repository:</label>
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/preview_tools_in_changeset.mako
--- a/templates/webapps/tool_shed/repository/preview_tools_in_changeset.mako
+++ b/templates/webapps/tool_shed/repository/preview_tools_in_changeset.mako
@@ -31,7 +31,7 @@
%endif
<div class="toolForm">
- <div class="toolFormTitle">Repository ${repository.name | h}</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div><div class="toolFormBody">
%if len( changeset_revision_select_field.options ) > 1:
<form name="change_revision" id="change_revision" action="${h.url_for( controller='repository', action='preview_tools_in_changeset', repository_id=trans.security.encode_id( repository.id ) )}" method="post" >
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/rate_repository.mako
--- a/templates/webapps/tool_shed/repository/rate_repository.mako
+++ b/templates/webapps/tool_shed/repository/rate_repository.mako
@@ -64,7 +64,7 @@
</div><p/><div class="toolForm">
- <div class="toolFormTitle">Rate and Review</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div><div class="toolFormBody"><form id="rate_repository" name="rate_repository" action="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}" method="post"><div class="form-row">
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/upload.mako
--- a/templates/webapps/tool_shed/repository/upload.mako
+++ b/templates/webapps/tool_shed/repository/upload.mako
@@ -41,12 +41,12 @@
${render_tool_shed_repository_actions( repository=repository)}
<div class="toolForm">
- <div class="toolFormTitle">Upload a single file or a tarball</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div><div class="toolFormBody"><div class="form-row"><div class="warningmessage">
- Uploading may take a while, depending upon the size of the file. Wait until a message is displayed in your
- browser after clicking the <b>Upload</b> button below.
+ Upload a single file or tarball. Uploading may take a while, depending upon the size of the file.
+ Wait until a message is displayed in your browser after clicking the <b>Upload</b> button below.
</div><div style="clear: both"></div></div>
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/view_changelog.mako
--- a/templates/webapps/tool_shed/repository/view_changelog.mako
+++ b/templates/webapps/tool_shed/repository/view_changelog.mako
@@ -38,7 +38,7 @@
%if can_download:
<div class="toolForm">
- <div class="toolFormTitle">${repository.name | h}</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div><div class="toolFormBody"><div class="form-row"><label>Clone this repository:</label>
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/view_changeset.mako
--- a/templates/webapps/tool_shed/repository/view_changeset.mako
+++ b/templates/webapps/tool_shed/repository/view_changeset.mako
@@ -37,7 +37,7 @@
%if can_download:
<div class="toolForm">
- <div class="toolFormTitle">${repository.name | h}</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div><div class="toolFormBody"><div class="form-row"><label>Clone this repository:</label>
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/view_repository.mako
--- a/templates/webapps/tool_shed/repository/view_repository.mako
+++ b/templates/webapps/tool_shed/repository/view_repository.mako
@@ -80,7 +80,7 @@
<p/>
%endif
<div class="toolForm">
- <div class="toolFormTitle">Repository '${repository.name}'</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div><div class="toolFormBody"><div class="form-row"><label>${sharable_link_label}</label>
diff -r ae52981af216ff749092ccf16f254e77e8c096fa -r 2de7ce3e39fd08c39d32ff47bab2dd1993388ba9 templates/webapps/tool_shed/repository/view_tool_metadata.mako
--- a/templates/webapps/tool_shed/repository/view_tool_metadata.mako
+++ b/templates/webapps/tool_shed/repository/view_tool_metadata.mako
@@ -47,7 +47,7 @@
<p/>
%if can_download:
<div class="toolForm">
- <div class="toolFormTitle">Repository '${repository.name}'</div>
+ <div class="toolFormTitle">Repository '${repository.name | h}'</div><div class="toolFormBody"><div class="form-row"><label>Clone this repository:</label>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: add editable min, max labels to tracks.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ae52981af216/
Changeset: ae52981af216
User: jgoecks
Date: 2013-05-02 21:14:50
Summary: Trackster: add editable min, max labels to tracks.
Affected #: 1 file
diff -r 262842a3689a77687ed3310ce180f5323e32b1b5 -r ae52981af216ff749092ccf16f254e77e8c096fa static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -2853,7 +2853,10 @@
/**
* Actions to be taken before drawing.
*/
- before_draw: function() {},
+ before_draw: function() {
+ // Clear because this is set when drawing.
+ this.max_height_px = 0;
+ },
/**
* Draw track. It is possible to force a redraw rather than use cached tiles and/or clear old
@@ -2930,11 +2933,15 @@
/**
* Add a maximum/minimum label to track.
*/
- _add_yaxis_label: function(type, val, pref_name) {
- var css_class = (type === 'max' ? 'top' : 'bottom'),
- text = (type === 'max' ? 'max' : 'min');
-
- var label = this.container_div.find(".yaxislabel." + css_class);
+ _add_yaxis_label: function(type, val, pref_name, on_change) {
+ var track = this,
+ css_class = (type === 'max' ? 'top' : 'bottom'),
+ text = (type === 'max' ? 'max' : 'min'),
+ // Default action for on_change is to redraw track.
+ on_change = on_change || function() {
+ track.request_draw(true);
+ },
+ label = this.container_div.find(".yaxislabel." + css_class);
if (label.length !== 0) {
// Label already exists, so update value.
@@ -2942,14 +2949,13 @@
}
else {
// Add label.
- var track = this;
label = $("<div/>").text(val).make_text_editable({
num_cols: 12,
on_finish: function(new_val) {
$(".bs-tooltip").remove();
var new_val = parseFloat(new_val);
track.prefs[ pref_name ] = (!isNaN(new_val) ? new_val : null);
- track.request_draw(true);
+ on_change();
},
help_text: "Set " + text + " value"
}).addClass('yaxislabel ' + css_class).css("color", this.prefs.label_color);
@@ -3337,6 +3343,9 @@
unpack_drawables: DrawableCollection.prototype.unpack_drawables,
+ /**
+ * Change mode for all tracks.
+ */
change_mode: function(new_mode) {
TiledTrack.prototype.change_mode.call(this, new_mode);
for (var i = 0; i < this.drawables.length; i++) {
@@ -3426,8 +3435,6 @@
// Set up and draw tile.
extend(tile_data, kwargs[ 'more_tile_data' ] );
- this.tile_predraw_init();
-
var canvas = track.view.canvas_manager.new_canvas(),
tile_low = region.get('start'),
tile_high = region.get('end'),
@@ -3518,9 +3525,11 @@
},
/**
- * Actions taken before drawing a tile.
+ * Actions taken before drawing.
*/
- tile_predraw_init: function() {
+ before_draw: function() {
+ TiledTrack.prototype.before_draw.call(this);
+
//
// Set min, max for LineTracks to be largest min, max.
//
@@ -3541,6 +3550,8 @@
}
}
}
+ this.prefs.min_value = min;
+ this.prefs.max_value = max;
// Set all tracks to smallest min, biggest max.
for (var i = 0; i < this.drawables.length; i++) {
@@ -3551,6 +3562,18 @@
},
/**
+ * Update minimum, maximum for component tracks.
+ */
+ update_all_min_max: function() {
+ var track = this;
+ _.each(this.drawables, function(d) {
+ d.prefs.min_value = track.prefs.min_value;
+ d.prefs.max_value = track.prefs.max_value;
+ });
+ this.request_draw(true);
+ },
+
+ /**
* Actions to be taken after draw has been completed. Draw is completed when all tiles have been
* drawn/fetched and shown.
*/
@@ -3572,7 +3595,15 @@
this.draw_helper(true, tile.region, tile.resolution, tile.html_elt.parent(), w_scale, { height: max_height } );
tile.html_elt.remove();
}
- }
+ }
+
+ // Wrap function so that it can be called without object reference.
+ var track = this,
+ t = function() { track.update_all_min_max(); };
+
+ // Add min, max labels.
+ this._add_yaxis_label('min', this.drawables[0].prefs.min_value, 'min_value', t);
+ this._add_yaxis_label('max', this.drawables[0].prefs.max_value, 'max_value', t);
}
});
@@ -3701,6 +3732,12 @@
},
/**
+ * Actions to be taken before drawing.
+ */
+ // FIXME: can the default behavior be used; right now it breaks during resize.
+ before_draw: function() {},
+
+ /**
* Draw LineTrack tile.
*/
draw_tile: function(result, ctx, mode, resolution, region, w_scale) {
@@ -3843,14 +3880,6 @@
},
/**
- * Actions to be taken before drawing.
- */
- before_draw: function() {
- // Clear because this is set when drawing.
- this.max_height_px = 0;
- },
-
- /**
* Actions to be taken after draw has been completed. Draw is completed when all tiles have been
* drawn/fetched and shown.
*/
@@ -4211,14 +4240,6 @@
},
/**
- * Actions to be taken before drawing.
- */
- before_draw: function() {
- // Clear because this is set when drawing.
- this.max_height_px = 0;
- },
-
- /**
* Additional initialization required before drawing track for the first time.
*/
predraw_init: function() {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: implement generic functionality for adding and editing track min/max values. Also redraw by default on resize.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/262842a3689a/
Changeset: 262842a3689a
User: jgoecks
Date: 2013-05-02 19:15:02
Summary: Trackster: implement generic functionality for adding and editing track min/max values. Also redraw by default on resize.
Affected #: 1 file
diff -r f7a2d117ad02430426fef338f991f063853c377e -r 262842a3689a77687ed3310ce180f5323e32b1b5 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -2442,7 +2442,9 @@
/**
* Action to take during resize.
*/
- on_resize: function() {},
+ on_resize: function() {
+ this.request_draw(true);
+ },
/**
* Add resizing handle to drawable's container_div.
@@ -2926,6 +2928,36 @@
},
/**
+ * Add a maximum/minimum label to track.
+ */
+ _add_yaxis_label: function(type, val, pref_name) {
+ var css_class = (type === 'max' ? 'top' : 'bottom'),
+ text = (type === 'max' ? 'max' : 'min');
+
+ var label = this.container_div.find(".yaxislabel." + css_class);
+
+ if (label.length !== 0) {
+ // Label already exists, so update value.
+ label.text(val);
+ }
+ else {
+ // Add label.
+ var track = this;
+ label = $("<div/>").text(val).make_text_editable({
+ num_cols: 12,
+ on_finish: function(new_val) {
+ $(".bs-tooltip").remove();
+ var new_val = parseFloat(new_val);
+ track.prefs[ pref_name ] = (!isNaN(new_val) ? new_val : null);
+ track.request_draw(true);
+ },
+ help_text: "Set " + text + " value"
+ }).addClass('yaxislabel ' + css_class).css("color", this.prefs.label_color);
+ this.container_div.prepend(label);
+ }
+ },
+
+ /**
* Actions to be taken after draw has been completed. Draw is completed when all tiles have been
* drawn/fetched and shown.
*/
@@ -2947,27 +2979,13 @@
}
//
- // If using SummaryTree tiles, show max and make it editable.
+ // If using SummaryTree tiles, show max.
//
var track = this,
first_tile = tiles[0];
if (first_tile instanceof SummaryTreeTile) {
- // Remove old max.
- this.container_div.find(".yaxislabel").remove();
-
- // Add new max.
- var max_val = (this.prefs.histogram_max ? this.prefs.histogram_max : first_tile.max_val),
- max_label = $("<div/>").text(max_val).make_text_editable({
- num_cols: 12,
- on_finish: function(new_val) {
- $(".bs-tooltip").remove();
- var new_val = parseFloat(new_val);
- track.prefs.histogram_max = (!isNaN(new_val) ? new_val : null);
- track.request_draw(true);
- },
- help_text: "Set max value; leave blank to use default"
- }).addClass('yaxislabel top').css("color", this.prefs.label_color);
- this.container_div.prepend(max_label);
+ var max_val = (this.prefs.histogram_max ? this.prefs.histogram_max : first_tile.max_val);
+ this._add_yaxis_label('max', max_val, 'histogram_max');
}
},
@@ -3496,7 +3514,7 @@
// Replace track with group.
var index = this.container.replace_drawable(this, group, true);
- group.request_draw();
+ group.request_draw(true);
},
/**
@@ -3647,8 +3665,7 @@
onchange: function() {
track.set_name(track.prefs.name);
track.vertical_range = track.prefs.max_value - track.prefs.min_value;
- track.set_min_value(track.prefs.min_value);
- track.set_max_value(track.prefs.max_value);
+ track.request_redraw(true);
}
});
@@ -3657,30 +3674,6 @@
this.vertical_range = this.config.values.max_value - this.config.values.min_value;
};
extend(LineTrack.prototype, Drawable.prototype, TiledTrack.prototype, {
- /**
- * Action to take during resize.
- */
- on_resize: function() {
- this.request_draw(true);
- },
-
- /**
- * Set track minimum value.
- */
- set_min_value: function(new_val) {
- this.prefs.min_value = new_val;
- $('#linetrack_' + this.dataset.id + '_minval').text(this.prefs.min_value);
- this.request_draw(true);
- },
-
- /**
- * Set track maximum value.
- */
- set_max_value: function(new_val) {
- this.prefs.max_value = new_val;
- $('#linetrack_' + this.dataset.id + '_maxval').text(this.prefs.max_value);
- this.request_draw(true);
- },
predraw_init: function() {
var track = this;
@@ -3701,45 +3694,9 @@
// Update the prefs
track.prefs.min_value = min_value;
track.prefs.max_value = max_value;
- // Update the config
- // FIXME: we should probably only save this when the user explicately sets it
- // since we lose the ability to compute it on the fly (when changing
- // chromosomes for example).
- $('#track_' + track.dataset.id + '_minval').val(track.prefs.min_value);
- $('#track_' + track.dataset.id + '_maxval').val(track.prefs.max_value);
}
track.vertical_range = track.prefs.max_value - track.prefs.min_value;
track.total_frequency = data.total_frequency;
-
- // Draw y-axis labels if necessary
- track.container_div.find(".yaxislabel").remove();
-
- // Add min, max labels.
- var
- min_label = $("<div/>").text(round(track.prefs.min_value, 3)).make_text_editable({
- num_cols: 6,
- on_finish: function(new_val) {
- $(".bs-tooltip").remove();
- var new_val = parseFloat(new_val);
- if (!isNaN(new_val)) {
- track.set_min_value(new_val);
- }
- },
- help_text: "Set min value"
- }).addClass('yaxislabel bottom').attr("id", 'linetrack_' + track.dataset.id + '_minval')
- .prependTo(track.container_div),
- max_label = $("<div/>").text(round(track.prefs.max_value, 3)).make_text_editable({
- num_cols: 6,
- on_finish: function(new_val) {
- $(".bs-tooltip").remove();
- var new_val = parseFloat(new_val);
- if (!isNaN(new_val)) {
- track.set_max_value(new_val);
- }
- },
- help_text: "Set max value"
- }).addClass('yaxislabel top').attr("id", 'linetrack_' + track.dataset.id + '_maxval')
- .prependTo(track.container_div);
});
},
@@ -3763,6 +3720,15 @@
*/
can_subset: function(entry) {
return (entry.data[1][0] - entry.data[0][0] === 1);
+ },
+
+ /**
+ * Add min, max labels.
+ */
+ postdraw_actions: function(tiles, width, w_scale, clear_after) {
+ // Add min, max labels.
+ this._add_yaxis_label('max', round(this.prefs.max_value, 3), 'max_value');
+ this._add_yaxis_label('min', round(this.prefs.min_value, 3), 'min_value');
}
});
@@ -3788,8 +3754,7 @@
onchange: function() {
track.set_name(track.prefs.name);
track.vertical_range = track.prefs.max_value - track.prefs.min_value;
- track.set_min_value(track.prefs.min_value);
- track.set_max_value(track.prefs.max_value);
+ this.request_redraw(true);
}
});
@@ -3799,27 +3764,6 @@
};
extend(DiagonalHeatmapTrack.prototype, Drawable.prototype, TiledTrack.prototype, {
/**
- * Action to take during resize.
- */
- on_resize: function() {
- this.request_draw(true);
- },
- /**
- * Set track minimum value.
- */
- set_min_value: function(new_val) {
- this.prefs.min_value = new_val;
- this.request_draw(true);
- },
- /**
- * Set track maximum value.
- */
- set_max_value: function(new_val) {
- this.prefs.max_value = new_val;
- this.request_draw(true);
- },
-
- /**
* Draw tile.
*/
draw_tile: function(result, ctx, mode, resolution, region, w_scale) {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix for generating a repository dependency key when prior installation required is true.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f7a2d117ad02/
Changeset: f7a2d117ad02
User: greg
Date: 2013-05-02 17:57:42
Summary: Fix for generating a repository dependency key when prior installation required is true.
Affected #: 2 files
diff -r a26ec089b62fc2eb4824e738b7cc668b481de184 -r f7a2d117ad02430426fef338f991f063853c377e lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -256,12 +256,34 @@
message = '%s ' % str( error )
return message
-def get_key_for_repository_changeset_revision( toolshed_base_url, repository, repository_metadata ):
- return container_util.generate_repository_dependencies_key_for_repository( toolshed_base_url=toolshed_base_url,
- repository_name=repository.name,
- repository_owner=repository.user.username,
- changeset_revision=repository_metadata.changeset_revision,
- prior_installation_required=False )
+def get_key_for_repository_changeset_revision( toolshed_base_url, repository, repository_metadata, all_repository_dependencies ):
+ prior_installation_required = get_prior_installation_required_for_key( toolshed_base_url, repository, repository_metadata, all_repository_dependencies )
+ # Create a key with the value of prior_installation_required defaulted to False.
+ key = container_util.generate_repository_dependencies_key_for_repository( toolshed_base_url=toolshed_base_url,
+ repository_name=repository.name,
+ repository_owner=repository.user.username,
+ changeset_revision=repository_metadata.changeset_revision,
+ prior_installation_required=prior_installation_required )
+ return key
+
+def get_prior_installation_required_for_key( toolshed_base_url, repository, repository_metadata, all_repository_dependencies ):
+ """
+ If all_repository_dependencies contains a repository dependency tuple that is associated with the received repository, return the
+ value of the tuple's prior_installation_required component.
+ """
+ rd_tuple = ( toolshed_base_url, repository.name, repository.user.username, repository_metadata.changeset_revision )
+ for rd_key, rd_tups in all_repository_dependencies.items():
+ if rd_key in [ 'root_key', 'description' ]:
+ continue
+ for rd_tup in rd_tups:
+ rd_toolshed, rd_name, rd_owner, rd_changeset_revision, rd_prior_installation_required = suc.parse_repository_dependency_tuple( rd_tup )
+ if rd_toolshed == toolshed_base_url and \
+ rd_name == repository.name and \
+ rd_owner == repository.user.username and \
+ rd_changeset_revision == repository_metadata.changeset_revision:
+ return rd_prior_installation_required
+ # Default prior_installation_required to False.
+ return False
def get_repository_dependencies_for_changeset_revision( trans, repository, repository_metadata, toolshed_base_url,
key_rd_dicts_to_be_processed=None, all_repository_dependencies=None,
@@ -285,7 +307,7 @@
metadata = repository_metadata.metadata
if metadata:
if 'repository_dependencies' in metadata:
- current_repository_key = get_key_for_repository_changeset_revision( toolshed_base_url, repository, repository_metadata )
+ current_repository_key = get_key_for_repository_changeset_revision( toolshed_base_url, repository, repository_metadata, all_repository_dependencies )
repository_dependencies_dict = metadata[ 'repository_dependencies' ]
if not all_repository_dependencies:
all_repository_dependencies = initialize_all_repository_dependencies( current_repository_key,
@@ -554,7 +576,7 @@
# Change the folder label from 'Missing repository dependencies' to be 'Repository dependencies' for display.
root_container = containers_dict[ 'missing_repository_dependencies' ]
for sub_container in root_container.folders:
- # There should only be 1 subfolder.
+ # There should only be 1 sub-folder.
sub_container.label = 'Repository dependencies'
containers_dict[ 'repository_dependencies' ] = root_container
containers_dict[ 'missing_repository_dependencies' ] = None
@@ -608,8 +630,8 @@
def prune_invalid_repository_dependencies( repository_dependencies ):
"""
- Eliminate all invalid entries in the received repository_dependencies dictionary. An entry is invalid if if the value_list of the key/value pair is
- empty. This occurs when an invalid combination of tool shed, name , owner, changeset_revision is used and a repository_metadata reocrd is not found.
+ Eliminate all invalid entries in the received repository_dependencies dictionary. An entry is invalid if the value_list of the key/value pair is
+ empty. This occurs when an invalid combination of tool shed, name , owner, changeset_revision is used and a repository_metadata record is not found.
"""
valid_repository_dependencies = {}
description = repository_dependencies.get( 'description', None )
diff -r a26ec089b62fc2eb4824e738b7cc668b481de184 -r f7a2d117ad02430426fef338f991f063853c377e templates/webapps/tool_shed/repository/common.mako
--- a/templates/webapps/tool_shed/repository/common.mako
+++ b/templates/webapps/tool_shed/repository/common.mako
@@ -980,6 +980,7 @@
</div>
%endif
%if tool_test_results_root_folder:
+ <p/><div class="toolForm"><div class="toolFormTitle">Automated tool test results</div><div class="toolFormBody">
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0b5c9c031f72/
Changeset: 0b5c9c031f72
User: jgoecks
Date: 2013-05-02 16:33:28
Summary: Trackster: remove nodraw parameter because it is no longer needed.
Affected #: 1 file
diff -r 72a381a4f692feb906e85f6cfed99c7407640282 -r 0b5c9c031f72526d506cb5acf55fb79ec0af1732 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -892,7 +892,7 @@
],
saved_values: obj_dict.prefs,
onchange: function() {
- track.request_redraw(false, true);
+ track.request_redraw(true);
}
});
},
@@ -1266,8 +1266,7 @@
view.chrom_select.val(view.chrom);
view.max_high = found.len-1; // -1 because we're using 0-based indexing.
view.reset();
- view.request_redraw(true);
-
+
for (var i = 0, len = view.drawables.length; i < len; i++) {
var drawable = view.drawables[i];
if (drawable.init) {
@@ -1392,8 +1391,7 @@
* Request that view redraw some or all tracks. If a track is not specificied, redraw all tracks.
*/
// FIXME: change method call so that track is first and additional parameters are optional.
- // FIXME: is nodraw parameter needed?
- request_redraw: function(nodraw, force, clear_after, a_track) {
+ request_redraw: function(force, clear_after, a_track) {
var
view = this,
// Either redrawing a single drawable or all view's drawables.
@@ -1428,7 +1426,7 @@
// Set up redraw if it has not been requested since last redraw.
if (!this.requested_redraw) {
- requestAnimationFrame(function() { view._redraw(nodraw); });
+ requestAnimationFrame(function() { view._redraw(); });
this.requested_redraw = true;
}
},
@@ -1437,7 +1435,7 @@
* NOTE: this method should never be called directly; request_redraw() should be used so
* that requestAnimationFrame can manage redrawing.
*/
- _redraw: function(nodraw) {
+ _redraw: function() {
// TODO: move this code to function that does location setting.
// Clear because requested redraw is being handled now.
@@ -1482,20 +1480,18 @@
this.overview_highlight.css({ left: left_px, width: width_px });
}
- if (!nodraw) {
- var track, force, clear_after;
- for (var i = 0, len = this.tracks_to_be_redrawn.length; i < len; i++) {
- track = this.tracks_to_be_redrawn[i][0];
- force = this.tracks_to_be_redrawn[i][1];
- clear_after = this.tracks_to_be_redrawn[i][2];
- if (track) {
- track._draw(force, clear_after);
- }
+ var track, force, clear_after;
+ for (var i = 0, len = this.tracks_to_be_redrawn.length; i < len; i++) {
+ track = this.tracks_to_be_redrawn[i][0];
+ force = this.tracks_to_be_redrawn[i][1];
+ clear_after = this.tracks_to_be_redrawn[i][2];
+ if (track) {
+ track._draw(force, clear_after);
}
- this.tracks_to_be_redrawn = [];
- for (i = 0, len = this.label_tracks.length; i < len; i++) {
- this.label_tracks[i]._draw();
- }
+ }
+ this.tracks_to_be_redrawn = [];
+ for (i = 0, len = this.label_tracks.length; i < len; i++) {
+ this.label_tracks[i]._draw();
}
},
zoom_in: function (point, container) {
@@ -2848,7 +2844,7 @@
* Request that track be drawn.
*/
request_draw: function(force, clear_after) {
- this.view.request_redraw(false, force, clear_after, this);
+ this.view.request_redraw(force, clear_after, this);
},
/**
https://bitbucket.org/galaxy/galaxy-central/commits/a26ec089b62f/
Changeset: a26ec089b62f
User: jgoecks
Date: 2013-05-02 16:58:19
Summary: Trackster: optionally clear tile cache when requesting a track redraw.
Affected #: 2 files
diff -r 0b5c9c031f72526d506cb5acf55fb79ec0af1732 -r a26ec089b62fc2eb4824e738b7cc668b481de184 static/scripts/viz/trackster/filters.js
--- a/static/scripts/viz/trackster/filters.js
+++ b/static/scripts/viz/trackster/filters.js
@@ -178,7 +178,7 @@
filter.manager.alpha_filter = null;
filter.transparency_icon.removeClass("active");
}
- filter.manager.track.request_draw(true, true);
+ filter.manager.track.request_draw(false, true, true);
} )
.appendTo(display_controls_div).hide();
this.height_icon = create_action_icon("Use filter for data height", "arrow-resize-090",
@@ -195,7 +195,7 @@
filter.manager.height_filter = null;
filter.height_icon.removeClass("active");
}
- filter.manager.track.request_draw(true, true);
+ filter.manager.track.request_draw(false, true, true);
} )
.appendTo(display_controls_div).hide();
filter.parent_div.hover( function() {
@@ -265,7 +265,7 @@
var self = this;
setTimeout(function() {
if (values[0] === self.low && values[1] === self.high) {
- self.manager.track.request_draw(true, true);
+ self.manager.track.request_draw(false, true, true);
}
}, 25);
diff -r 0b5c9c031f72526d506cb5acf55fb79ec0af1732 -r a26ec089b62fc2eb4824e738b7cc668b481de184 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -845,9 +845,9 @@
return obj_dict;
},
- request_draw: function(clear_after, force) {
+ request_draw: function(clear_tile_cache, force, clear_after) {
for (var i = 0; i < this.drawables.length; i++) {
- this.drawables[i].request_draw(clear_after, force);
+ this.drawables[i].request_draw(clear_tile_cache, force, clear_after);
}
}
});
@@ -1390,7 +1390,6 @@
/**
* Request that view redraw some or all tracks. If a track is not specificied, redraw all tracks.
*/
- // FIXME: change method call so that track is first and additional parameters are optional.
request_redraw: function(force, clear_after, a_track) {
var
view = this,
@@ -2101,7 +2100,7 @@
tile.stale = true;
track.data_manager.get_more_data(tile_region, track.mode, tile.resolution, {}, track.data_manager.DEEP_DATA_REQ);
$(".bs-tooltip").hide();
- track.request_draw(true);
+ track.request_draw(false, true);
}).dblclick(function(e) {
// Do not propogate as this would normally zoom in.
e.stopPropagation();
@@ -2112,7 +2111,7 @@
tile.stale = true;
track.data_manager.get_more_data(tile_region, track.mode, tile.resolution, {}, track.data_manager.BROAD_DATA_REQ);
$(".bs-tooltip").hide();
- track.request_draw(true);
+ track.request_draw(false, true);
}).dblclick(function(e) {
// Do not propogate as this would normally zoom in.
e.stopPropagation();
@@ -2786,8 +2785,7 @@
// TODO: is it necessary to store the mode in two places (.mode and track_config)?
track.mode = new_mode;
track.config.values['mode'] = new_mode;
- track.tile_cache.clear();
- track.request_draw();
+ track.request_draw(true);
this.action_icons.mode_icon.attr("title", "Set display mode (now: " + track.mode + ")");
return track;
},
@@ -2843,7 +2841,10 @@
/**
* Request that track be drawn.
*/
- request_draw: function(force, clear_after) {
+ request_draw: function(clear_tile_cache, force, clear_after) {
+ if (clear_tile_cache) {
+ this.tile_cache.clear();
+ }
this.view.request_redraw(force, clear_after, this);
},
@@ -2962,8 +2963,7 @@
$(".bs-tooltip").remove();
var new_val = parseFloat(new_val);
track.prefs.histogram_max = (!isNaN(new_val) ? new_val : null);
- track.tile_cache.clear();
- track.request_draw();
+ track.request_draw(true);
},
help_text: "Set max value; leave blank to use default"
}).addClass('yaxislabel top').css("color", this.prefs.label_color);
@@ -3670,8 +3670,7 @@
set_min_value: function(new_val) {
this.prefs.min_value = new_val;
$('#linetrack_' + this.dataset.id + '_minval').text(this.prefs.min_value);
- this.tile_cache.clear();
- this.request_draw();
+ this.request_draw(true);
},
/**
@@ -3680,8 +3679,7 @@
set_max_value: function(new_val) {
this.prefs.max_value = new_val;
$('#linetrack_' + this.dataset.id + '_maxval').text(this.prefs.max_value);
- this.tile_cache.clear();
- this.request_draw();
+ this.request_draw(true);
},
predraw_init: function() {
@@ -3811,16 +3809,14 @@
*/
set_min_value: function(new_val) {
this.prefs.min_value = new_val;
- this.tile_cache.clear();
- this.request_draw();
+ this.request_draw(true);
},
/**
* Set track maximum value.
*/
set_max_value: function(new_val) {
this.prefs.max_value = new_val;
- this.tile_cache.clear();
- this.request_draw();
+ this.request_draw(true);
},
/**
@@ -3874,9 +3870,8 @@
saved_values: obj_dict.prefs,
onchange: function() {
track.set_name(track.prefs.name);
- track.tile_cache.clear();
track.set_painter_from_config();
- track.request_draw();
+ track.request_draw(true);
}
});
this.prefs = this.config.values;
@@ -4210,8 +4205,7 @@
saved_values: obj_dict.prefs,
onchange: function() {
this.track.set_name(this.track.prefs.name);
- this.track.tile_cache.clear();
- this.track.request_draw();
+ this.track.request_draw(true);
}
});
this.prefs = this.config.values;
@@ -4369,8 +4363,7 @@
saved_values: obj_dict.prefs,
onchange: function() {
this.track.set_name(this.track.prefs.name);
- this.track.tile_cache.clear();
- this.track.request_draw();
+ this.track.request_draw(true);
}
});
this.prefs = this.config.values;
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: whitespace fixes.
by commits-noreply@bitbucket.org 02 May '13
by commits-noreply@bitbucket.org 02 May '13
02 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/72a381a4f692/
Changeset: 72a381a4f692
User: jgoecks
Date: 2013-05-02 15:41:17
Summary: Trackster: whitespace fixes.
Affected #: 1 file
diff -r fadc4b334f3e3cca07238f86d30053318215486e -r 72a381a4f692feb906e85f6cfed99c7407640282 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -2722,6 +2722,7 @@
}
};
extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, {
+
action_icons_def: Track.prototype.action_icons_def.concat( [
// Show more rows when all features are not slotted.
{
@@ -2737,6 +2738,7 @@
hide: true
}
] ),
+
/**
* Returns a copy of the track. The copy uses the same data manager so that the tracks can share data.
*/
@@ -2752,6 +2754,7 @@
new_track.enabled = this.enabled;
return new_track;
},
+
/**
* Set filters manager + HTML elements.
*/
@@ -2759,6 +2762,7 @@
this.filters_manager = filters_manager;
this.header_div.after(this.filters_manager.parent_div);
},
+
/**
* Returns representation of object in a dictionary for easy saving.
* Use from_dict to recreate object.
@@ -2777,6 +2781,7 @@
tool_state: (this.tool ? this.tool.state_dict() : {})
};
},
+
/**
* Change track's mode.
*/
@@ -2789,7 +2794,8 @@
track.request_draw();
this.action_icons.mode_icon.attr("title", "Set display mode (now: " + track.mode + ")");
return track;
- },
+ },
+
/**
* Update track's buttons.
*/
@@ -2921,6 +2927,7 @@
}
});
},
+
/**
* Actions to be taken after draw has been completed. Draw is completed when all tiles have been
* drawn/fetched and shown.
@@ -3160,6 +3167,7 @@
region_str = (region !== undefined ? region.toString() : "all");
return " - region=[" + region_str + "], parameters=[" + track.tool.get_param_values().join(", ") + "]";
},
+
/**
* Returns true if data is compatible with a given mode. Defaults to true because, for many tracks,
* all data is compatible with all modes.
@@ -3167,12 +3175,14 @@
data_and_mode_compatible: function(data, mode) {
return true;
},
+
/**
* Returns true if data can be subsetted. Defaults to false to ensure data is fetched when needed.
*/
can_subset: function(data) {
return false;
},
+
/**
* Set up track to receive tool data.
*/
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: First pass at standardizing the Repository Actions menu in the tool shed.
by commits-noreply@bitbucket.org 01 May '13
by commits-noreply@bitbucket.org 01 May '13
01 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fadc4b334f3e/
Changeset: fadc4b334f3e
User: greg
Date: 2013-05-01 23:02:32
Summary: First pass at standardizing the Repository Actions menu in the tool shed.
Affected #: 21 files
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -545,13 +545,11 @@
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
# Update repository files for browsing.
suc.update_repository( repo )
- is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
return trans.fill_template( '/webapps/tool_shed/repository/browse_repository.mako',
repository=repository,
metadata=metadata,
commit_message=commit_message,
- is_malicious=is_malicious,
message=message,
status=status )
@@ -941,7 +939,6 @@
if message:
status = 'error'
tool_state = self.__new_state( trans )
- is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, repository_id, changeset_revision )
try:
return trans.fill_template( "/webapps/tool_shed/repository/tool_form.mako",
@@ -950,7 +947,6 @@
changeset_revision=changeset_revision,
tool=tool,
tool_state=tool_state,
- is_malicious=is_malicious,
message=message,
status=status )
except Exception, e:
@@ -1779,7 +1775,6 @@
status = params.get( 'status', 'error' )
repository, tool, error_message = tool_util.load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config )
tool_state = self.__new_state( trans )
- is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
invalid_file_tups = []
if tool:
invalid_file_tups = tool_util.check_tool_input_params( trans.app,
@@ -1797,7 +1792,6 @@
changeset_revision=changeset_revision,
tool=tool,
tool_state=tool_state,
- is_malicious=is_malicious,
message=message,
status='error' )
except Exception, e:
@@ -2024,17 +2018,6 @@
malicious_check_box = CheckboxField( 'malicious', checked=is_malicious )
categories = suc.get_categories( trans )
selected_categories = [ rca.category_id for rca in repository.categories ]
- # Determine if the current changeset revision has been reviewed by the current user.
- reviewed_by_user = review_util.changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
- if reviewed_by_user:
- review = review_util.get_review_by_repository_id_changeset_revision_user_id( trans=trans,
- repository_id=id,
- changeset_revision=changeset_revision,
- user_id=trans.security.encode_id( trans.user.id ) )
- review_id = trans.security.encode_id( review.id )
- else:
- review_id = None
- can_browse_repository_reviews = review_util.can_browse_repository_reviews( trans, repository )
containers_dict = container_util.build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata )
return trans.fill_template( '/webapps/tool_shed/repository/manage_repository.mako',
repo_name=repo_name,
@@ -2047,8 +2030,6 @@
containers_dict=containers_dict,
repository_metadata=repository_metadata,
changeset_revision=changeset_revision,
- reviewed_by_user=reviewed_by_user,
- review_id=review_id,
changeset_revision_select_field=changeset_revision_select_field,
revision_label=revision_label,
selected_categories=selected_categories,
@@ -2059,8 +2040,6 @@
num_ratings=num_ratings,
alerts_check_box=alerts_check_box,
malicious_check_box=malicious_check_box,
- is_malicious=is_malicious,
- can_browse_repository_reviews=can_browse_repository_reviews,
message=message,
status=status )
@@ -2214,7 +2193,6 @@
avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, repository, webapp_model=trans.model )
display_reviews = util.string_as_bool( params.get( 'display_reviews', False ) )
rra = self.get_user_item_rating( trans.sa_session, trans.user, repository, webapp_model=trans.model )
- is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
return trans.fill_template( '/webapps/tool_shed/repository/rate_repository.mako',
repository=repository,
@@ -2223,7 +2201,6 @@
display_reviews=display_reviews,
num_ratings=num_ratings,
rra=rra,
- is_malicious=is_malicious,
message=message,
status=status )
@@ -2403,12 +2380,10 @@
else:
message = "Select at least 1 file to delete from the repository before clicking <b>Delete selected files</b>."
status = "error"
- is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
return trans.fill_template( '/webapps/tool_shed/repository/browse_repository.mako',
repo=repo,
repository=repository,
commit_message=commit_message,
- is_malicious=is_malicious,
message=message,
status=status )
@@ -2679,13 +2654,11 @@
'has_metadata' : has_metadata }
# Make sure we'll view latest changeset first.
changesets.insert( 0, change_dict )
- is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, repository.tip( trans.app ) )
return trans.fill_template( '/webapps/tool_shed/repository/view_changelog.mako',
repository=repository,
metadata=metadata,
changesets=changesets,
- is_malicious=is_malicious,
message=message,
status=status )
@@ -2711,7 +2684,6 @@
diffs = []
for diff in patch.diff( repo, node1=ctx_parent.node(), node2=ctx.node() ):
diffs.append( suc.to_safe_string( diff, to_html=True ) )
- is_malicious = suc.changeset_is_malicious( trans, id, repository.tip( trans.app ) )
metadata = self.get_metadata( trans, id, ctx_str )
return trans.fill_template( '/webapps/tool_shed/repository/view_changeset.mako',
repository=repository,
@@ -2726,7 +2698,6 @@
ignored=ignored,
clean=clean,
diffs=diffs,
- is_malicious=is_malicious,
message=message,
status=status )
@@ -2814,18 +2785,7 @@
else:
message += malicious_error
status = 'error'
- # Determine if the current changeset revision has been reviewed by the current user.
- reviewed_by_user = review_util.changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
- if reviewed_by_user:
- review = review_util.get_review_by_repository_id_changeset_revision_user_id( trans=trans,
- repository_id=id,
- changeset_revision=changeset_revision,
- user_id=trans.security.encode_id( trans.user.id ) )
- review_id = trans.security.encode_id( review.id )
- else:
- review_id = None
containers_dict = container_util.build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata )
- can_browse_repository_reviews = review_util.can_browse_repository_reviews( trans, repository )
return trans.fill_template( '/webapps/tool_shed/repository/view_repository.mako',
repo=repo,
repository=repository,
@@ -2837,12 +2797,8 @@
num_ratings=num_ratings,
alerts_check_box=alerts_check_box,
changeset_revision=changeset_revision,
- reviewed_by_user=reviewed_by_user,
- review_id=review_id,
changeset_revision_select_field=changeset_revision_select_field,
revision_label=revision_label,
- is_malicious=is_malicious,
- can_browse_repository_reviews=can_browse_repository_reviews,
message=message,
status=status )
@@ -2898,22 +2854,12 @@
else:
repository_metadata_id = None
metadata = None
- is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
changeset_revision_select_field = grids_util.build_changeset_revision_select_field( trans,
repository,
selected_value=changeset_revision,
add_id_to_name=False,
downloadable=False )
trans.app.config.tool_data_path = original_tool_data_path
- reviewed_by_user = review_util.changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
- if reviewed_by_user:
- review = review_util.get_review_by_repository_id_changeset_revision_user_id( trans=trans,
- repository_id=repository_id,
- changeset_revision=changeset_revision,
- user_id=trans.security.encode_id( trans.user.id ) )
- review_id = trans.security.encode_id( review.id )
- else:
- review_id = None
return trans.fill_template( "/webapps/tool_shed/repository/view_tool_metadata.mako",
repository=repository,
repository_metadata_id=repository_metadata_id,
@@ -2924,9 +2870,6 @@
changeset_revision=changeset_revision,
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
- is_malicious=is_malicious,
- reviewed_by_user=reviewed_by_user,
- review_id=review_id,
message=message,
status=status )
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/common/repository_actions_menu.mako
--- /dev/null
+++ b/templates/webapps/tool_shed/common/repository_actions_menu.mako
@@ -0,0 +1,142 @@
+<%inherit file="/base.mako"/>
+
+<%def name="render_tool_shed_repository_actions( repository, repo=None, metadata=None, changeset_revision=None )">
+ <%
+ from tool_shed.util.review_util import can_browse_repository_reviews, changeset_revision_reviewed_by_user, get_review_by_repository_id_changeset_revision_user_id
+ from tool_shed.util.shed_util_common import changeset_is_malicious
+
+ has_metadata = repository.metadata_revisions
+ has_readme = metadata and 'readme' in metadata
+ is_admin = trans.user_is_admin()
+ is_deprecated = repository.deprecated
+ is_new = repository.is_new( trans.app )
+ is_malicious = changeset_is_malicious( trans, trans.security.encode_id( repository.id ), repository.tip( trans.app ) )
+
+ can_browse_contents = not is_new
+ can_browse_reviews = can_browse_repository_reviews( trans, repository )
+ can_contact_owner = trans.user and trans.user != repository.user
+ can_deprecate = not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated
+ can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository )
+ can_download = not is_deprecated and not is_new and ( not is_malicious or can_push )
+ if not is_deprecated:
+ if repo and len( repo ) > 0:
+ can_reset_all_metadata = True
+ else:
+ can_reset_all_metadata = False
+ else:
+ can_reset_all_metadata = False
+ can_upload = can_push and not is_deprecated
+ can_rate = not is_new and not is_deprecated and trans.user and repository.user != trans.user
+ if changeset_revision:
+ can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
+ reviewed_by_user = changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
+ else:
+ can_review_repository = False
+ reviewed_by_user = False
+
+ # Determine if the current changeset revision has been reviewed by the current user.
+ if reviewed_by_user:
+ review = get_review_by_repository_id_changeset_revision_user_id( trans=trans,
+ repository_id=trans.security.encode_id( repository.id ),
+ changeset_revision=changeset_revision,
+ user_id=trans.security.encode_id( trans.user.id ) )
+ review_id = trans.security.encode_id( review.id )
+ else:
+ review_id = None
+
+ can_set_metadata = not is_new and not is_deprecated
+ if changeset_revision:
+ if changeset_revision == repository.tip( trans.app ):
+ changeset_revision_is_repository_tip = True
+ else:
+ changeset_revision_is_repository_tip = False
+ else:
+ changeset_revision_is_repository_tip = False
+ can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision_is_repository_tip
+ can_undeprecate = trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated
+ can_manage = is_admin or repository.user == trans.user
+ can_view_change_log = not is_new
+
+ if can_push:
+ browse_label = 'Browse or delete repository tip files'
+ else:
+ browse_label = 'Browse repository tip files'
+ %>
+
+ <br/><br/>
+ <ul class="manage-table-actions">
+ %if is_new:
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
+ %endif
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_review_repository:
+ %if reviewed_by_user:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=review_id )}">Manage my review of this revision</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ %endif
+ %endif
+ %if can_browse_reviews:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='manage_repository_reviews', id=trans.app.security.encode_id( repository.id ) )}">Browse reviews of this repository</a>
+ %endif
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
+ %endif
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label | h}</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
+ %endif
+ %if can_reset_all_metadata:
+ <a class="action-button" href="${h.url_for( controller='repository', action='reset_all_metadata', id=trans.security.encode_id( repository.id ) )}">Reset all repository metadata</a>
+ %endif
+ %if can_deprecate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=True )}" confirm="Click Ok to deprecate this repository.">Mark repository as deprecated</a>
+ %endif
+ %if can_undeprecate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=False )}">Mark repository as not deprecated</a>
+ %endif
+ %if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
+ %endif
+ </div>
+ %endif
+ </ul>
+</%def>
+
+<%def name="render_galaxy_repository_actions( repository=None )">
+ <br/><br/>
+ <ul class="manage-table-actions">
+ %if repository:
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install to Galaxy</a></li>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='preview_tools_in_changeset', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Browse repository</a></li>
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a>
+ </div>
+ %else:
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a></li>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a></li>
+ %endif
+ </ul>
+</%def>
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/browse_repository.mako
--- a/templates/webapps/tool_shed/repository/browse_repository.mako
+++ b/templates/webapps/tool_shed/repository/browse_repository.mako
@@ -1,23 +1,9 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
-<%
- from galaxy.web.framework.helpers import time_ago
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_upload = can_push and ( not repository.deprecated )
- can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_rate = trans.user and repository.user != trans.user
- can_manage = is_admin or repository.user == trans.user
- can_view_change_log = not is_new
- has_readme = metadata and 'readme' in metadata
-%>
-
<%!
def inherit(context):
if context.get('use_panels'):
@@ -30,30 +16,6 @@
<%def name="stylesheets()">
${parent.stylesheets()}
${h.css( "jquery.rating", "dynatree_skin/ui.dynatree" )}
- <style type="text/css">
- ul.fileBrowser,
- ul.toolFile {
- margin-left: 0;
- padding-left: 0;
- list-style: none;
- }
- ul.fileBrowser {
- margin-left: 20px;
- }
- .fileBrowser li,
- .toolFile li {
- padding-left: 20px;
- background-repeat: no-repeat;
- background-position: 0;
- min-height: 20px;
- }
- .toolFile li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white_compressed.png' )} );
- }
- .fileBrowser li {
- background-image: url( ${h.url_for( '/static/images/silk/page_white.png' )} );
- }
- </style></%def><%def name="javascripts()">
@@ -62,35 +24,14 @@
${common_javascripts(repository)}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
+<%
+ is_new = repository.is_new( trans.app )
+ can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
+ can_download = not is_new and ( not is_malicious or can_push )
+ can_browse_contents = not is_new
+%>
+
+${render_tool_shed_repository_actions( repository )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/contact_owner.mako
--- a/templates/webapps/tool_shed/repository/contact_owner.mako
+++ b/templates/webapps/tool_shed/repository/contact_owner.mako
@@ -1,23 +1,6 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-
-<%
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_upload = can_push
- can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_rate = repository.user != trans.user
- can_manage = is_admin or repository.user == trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
- has_readme = metadata and 'readme' in metadata
-%>
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%!
def inherit(context):
@@ -28,35 +11,7 @@
%><%inherit file="${inherit(context)}"/>
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new and can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ) )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label | h}</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
+${render_tool_shed_repository_actions( repository )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/find_tools.mako
--- a/templates/webapps/tool_shed/repository/find_tools.mako
+++ b/templates/webapps/tool_shed/repository/find_tools.mako
@@ -1,5 +1,6 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_galaxy_repository_actions" /><%!
def inherit(context):
@@ -11,11 +12,7 @@
<%inherit file="${inherit(context)}"/>
%if trans.webapp.name == 'galaxy':
- <br/><br/>
- <ul class="manage-table-actions">
- <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a></li>
- <li><a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a></li>
- </ul>
+ ${render_galaxy_repository_actions( repository=None )}
%endif
%if message:
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/find_workflows.mako
--- a/templates/webapps/tool_shed/repository/find_workflows.mako
+++ b/templates/webapps/tool_shed/repository/find_workflows.mako
@@ -1,5 +1,6 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_galaxy_repository_actions" /><%!
def inherit(context):
@@ -11,11 +12,7 @@
<%inherit file="${inherit(context)}"/>
%if trans.webapp.name == 'galaxy':
- <br/><br/>
- <ul class="manage-table-actions">
- <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a></li>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
- </ul>
+ ${render_galaxy_repository_actions( repository=None )}
%endif
%if message:
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/manage_repository.mako
--- a/templates/webapps/tool_shed/repository/manage_repository.mako
+++ b/templates/webapps/tool_shed/repository/manage_repository.mako
@@ -2,6 +2,7 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
from galaxy.web.framework.helpers import time_ago
@@ -12,26 +13,14 @@
is_new = repository.is_new( trans.app )
is_deprecated = repository.deprecated
- can_browse_contents = not is_new
- can_contact_owner = trans.user and trans.user != repository.user
- can_deprecate = not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated
can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository )
can_download = not is_deprecated and not is_new and ( not is_malicious or can_push )
- can_rate = not is_new and not is_deprecated and trans.user and repository.user != trans.user
- can_reset_all_metadata = not is_deprecated and len( repo ) > 0
can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
can_set_metadata = not is_new and not is_deprecated
changeset_revision_is_repository_tip = changeset_revision == repository.tip( trans.app )
can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision_is_repository_tip
- can_undeprecate = trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated
- can_upload = can_push
can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
-
if changeset_revision_is_repository_tip:
tip_str = 'repository tip'
sharable_link_label = 'Sharable link to this repository:'
@@ -62,57 +51,7 @@
${container_javascripts()}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new:
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_review_repository:
- %if reviewed_by_user:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=review_id )}">Manage my review of this revision</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
- %endif
- %endif
- %if can_browse_repository_reviews:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='manage_repository_reviews', id=trans.app.security.encode_id( repository.id ) )}">Browse reviews of this repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label | h}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_reset_all_metadata:
- <a class="action-button" href="${h.url_for( controller='repository', action='reset_all_metadata', id=trans.security.encode_id( repository.id ) )}">Reset all repository metadata</a>
- %endif
- %if can_deprecate:
- <a class="action-button" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=True )}" confirm="Click Ok to deprecate this repository.">Mark repository as deprecated</a>
- %endif
- %if can_undeprecate:
- <a class="action-button" href="${h.url_for( controller='repository', action='deprecate', id=trans.security.encode_id( repository.id ), mark_deprecated=False )}">Mark repository as not deprecated</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
+${render_tool_shed_repository_actions( repository, repo=repo, metadata=metadata, changeset_revision=changeset_revision )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/preview_tools_in_changeset.mako
--- a/templates/webapps/tool_shed/repository/preview_tools_in_changeset.mako
+++ b/templates/webapps/tool_shed/repository/preview_tools_in_changeset.mako
@@ -2,22 +2,7 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
-
-<%
- is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = not is_new and trans.user and repository.user != trans.user
- can_upload = can_push
- can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
- has_readme = metadata and 'readme' in metadata
-%>
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_galaxy_repository_actions" /><%!
def inherit(context):
@@ -39,16 +24,7 @@
${container_javascripts()}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install to Galaxy</a></li>
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a>
- </div>
-</ul>
+${render_galaxy_repository_actions( repository=repository )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/rate_repository.mako
--- a/templates/webapps/tool_shed/repository/rate_repository.mako
+++ b/templates/webapps/tool_shed/repository/rate_repository.mako
@@ -1,25 +1,13 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
from galaxy.web.framework.helpers import time_ago
- from urllib import quote_plus
- is_admin = trans.user_is_admin()
is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_upload = can_push
can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_rate = repository.user != trans.user
- can_manage = is_admin or repository.user == trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
- has_readme = metadata and 'readme' in metadata
%><%!
@@ -45,38 +33,7 @@
${render_msg( message, status )}
%endif
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label | h}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
+${render_tool_shed_repository_actions( repository, repo=None, metadata=None, changeset_revision=None )}
%if repository.user != trans.user:
<div class="toolForm">
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/tool_form.mako
--- a/templates/webapps/tool_shed/repository/tool_form.mako
+++ b/templates/webapps/tool_shed/repository/tool_form.mako
@@ -1,27 +1,12 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="*" /><%
from galaxy.util.expressions import ExpressionContext
from galaxy import util
from galaxy.tools.parameters.basic import DataToolParameter, ColumnListParameter, GenomeBuildParameter, SelectToolParameter
from galaxy.web.form_builder import SelectField
-
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_upload = can_push
- can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_rate = trans.user and repository.user != trans.user
- can_manage = is_admin or repository.user == trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
- has_readme = metadata and 'readme' in metadata
%><html>
@@ -119,56 +104,12 @@
</div></%def>
- <br/><br/>
- <ul class="manage-table-actions">
- %if trans.webapp.name == 'galaxy':
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install to Galaxy</a></li>
- <li><a class="action-button" href="${h.url_for( controller='repository', action='preview_tools_in_changeset', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Browse repository</a></li>
- </div>
- <li><a class="action-button" id="tool_shed-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
- <div popupmenu="tool_shed-${repository.id}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a>
- </div>
- %else:
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
- %endif
- </ul>
-
+ %if trans.webapp.name == 'galaxy':
+ ${render_galaxy_repository_actions( repository=repository )}
+ %else:
+ ${render_tool_shed_repository_actions( repository, repo=None, metadata=None, changeset_revision=None )}
+ %endif
+
%if message:
${render_msg( message, status )}
%endif
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/upload.mako
--- a/templates/webapps/tool_shed/repository/upload.mako
+++ b/templates/webapps/tool_shed/repository/upload.mako
@@ -1,14 +1,9 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
- is_admin = trans.user_is_admin()
is_new = repository.is_new( trans.app )
- can_browse_contents = not is_new
- can_browse_contents = not is_new
- can_rate = repository.user != trans.user
- can_manage = is_admin or repository.user == trans.user
- can_view_change_log = not is_new
%><%!
@@ -43,23 +38,7 @@
${render_msg( message, status )}
%endif
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">Browse or delete repository files</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository)}
<div class="toolForm"><div class="toolFormTitle">Upload a single file or a tarball</div>
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/view_changelog.mako
--- a/templates/webapps/tool_shed/repository/view_changelog.mako
+++ b/templates/webapps/tool_shed/repository/view_changelog.mako
@@ -2,23 +2,13 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="render_clone_str" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
from galaxy.web.framework.helpers import time_ago
- is_admin = trans.user_is_admin()
is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
- can_browse_contents = not is_new
- can_manage = is_admin or trans.user == repository.user
can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = trans.user and repository.user != trans.user
- can_upload = can_push
can_download = not is_new and ( not is_malicious or can_push )
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
- has_readme = metadata and 'readme' in metadata
%><%!
@@ -40,34 +30,7 @@
${h.js( "libs/jquery/jquery.rating" )}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/view_changeset.mako
--- a/templates/webapps/tool_shed/repository/view_changeset.mako
+++ b/templates/webapps/tool_shed/repository/view_changeset.mako
@@ -2,24 +2,12 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="render_clone_str" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
- from galaxy.web.framework.helpers import time_ago
- is_admin = trans.user_is_admin()
is_new = repository.is_new( trans.app )
- can_contact_owner = trans.user and trans.user != repository.user
- can_browse_contents = not is_new
- can_rate = trans.user and repository.user != trans.user
- can_manage = is_admin or trans.user == repository.user
can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_view_change_log = not is_new
- can_upload = can_push
can_download = not is_new and ( not is_malicious or can_push )
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
- has_readme = metadata and 'readme' in metadata
%><%!
@@ -41,37 +29,7 @@
${h.js( "libs/jquery/jquery.rating" )}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ), file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/view_repository.mako
--- a/templates/webapps/tool_shed/repository/view_repository.mako
+++ b/templates/webapps/tool_shed/repository/view_repository.mako
@@ -2,34 +2,21 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="*" /><%
from galaxy.web.framework.helpers import time_ago
from tool_shed.util.shed_util_common import to_safe_string
- if metadata:
- has_readme = 'readme' in metadata
- else:
- has_readme = False
- has_metadata = repository.metadata_revisions
is_new = repository.is_new( trans.app )
is_deprecated = repository.deprecated
can_browse_contents = trans.webapp.name == 'tool_shed' and not is_new
- can_contact_owner = trans.user and trans.user != repository.user
+ can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository )
can_download = not is_deprecated and not is_new and ( not is_malicious or can_push )
- can_push = not is_deprecated and trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = not is_deprecated and not is_new and trans.user and repository.user != trans.user
- can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
- can_upload = can_push
can_view_change_log = trans.webapp.name == 'tool_shed' and not is_new
changeset_revision_is_repository_tip = changeset_revision == repository.tip( trans.app )
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
-
if changeset_revision_is_repository_tip:
tip_str = 'repository tip'
sharable_link_label = 'Sharable link to this repository:'
@@ -60,58 +47,11 @@
${container_javascripts()}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- %if trans.webapp.name == 'tool_shed':
- %if is_new:
- %if can_upload:
- <li><a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a></li>
- %endif
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_review_repository:
- %if reviewed_by_user:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=review_id )}">Manage my review of this revision</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
- %endif
- %endif
- %if can_browse_repository_reviews:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='manage_repository_reviews', id=trans.app.security.encode_id( repository.id ) )}">Browse reviews of this repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
- %else:
- <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install to Galaxy</a></li>
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a>
- </div>
- %endif
-</ul>
+%if trans.webapp.name == 'tool_shed':
+ ${render_tool_shed_repository_actions( repository=repository, changeset_revision=changeset_revision )}
+%else:
+ ${render_galaxy_repository_actions( repository=repository )}
+%endif
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/view_tool_metadata.mako
--- a/templates/webapps/tool_shed/repository/view_tool_metadata.mako
+++ b/templates/webapps/tool_shed/repository/view_tool_metadata.mako
@@ -2,33 +2,14 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="*" /><%
- from galaxy.web.framework.helpers import time_ago
- from urllib import quote_plus
+ is_new = repository.is_new( trans.app )
- has_metadata = repository.metadata_revisions
- has_readme = metadata and 'readme' in metadata
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- is_deprecated = repository.deprecated
-
- can_browse_contents = trans.webapp.name == 'tool_shed' and not is_new
- can_contact_owner = trans.user and trans.user != repository.user
+ can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
can_download = not is_new and ( not is_malicious or can_push )
- can_manage = is_admin or repository.user == trans.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = repository.user != trans.user
- can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
- can_upload = can_push
can_view_change_log = trans.webapp.name == 'tool_shed' and not is_new
- # TODO: fix the following when the install and test buildbot is functional.
- #can_view_tool_test_results = tool_test_results is not None
-
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
%><%!
@@ -40,59 +21,11 @@
%><%inherit file="${inherit(context)}"/>
-<br/><br/>
-<ul class="manage-table-actions">
- %if trans.webapp.name == 'galaxy':
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install to Galaxy</a></li>
- <li><a class="action-button" href="${h.url_for( controller='repository', action='preview_tools_in_changeset', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Browse repository</a></li>
- </div>
- <li><a class="action-button" id="tool_shed-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
- <div popupmenu="tool_shed-${repository.id}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_categories' )}">Browse valid repositories</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_tools' )}">Search for valid tools</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a>
- </div>
- %else:
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_review_repository:
- %if reviewed_by_user:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=review_id )}">Manage my review of this revision</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
- %endif
- %endif
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
- %endif
-</ul>
+%if trans.webapp.name == 'tool_shed':
+ ${render_tool_shed_repository_actions( repository=repository, changeset_revision=changeset_revision )}
+%else:
+ ${render_galaxy_repository_actions( repository=repository )}
+%endif
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository/view_workflow.mako
--- a/templates/webapps/tool_shed/repository/view_workflow.mako
+++ b/templates/webapps/tool_shed/repository/view_workflow.mako
@@ -2,27 +2,10 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
- from galaxy.web.framework.helpers import time_ago
from tool_shed.util.encoding_util import tool_shed_encode
-
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_manage = is_admin or trans.user == repository.user
- can_contact_owner = trans.user and trans.user != repository.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_upload = can_push
- can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_rate = not is_new and trans.user and repository.user != trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
-
- # <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install repository to Galaxy</a></li>
%><%!
@@ -32,6 +15,7 @@
else:
return '/base.mako'
%>
+
<%inherit file="${inherit(context)}"/><%def name="render_workflow( workflow_name, repository_metadata_id )">
@@ -39,41 +23,7 @@
<iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe></%def>
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new and can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
+${render_tool_shed_repository_actions( repository=repository )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository_review/browse_review.mako
--- a/templates/webapps/tool_shed/repository_review/browse_review.mako
+++ b/templates/webapps/tool_shed/repository_review/browse_review.mako
@@ -1,12 +1,12 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
from galaxy.web.form_builder import CheckboxField
from galaxy.webapps.tool_shed.util.container_util import STRSEP
from tool_shed.util.shed_util_common import to_safe_string
- can_manage_repository = is_admin or repository.user == trans.user
%><%def name="stylesheets()">
@@ -18,17 +18,7 @@
${h.js( "libs/jquery/jquery.rating" )}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="review-${review.id}-popup" class="menubutton">Review Actions</a></li>
- <div popupmenu="review-${review.id}-popup">
- %if can_manage_repository:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">View repository</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository, changeset_revision=review.changeset_revision )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository_review/edit_review.mako
--- a/templates/webapps/tool_shed/repository_review/edit_review.mako
+++ b/templates/webapps/tool_shed/repository_review/edit_review.mako
@@ -1,12 +1,12 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
from galaxy.web.form_builder import CheckboxField
from tool_shed.grids.util import build_approved_select_field
from galaxy.webapps.tool_shed.util.container_util import STRSEP
- can_manage_repository = is_admin or repository.user == trans.user
%><%def name="stylesheets()">
@@ -18,17 +18,7 @@
${h.js( "libs/jquery/jquery.rating" )}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="review-${review.id}-popup" class="menubutton">Review Actions</a></li>
- <div popupmenu="review-${review.id}-popup">
- %if can_manage_repository:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">View repository</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository, changeset_revision=review.changeset_revision )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository_review/reviews_of_changeset_revision.mako
--- a/templates/webapps/tool_shed/repository_review/reviews_of_changeset_revision.mako
+++ b/templates/webapps/tool_shed/repository_review/reviews_of_changeset_revision.mako
@@ -2,22 +2,12 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
from tool_shed.grids.util import build_approved_select_field
from galaxy.webapps.tool_shed.util.container_util import STRSEP
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_browse_contents = not is_new
- can_contact_owner = trans.user and trans.user != repository.user
- can_manage = is_admin or repository.user == trans.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = not is_new and trans.user and repository.user != trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
+
if installable:
installable_str = 'yes'
else:
@@ -44,29 +34,7 @@
${common_javascripts(repository)}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository, changeset_revision=changeset_revision )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository_review/reviews_of_repository.mako
--- a/templates/webapps/tool_shed/repository_review/reviews_of_repository.mako
+++ b/templates/webapps/tool_shed/repository_review/reviews_of_repository.mako
@@ -2,26 +2,13 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_browse_contents = not is_new
- can_contact_owner = trans.user and trans.user != repository.user
- can_manage = is_admin or repository.user == trans.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = not is_new and trans.user and repository.user != trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
if mine:
title = "My reviews of repository '%s'" % repository.name
- review_revision_label = "Manage my review of this revision"
else:
title = "All reviews of repository '%s'" % repository.name
- review_revision_label = "Inspect reviews of this revision"
%><%!
@@ -39,29 +26,7 @@
${common_javascripts(repository)}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">${browse_label | h}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository )}
%if message:
${render_msg( message, status )}
diff -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc -r fadc4b334f3e3cca07238f86d30053318215486e templates/webapps/tool_shed/repository_review/select_previous_review.mako
--- a/templates/webapps/tool_shed/repository_review/select_previous_review.mako
+++ b/templates/webapps/tool_shed/repository_review/select_previous_review.mako
@@ -2,22 +2,7 @@
<%namespace file="/message.mako" import="render_msg" /><%namespace file="/webapps/tool_shed/common/common.mako" import="*" /><%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
-
-<%
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- can_browse_contents = not is_new
- can_contact_owner = trans.user and trans.user != repository.user
- can_manage = is_admin or repository.user == trans.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = not is_new and trans.user and repository.user != trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
- can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user )
-%>
+<%namespace file="/webapps/tool_shed/common/repository_actions_menu.mako" import="render_tool_shed_repository_actions" /><%!
def inherit(context):
@@ -38,29 +23,7 @@
${common_javascripts(repository)}
</%def>
-<br/><br/>
-<ul class="manage-table-actions">
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip( trans.app ) )}">View repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- </div>
-</ul>
+${render_tool_shed_repository_actions( repository=repository )}
%if message:
${render_msg( message, status )}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: make composite track draw helper compatible with dd4b953.
by commits-noreply@bitbucket.org 01 May '13
by commits-noreply@bitbucket.org 01 May '13
01 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3294bcdca48f/
Changeset: 3294bcdca48f
User: jgoecks
Date: 2013-05-01 21:08:25
Summary: Trackster: make composite track draw helper compatible with dd4b953.
Affected #: 1 file
diff -r b3338ccd9c793bb44cab686645e6cdeef8976ee8 -r 3294bcdca48fad92dbc9349da0dcd5ee6721b3bc static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -3349,18 +3349,26 @@
draw_helper: function(force, region, resolution, parent_element, w_scale, kwargs) {
// FIXME: this function is similar to TiledTrack.draw_helper -- can the two be merged/refactored?
+
+ // SHARED block with TiledTrack.draw_helper():
+
var track = this,
- key = this._gen_tile_cache_key(w_scale, region);
+ key = this._gen_tile_cache_key(w_scale, region),
+ is_tile = function(o) { return (o && 'track' in o); };
// Init kwargs if necessary to avoid having to check if kwargs defined.
if (!kwargs) { kwargs = {}; }
// Check tile cache, if found show existing tile in correct position
var tile = (force ? undefined : track.tile_cache.get_elt(key));
- if (tile) {
- track.show_tile(tile, parent_element, w_scale);
+ if (tile) {
+ if (is_tile(tile)) {
+ track.show_tile(tile, parent_element, w_scale);
+ }
return tile;
}
+
+ // UNIQUE block.
// Try to get drawables' data.
var all_data = [],
@@ -3447,17 +3455,20 @@
this.show_tile(tile, parent_element, w_scale);
return tile;
}
-
- // Can't draw now, so trigger another redraw when the data is ready
- var can_draw = $.Deferred(),
- track = this;
+
+ // SHARED (somewhat) block with TiledTrack.draw_helper()
+
+ // Can't draw now, so put Deferred in cache and draw tile when data is available.
+ var tile_drawn = $.Deferred();
+ track = this;
+ track.tile_cache.set_elt(key, tile_drawn);
$.when.apply($, all_data).then(function() {
- view.request_redraw(false, false, false, track);
- can_draw.resolve();
+ // Draw tile--force to clear Deferred from cache--and resolve.
+ tile = track.draw_helper(true, region, resolution, parent_element, w_scale, kwargs);
+ tile_drawn.resolve(tile);
});
- // Returned Deferred that is resolved when tile can be drawn.
- return can_draw;
+ return tile_drawn;
},
/**
@@ -3534,7 +3545,7 @@
for (var i = 0; i < tiles.length; i++) {
var tile = tiles[i];
if (tile.html_elt.find("canvas").height() !== max_height) {
- this.draw_helper(true, tile.index, tile.resolution, tile.html_elt.parent(), w_scale, { height: max_height } );
+ this.draw_helper(true, tile.region, tile.resolution, tile.html_elt.parent(), w_scale, { height: max_height } );
tile.html_elt.remove();
}
}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Visualization framework: (1) fix disappearing Y axis labels for line tracks and (2) update dataset dict to correspond with new description.
by commits-noreply@bitbucket.org 01 May '13
by commits-noreply@bitbucket.org 01 May '13
01 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b3338ccd9c79/
Changeset: b3338ccd9c79
User: jgoecks
Date: 2013-05-01 20:04:23
Summary: Visualization framework: (1) fix disappearing Y axis labels for line tracks and (2) update dataset dict to correspond with new description.
Affected #: 2 files
diff -r c2c22e38826b65c67202b39e2f7e789c1761c892 -r b3338ccd9c793bb44cab686645e6cdeef8976ee8 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -703,17 +703,18 @@
# -- Validate config. --
if vis.type == 'trackster':
- def unpack_track( track_json ):
+ def unpack_track( track_dict ):
""" Unpack a track from its json. """
+ dataset_dict = track_dict[ 'dataset' ]
return {
- "dataset_id": trans.security.decode_id( track_json['dataset_id'] ),
- "hda_ldda": track_json.get('hda_ldda', 'hda'),
- "name": track_json['name'],
- "track_type": track_json['track_type'],
- "prefs": track_json['prefs'],
- "mode": track_json['mode'],
- "filters": track_json['filters'],
- "tool_state": track_json['tool_state']
+ "dataset_id": trans.security.decode_id( dataset_dict['id'] ),
+ "hda_ldda": dataset_dict.get('hda_ldda', 'hda'),
+ "name": track_dict['name'],
+ "track_type": track_dict['track_type'],
+ "prefs": track_dict['prefs'],
+ "mode": track_dict['mode'],
+ "filters": track_dict['filters'],
+ "tool_state": track_dict['tool_state']
}
def unpack_collection( collection_json ):
diff -r c2c22e38826b65c67202b39e2f7e789c1761c892 -r b3338ccd9c793bb44cab686645e6cdeef8976ee8 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -2765,14 +2765,16 @@
*/
to_dict: function() {
return {
- "track_type": this.get_type(),
- "name": this.name,
- "hda_ldda": this.dataset.get('hda_ldda'),
- "dataset_id": this.dataset.id,
- "prefs": this.prefs,
- "mode": this.mode,
- "filters": this.filters_manager.to_dict(),
- "tool_state": (this.tool ? this.tool.state_dict() : {})
+ track_type: this.get_type(),
+ name: this.name,
+ dataset: {
+ id: this.dataset.id,
+ hda_ldda: this.dataset.get('hda_ldda')
+ },
+ prefs: this.prefs,
+ mode: this.mode,
+ filters: this.filters_manager.to_dict(),
+ tool_state: (this.tool ? this.tool.state_dict() : {})
};
},
/**
@@ -2943,10 +2945,13 @@
//
// If using SummaryTree tiles, show max and make it editable.
//
- this.container_div.find(".yaxislabel").remove();
var track = this,
first_tile = tiles[0];
if (first_tile instanceof SummaryTreeTile) {
+ // Remove old max.
+ this.container_div.find(".yaxislabel").remove();
+
+ // Add new max.
var max_val = (this.prefs.histogram_max ? this.prefs.histogram_max : first_tile.max_val),
max_label = $("<div/>").text(max_val).make_text_editable({
num_cols: 12,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Move the My invalid tools menu item in the tool shed to a grid that filters to the latest metadata revision.
by commits-noreply@bitbucket.org 01 May '13
by commits-noreply@bitbucket.org 01 May '13
01 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c2c22e38826b/
Changeset: c2c22e38826b
User: greg
Date: 2013-05-01 19:42:47
Summary: Move the My invalid tools menu item in the tool shed to a grid that filters to the latest metadata revision.
Affected #: 8 files
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 lib/galaxy/webapps/tool_shed/api/repositories.py
--- a/lib/galaxy/webapps/tool_shed/api/repositories.py
+++ b/lib/galaxy/webapps/tool_shed/api/repositories.py
@@ -48,7 +48,7 @@
encoded_repository_id = trans.security.encode_id( repository.id )
repo_dir = repository.repo_path( trans.app )
repo = hg.repository( suc.get_configured_ui(), repo_dir )
- ordered_installable_revisions = suc.get_ordered_downloadable_changeset_revisions( repository, repo )
+ ordered_installable_revisions = suc.get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True )
return ordered_installable_revisions
except Exception, e:
message = "Error in the Tool Shed repositories API in get_ordered_installable_revisions: %s" % str( e )
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -61,12 +61,14 @@
my_writable_repositories_grid = repository_grids.MyWritableRepositoriesGrid()
my_writable_repositories_missing_tool_test_components_grid = repository_grids.MyWritableRepositoriesMissingToolTestComponentsGrid()
my_writable_repositories_with_failing_tool_tests_grid = repository_grids.MyWritableRepositoriesWithFailingToolTestsGrid()
+ my_writable_repositories_with_invalid_tools_grid = repository_grids.MyWritableRepositoriesWithInvalidToolsGrid()
my_writable_repositories_with_no_failing_tool_tests_grid = repository_grids.MyWritableRepositoriesWithNoFailingToolTestsGrid()
repositories_by_user_grid = repository_grids.RepositoriesByUserGrid()
repositories_i_own_grid = repository_grids.RepositoriesIOwnGrid()
repositories_in_category_grid = repository_grids.RepositoriesInCategoryGrid()
repositories_missing_tool_test_components_grid = repository_grids.RepositoriesMissingToolTestComponentsGrid()
repositories_with_failing_tool_tests_grid = repository_grids.RepositoriesWithFailingToolTestsGrid()
+ repositories_with_invalid_tools_grid = repository_grids.RepositoriesWithInvalidToolsGrid()
repositories_with_no_failing_tool_tests_grid = repository_grids.RepositoriesWithNoFailingToolTestsGrid()
repository_dependencies_grid = repository_grids.RepositoryDependenciesGrid()
repository_grid = repository_grids.RepositoryGrid()
@@ -141,47 +143,6 @@
return self.deprecated_repositories_i_own_grid( trans, **kwd )
@web.expose
- def browse_invalid_tools( self, trans, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- cntrller = params.get( 'cntrller', 'repository' )
- is_admin = trans.user_is_admin()
- invalid_tools_dict = odict()
- if is_admin and cntrller == 'admin':
- for repository in trans.sa_session.query( trans.model.Repository ) \
- .filter( trans.model.Repository.table.c.deleted == False ) \
- .order_by( trans.model.Repository.table.c.name ):
- # A repository's metadata_revisions are those that ignore the value of the repository_metadata.downloadable column.
- for downloadable_revision in repository.metadata_revisions:
- metadata = downloadable_revision.metadata
- invalid_tools = metadata.get( 'invalid_tools', [] )
- for invalid_tool_config in invalid_tools:
- invalid_tools_dict[ invalid_tool_config ] = ( repository.id,
- repository.name,
- repository.user.username,
- downloadable_revision.changeset_revision )
- else:
- for repository in trans.sa_session.query( trans.model.Repository ) \
- .filter( and_( trans.model.Repository.table.c.deleted == False,
- trans.model.Repository.table.c.user_id == trans.user.id ) ) \
- .order_by( trans.model.Repository.table.c.name ):
- for downloadable_revision in repository.metadata_revisions:
- metadata = downloadable_revision.metadata
- if metadata:
- invalid_tools = metadata.get( 'invalid_tools', [] )
- for invalid_tool_config in invalid_tools:
- invalid_tools_dict[ invalid_tool_config ] = ( repository.id,
- repository.name,
- repository.user.username,
- downloadable_revision.changeset_revision )
- return trans.fill_template( '/webapps/tool_shed/repository/browse_invalid_tools.mako',
- cntrller=cntrller,
- invalid_tools_dict=invalid_tools_dict,
- message=message,
- status=status )
-
- @web.expose
def browse_my_writable_repositories( self, trans, **kwd ):
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
@@ -265,6 +226,34 @@
return self.my_writable_repositories_with_failing_tool_tests_grid( trans, **kwd )
@web.expose
+ def browse_my_writable_repositories_with_invalid_tools( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "view_or_manage_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_or_manage_repository',
+ **kwd ) )
+ elif operation == "repositories_by_user":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repositories_by_user',
+ **kwd ) )
+ elif operation in [ 'mark as deprecated', 'mark as not deprecated' ]:
+ kwd[ 'mark_deprecated' ] = operation == 'mark as deprecated'
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='deprecate',
+ **kwd ) )
+ if 'message' not in kwd:
+ message = 'This list contains repositories that match the following criteria:<br>'
+ message += '<ul>'
+ message += '<li>you are authorized to update them</li>'
+ message += '<li>the latest metadata revision contains at least 1 invalid tool</li>'
+ message += '</ul>'
+ message += 'Click the tool config file name to see why the tool is invalid.'
+ kwd[ 'message' ] = message
+ kwd[ 'status' ] = 'warning'
+ return self.my_writable_repositories_with_invalid_tools_grid( trans, **kwd )
+
+ @web.expose
def browse_my_writable_repositories_with_no_failing_tool_tests( self, trans, **kwd ):
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
@@ -492,6 +481,33 @@
return self.repositories_with_failing_tool_tests_grid( trans, **kwd )
@web.expose
+ def browse_repositories_with_invalid_tools( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "view_or_manage_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_or_manage_repository',
+ **kwd ) )
+ elif operation == "repositories_by_user":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repositories_by_user',
+ **kwd ) )
+ elif operation in [ 'mark as deprecated', 'mark as not deprecated' ]:
+ kwd[ 'mark_deprecated' ] = operation == 'mark as deprecated'
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='deprecate',
+ **kwd ) )
+ if 'message' not in kwd:
+ message = 'This list contains repositories that match the following criteria:<br>'
+ message += '<ul>'
+ message += '<li>the latest metadata revision contains at least 1 invalid tool</li>'
+ message += '</ul>'
+ message += 'Click the tool config file name to see why the tool is invalid.'
+ kwd[ 'message' ] = message
+ kwd[ 'status' ] = 'warning'
+ return self.repositories_with_invalid_tools_grid( trans, **kwd )
+
+ @web.expose
def browse_repositories_with_no_failing_tool_tests( self, trans, **kwd ):
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
@@ -1976,7 +1992,7 @@
is_malicious = repository_metadata.malicious
else:
# There is no repository_metadata defined for the changeset_revision, so see if it was defined in a previous changeset in the changelog.
- previous_changeset_revision = suc.get_previous_downloadable_changeset_revision( repository, repo, changeset_revision )
+ previous_changeset_revision = suc.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=False )
if previous_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, previous_changeset_revision )
if repository_metadata:
@@ -2161,7 +2177,7 @@
repo_dir = repository.repo_path( trans.app )
repo = hg.repository( suc.get_configured_ui(), repo_dir )
# Get the lower bound changeset revision.
- lower_bound_changeset_revision = suc.get_previous_downloadable_changeset_revision( repository, repo, changeset_revision )
+ lower_bound_changeset_revision = suc.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=True )
# Build the list of changeset revision hashes.
changeset_hashes = []
for changeset in suc.reversed_lower_upper_bounded_changelog( repo, lower_bound_changeset_revision, changeset_revision ):
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -73,48 +73,6 @@
use_paging = False
-class ValidCategoryGrid( CategoryGrid ):
-
-
- class RepositoriesColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, category ):
- if category.repositories:
- viewable_repositories = 0
- for rca in category.repositories:
- repository = rca.repository
- if not repository.deleted and not repository.deprecated and repository.downloadable_revisions:
- viewable_repositories += 1
- return viewable_repositories
- return 0
-
- title = "Categories of valid repositories"
- model_class = model.Category
- template='/webapps/tool_shed/category/valid_grid.mako'
- default_sort_key = "name"
- columns = [
- CategoryGrid.NameColumn( "Name",
- key="Category.name",
- link=( lambda item: dict( operation="valid_repositories_by_category", id=item.id ) ),
- attach_popup=False ),
- CategoryGrid.DescriptionColumn( "Description",
- key="Category.description",
- attach_popup=False ),
- # Columns that are valid for filtering but are not visible.
- RepositoriesColumn( "Valid repositories",
- model_class=model.Repository,
- attach_popup=False )
- ]
- # Override these
- default_filter = {}
- global_actions = []
- operations = []
- standard_filters = []
- num_rows_per_page = 50
- preserve_state = False
- use_paging = False
-
-
class RepositoryGrid( grids.Grid ):
@@ -248,7 +206,7 @@
NameColumn( "Name",
key="name",
link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
+ attach_popup=False ),
DescriptionColumn( "Synopsis",
key="description",
attach_popup=False ),
@@ -294,6 +252,195 @@
.outerjoin( model.Category.table )
+class EmailAlertsRepositoryGrid( RepositoryGrid ):
+ columns = [
+ RepositoryGrid.NameColumn( "Name",
+ key="name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryGrid.DescriptionColumn( "Synopsis",
+ key="description",
+ attach_popup=False ),
+ RepositoryGrid.UserColumn( "Owner",
+ model_class=model.User,
+ link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
+ attach_popup=False,
+ key="User.username" ),
+ RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ),
+ # Columns that are valid for filtering but are not visible.
+ grids.DeletedColumn( "Deleted",
+ key="deleted",
+ visible=False,
+ filterable="advanced" )
+ ]
+ operations = []
+ global_actions = [
+ grids.GridAction( "User preferences", dict( controller='user', action='index', cntrller='repository' ) )
+ ]
+
+
+class MatchedRepositoryGrid( grids.Grid ):
+ # This grid filters out repositories that have been marked as deleted or deprecated.
+
+
+ class NameColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return repository_metadata.repository.name
+
+
+ class DescriptionColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return repository_metadata.repository.description
+
+
+ class RevisionColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return repository_metadata.changeset_revision
+
+
+ class UserColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.repository.user:
+ return repository_metadata.repository.user.username
+ return 'no user'
+
+ # Grid definition
+ title = "Matching repositories"
+ model_class = model.RepositoryMetadata
+ template='/webapps/tool_shed/repository/grid.mako'
+ default_sort_key = "Repository.name"
+ columns = [
+ NameColumn( "Repository name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=True ),
+ DescriptionColumn( "Synopsis",
+ attach_popup=False ),
+ RevisionColumn( "Revision" ),
+ UserColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False )
+ ]
+ operations = [ grids.GridOperation( "Install to Galaxy", allow_multiple=True ) ]
+ standard_filters = []
+ default_filter = {}
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = False
+
+ def build_initial_query( self, trans, **kwd ):
+ match_tuples = kwd.get( 'match_tuples', [] )
+ clause_list = []
+ if match_tuples:
+ for match_tuple in match_tuples:
+ repository_id, changeset_revision = match_tuple
+ clause_list.append( "%s=%d and %s='%s'" % ( model.RepositoryMetadata.table.c.repository_id,
+ int( repository_id ),
+ model.RepositoryMetadata.table.c.changeset_revision,
+ changeset_revision ) )
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .filter( or_( *clause_list ) ) \
+ .order_by( model.Repository.name )
+ # Return an empty query
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .filter( model.RepositoryMetadata.id < 0 )
+
+
+class InstallMatchedRepositoryGrid( MatchedRepositoryGrid ):
+ columns = [ col for col in MatchedRepositoryGrid.columns ]
+ # Override the NameColumn
+ columns[ 0 ] = MatchedRepositoryGrid.NameColumn( "Name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False )
+
+
+class MyWritableRepositoriesGrid( RepositoryGrid ):
+ # This grid filters out repositories that have been marked as either deprecated or deleted.
+ title = 'Repositories I can change'
+ columns = [
+ RepositoryGrid.NameColumn( "Name",
+ key="name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
+ RepositoryGrid.UserColumn( "Owner",
+ model_class=model.User,
+ link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
+ attach_popup=False,
+ key="User.username" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name",
+ cols_to_filter=[ columns[ 0 ] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ operations = []
+ use_paging = False
+
+ def build_initial_query( self, trans, **kwd ):
+ # TODO: improve performance by adding a db table associating users with repositories for which they have write access.
+ username = trans.user.username
+ clause_list = []
+ for repository in trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ):
+ allow_push = repository.allow_push( trans.app )
+ if allow_push:
+ allow_push_usernames = allow_push.split( ',' )
+ if username in allow_push_usernames:
+ clause_list.append( model.Repository.table.c.id == repository.id )
+ if clause_list:
+ return trans.sa_session.query( model.Repository ) \
+ .filter( or_( *clause_list ) ) \
+ .join( model.User.table )
+ # Return an empty query.
+ return trans.sa_session.query( model.Repository ) \
+ .filter( model.Repository.table.c.id < 0 )
+
+
+class RepositoriesByUserGrid( RepositoryGrid ):
+ title = "Repositories by user"
+ columns = [
+ RepositoryGrid.NameColumn( "Name",
+ key="name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryGrid.DescriptionColumn( "Synopsis",
+ key="description",
+ attach_popup=False ),
+ RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
+ RepositoryGrid.CategoryColumn( "Category",
+ model_class=model.Category,
+ key="Category.name",
+ attach_popup=False )
+ ]
+ operations = []
+ standard_filters = []
+ default_filter = dict( deleted="False" )
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = False
+
+ def build_initial_query( self, trans, **kwd ):
+ decoded_user_id = trans.security.decode_id( kwd[ 'user_id' ] )
+ return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.user_id == decoded_user_id ) ) \
+ .join( model.User.table ) \
+ .outerjoin( model.RepositoryCategoryAssociation.table ) \
+ .outerjoin( model.Category.table )
+
+
class RepositoriesInCategoryGrid( RepositoryGrid ):
title = "Category"
@@ -346,48 +493,13 @@
.outerjoin( model.Category.table )
-class RepositoriesByUserGrid( RepositoryGrid ):
- title = "Repositories by user"
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False ),
- RepositoryGrid.DescriptionColumn( "Synopsis",
- key="description",
- attach_popup=False ),
- RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
- RepositoryGrid.CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False )
- ]
- operations = []
- standard_filters = []
- default_filter = dict( deleted="False" )
- num_rows_per_page = 50
- preserve_state = False
- use_paging = False
-
- def build_initial_query( self, trans, **kwd ):
- decoded_user_id = trans.security.decode_id( kwd[ 'user_id' ] )
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False,
- model.Repository.table.c.user_id == decoded_user_id ) ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
-
-
class RepositoriesIOwnGrid( RepositoryGrid ):
title = "Repositories I own"
columns = [
RepositoryGrid.NameColumn( "Name",
key="name",
link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
+ attach_popup=False ),
RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
RepositoryGrid.DeprecatedColumn( "Deprecated" )
@@ -409,110 +521,8 @@
.outerjoin( model.Category.table )
-class DeprecatedRepositoriesIOwnGrid( RepositoriesIOwnGrid ):
- title = "Deprecated repositories I own"
- columns = [
- RepositoriesIOwnGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- RepositoriesIOwnGrid.MetadataRevisionColumn( "Metadata Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
- RepositoriesIOwnGrid.CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False ),
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name",
- cols_to_filter=[ columns[0] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- use_paging = False
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.user_id == trans.user.id,
- model.Repository.table.c.deprecated == True ) ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
-
-
-class EmailAlertsRepositoryGrid( RepositoryGrid ):
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False ),
- RepositoryGrid.DescriptionColumn( "Synopsis",
- key="description",
- attach_popup=False ),
- RepositoryGrid.UserColumn( "Owner",
- model_class=model.User,
- link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
- attach_popup=False,
- key="User.username" ),
- RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ),
- # Columns that are valid for filtering but are not visible.
- grids.DeletedColumn( "Deleted",
- key="deleted",
- visible=False,
- filterable="advanced" )
- ]
- operations = []
- global_actions = [
- grids.GridAction( "User preferences", dict( controller='user', action='index', cntrller='repository' ) )
- ]
-
-
-class MyWritableRepositoriesGrid( RepositoryGrid ):
- # This grid filters out repositories that have been marked as either deprecated or deleted.
- title = 'Repositories I can change'
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
- RepositoryGrid.UserColumn( "Owner",
- model_class=model.User,
- link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
- attach_popup=False,
- key="User.username" )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name",
- cols_to_filter=[ columns[ 0 ] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- operations = []
- use_paging = False
-
- def build_initial_query( self, trans, **kwd ):
- # TODO: improve performance by adding a db table associating users with repositories for which they have write access.
- username = trans.user.username
- clause_list = []
- for repository in trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deprecated == False,
- model.Repository.table.c.deleted == False ) ):
- allow_push = repository.allow_push( trans.app )
- if allow_push:
- allow_push_usernames = allow_push.split( ',' )
- if username in allow_push_usernames:
- clause_list.append( model.Repository.table.c.id == repository.id )
- if clause_list:
- return trans.sa_session.query( model.Repository ) \
- .filter( or_( *clause_list ) ) \
- .join( model.User.table )
- # Return an empty query.
- return trans.sa_session.query( model.Repository ) \
- .filter( model.Repository.table.c.id < 0 )
-
-
class RepositoriesMissingToolTestComponentsGrid( RepositoryGrid ):
+ # This grid displays only the latest installable revision of each repository.
title = "Repositories with missing tool test components"
columns = [
RepositoryGrid.NameColumn( "Name",
@@ -545,6 +555,8 @@
revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
if revision_clause_list:
return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.join( model.RepositoryMetadata ) \
.filter( or_( *revision_clause_list ) ) \
.join( model.User.table )
@@ -554,6 +566,7 @@
class MyWritableRepositoriesMissingToolTestComponentsGrid( RepositoriesMissingToolTestComponentsGrid ):
+ # This grid displays only the latest installable revision of each repository.
title = "Repositories I can change with missing tool test components"
columns = [ col for col in RepositoriesMissingToolTestComponentsGrid.columns ]
operations = []
@@ -576,12 +589,16 @@
# tools with missing tool test components.
revision_clause_list = []
for repository in trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.filter( or_( *user_clause_list ) ):
changeset_revision = filter_by_latest_downloadable_changeset_revision_that_has_missing_tool_test_components( trans, repository )
if changeset_revision:
revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
if revision_clause_list:
return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.join( model.User.table ) \
.filter( or_( *user_clause_list ) ) \
.join( model.RepositoryMetadata ) \
@@ -591,7 +608,39 @@
.filter( model.Repository.table.c.id < 0 )
+class DeprecatedRepositoriesIOwnGrid( RepositoriesIOwnGrid ):
+ title = "Deprecated repositories I own"
+ columns = [
+ RepositoriesIOwnGrid.NameColumn( "Name",
+ key="name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoriesIOwnGrid.MetadataRevisionColumn( "Metadata Revisions" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
+ RepositoriesIOwnGrid.CategoryColumn( "Category",
+ model_class=model.Category,
+ key="Category.name",
+ attach_popup=False ),
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name",
+ cols_to_filter=[ columns[0] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ use_paging = False
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deleted == False,
+ model.Repository.table.c.user_id == trans.user.id,
+ model.Repository.table.c.deprecated == True ) ) \
+ .join( model.User.table ) \
+ .outerjoin( model.RepositoryCategoryAssociation.table ) \
+ .outerjoin( model.Category.table )
+
+
class RepositoriesWithFailingToolTestsGrid( RepositoryGrid ):
+ # This grid displays only the latest installable revision of each repository.
title = "Repositories with failing tool tests"
columns = [
RepositoryGrid.NameColumn( "Name",
@@ -624,6 +673,8 @@
revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
if revision_clause_list:
return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.join( model.RepositoryMetadata ) \
.filter( or_( *revision_clause_list ) ) \
.join( model.User.table )
@@ -633,6 +684,7 @@
class MyWritableRepositoriesWithFailingToolTestsGrid( RepositoriesWithFailingToolTestsGrid ):
+ # This grid displays only the latest installable revision of each repository.
title = "Repositories I can change with failing tool tests"
columns = [ col for col in RepositoriesWithFailingToolTestsGrid.columns ]
operations = []
@@ -655,12 +707,16 @@
# tools with at least 1 failing tool test.
revision_clause_list = []
for repository in trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.filter( or_( *user_clause_list ) ):
changeset_revision = filter_by_latest_downloadable_changeset_revision_that_has_failing_tool_tests( trans, repository )
if changeset_revision:
revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
if revision_clause_list:
return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.join( model.User.table ) \
.filter( or_( *user_clause_list ) ) \
.join( model.RepositoryMetadata ) \
@@ -671,6 +727,7 @@
class RepositoriesWithNoFailingToolTestsGrid( RepositoryGrid ):
+ # This grid displays only the latest installable revision of each repository.
title = "Repositories with no failing tool tests"
columns = [
RepositoryGrid.NameColumn( "Name",
@@ -704,6 +761,8 @@
revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
if revision_clause_list:
return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.join( model.RepositoryMetadata ) \
.filter( or_( *revision_clause_list ) ) \
.join( model.User.table )
@@ -713,6 +772,7 @@
class MyWritableRepositoriesWithNoFailingToolTestsGrid( RepositoriesWithNoFailingToolTestsGrid ):
+ # This grid displays only the latest installable revision of each repository.
title = "Repositories I can change with no failing tool tests"
columns = [ col for col in RepositoriesWithNoFailingToolTestsGrid.columns ]
operations = []
@@ -735,12 +795,16 @@
# at least 1 tool, no missing tool test components, and no failing tool tests.
revision_clause_list = []
for repository in trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.filter( or_( *user_clause_list ) ):
changeset_revision = filter_by_latest_downloadable_changeset_revision_that_has_no_failing_tool_tests( trans, repository )
if changeset_revision:
revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
if revision_clause_list:
return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
.join( model.User.table ) \
.filter( or_( *user_clause_list ) ) \
.join( model.RepositoryMetadata ) \
@@ -750,179 +814,110 @@
.filter( model.Repository.table.c.id < 0 )
-class ValidRepositoryGrid( RepositoryGrid ):
- # This grid filters out repositories that have been marked as either deleted or deprecated.
+class RepositoriesWithInvalidToolsGrid( RepositoryGrid ):
+ # This grid displays only the latest installable revision of each repository.
- class CategoryColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- rval = '<ul>'
- if repository.categories:
- for rca in repository.categories:
- rval += '<li><a href="browse_repositories?operation=valid_repositories_by_category&id=%s">%s</a></li>' \
- % ( trans.security.encode_id( rca.category.id ), rca.category.name )
- else:
- rval += '<li>not set</li>'
- rval += '</ul>'
- return rval
-
-
- class RepositoryCategoryColumn( grids.GridColumn ):
-
- def filter( self, trans, user, query, column_filter ):
- """Modify query to filter by category."""
- if column_filter == "All":
- return query
- return query.filter( model.Category.name == column_filter )
-
-
- class InstallableRevisionColumn( grids.GridColumn ):
+ class InvalidToolConfigColumn( grids.GridColumn ):
def __init__( self, col_name ):
grids.GridColumn.__init__( self, col_name )
def get_value( self, trans, grid, repository ):
- """Display a SelectField whose options are the changeset_revision strings of all download-able revisions of this repository."""
- select_field = grids_util.build_changeset_revision_select_field( trans, repository, downloadable=True )
- if len( select_field.options ) > 1:
- return select_field.get_html()
- elif len( select_field.options ) == 1:
- return select_field.options[ 0 ][ 0 ]
- return ''
+ # At the time this grid is displayed we know that the received repository will have invalid tools in it's latest changeset revision
+ # that has associated metadata.
+ val = ''
+ repository_metadata = get_latest_repository_metadata_if_it_includes_invalid_tools( trans, repository )
+ metadata = repository_metadata.metadata
+ invalid_tools = metadata.get( 'invalid_tools', [] )
+ if invalid_tools:
+ for invalid_tool_config in invalid_tools:
+ href_str = '<a href="load_invalid_tool?repository_id=%s&tool_config=%s&changeset_revision=%s">%s</a>' % \
+ ( trans.security.encode_id( repository.id ), invalid_tool_config, repository_metadata.changeset_revision, invalid_tool_config )
+ val += href_str
+ val += '<br/>'
+ val = val.rstrip( '<br/>' )
+ return val
- title = "Valid repositories"
- columns = [
+ title = "Repositories with invalid tools"
+ columns = [
+ InvalidToolConfigColumn( "Tool config" ),
RepositoryGrid.NameColumn( "Name",
key="name",
- attach_popup=True ),
- RepositoryGrid.DescriptionColumn( "Synopsis",
- key="description",
- attach_popup=False ),
- InstallableRevisionColumn( "Installable Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryGrid.LatestInstallableRevisionColumn( "Latest Metadata Revision" ),
RepositoryGrid.UserColumn( "Owner",
+ key="User.username",
model_class=model.User,
- attach_popup=False ),
- # Columns that are valid for filtering but are not visible.
- RepositoryCategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- visible=False )
+ link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
+ attach_popup=False )
]
- columns.append( grids.MulticolFilterColumn( "Search repository name, description",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
operations = []
use_paging = False
def build_initial_query( self, trans, **kwd ):
- if 'id' in kwd:
- # The user is browsing categories of valid repositories, so filter the request by the received id, which is a category id.
+ # Filter by latest metadata revisions that contain invalid tools.
+ revision_clause_list = []
+ for repository in trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ):
+ changeset_revision = filter_by_latest_metadata_changeset_revision_that_has_invalid_tools( trans, repository )
+ if changeset_revision:
+ revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
+ if revision_clause_list:
return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.RepositoryMetadata.table ) \
- .join( model.User.table ) \
- .join( model.RepositoryCategoryAssociation.table ) \
- .join( model.Category.table ) \
- .filter( and_( model.Category.table.c.id == trans.security.decode_id( kwd[ 'id' ] ),
- model.RepositoryMetadata.table.c.downloadable == True ) )
- # The user performed a free text search on the ValidCategoryGrid.
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
+ .join( model.RepositoryMetadata ) \
+ .filter( or_( *revision_clause_list ) ) \
+ .join( model.User.table )
+ # Return an empty query.
return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.RepositoryMetadata.table ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table ) \
- .filter( model.RepositoryMetadata.table.c.downloadable == True )
+ .filter( model.Repository.table.c.id < 0 )
-class MatchedRepositoryGrid( grids.Grid ):
- # This grid filters out repositories that have been marked as deprecated.
-
-
- class NameColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- return repository_metadata.repository.name
-
-
- class DescriptionColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- return repository_metadata.repository.description
-
-
- class RevisionColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- return repository_metadata.changeset_revision
-
-
- class UserColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.repository.user:
- return repository_metadata.repository.user.username
- return 'no user'
-
- # Grid definition
- title = "Matching repositories"
- model_class = model.RepositoryMetadata
- template='/webapps/tool_shed/repository/grid.mako'
- default_sort_key = "Repository.name"
- columns = [
- NameColumn( "Repository name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- DescriptionColumn( "Synopsis",
- attach_popup=False ),
- RevisionColumn( "Revision" ),
- UserColumn( "Owner",
- model_class=model.User,
- attach_popup=False )
- ]
- operations = [
- grids.GridOperation( "Install to Galaxy", allow_multiple=True )
- ]
- standard_filters = []
- default_filter = {}
- num_rows_per_page = 50
- preserve_state = False
+class MyWritableRepositoriesWithInvalidToolsGrid( RepositoriesWithInvalidToolsGrid ):
+ # This grid displays only the latest installable revision of each repository.
+ title = "Repositories I can change with invalid tools"
+ columns = [ col for col in RepositoriesWithInvalidToolsGrid.columns ]
+ operations = []
use_paging = False
def build_initial_query( self, trans, **kwd ):
- match_tuples = kwd.get( 'match_tuples', [] )
- clause_list = []
- if match_tuples:
- for match_tuple in match_tuples:
- repository_id, changeset_revision = match_tuple
- clause_list.append( "%s=%d and %s='%s'" % ( model.RepositoryMetadata.table.c.repository_id,
- int( repository_id ),
- model.RepositoryMetadata.table.c.changeset_revision,
- changeset_revision ) )
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .filter( or_( *clause_list ) ) \
- .order_by( model.Repository.name )
- # Return an empty query
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .filter( model.RepositoryMetadata.id < 0 )
-
-
-class InstallMatchedRepositoryGrid( MatchedRepositoryGrid ):
- columns = [ col for col in MatchedRepositoryGrid.columns ]
- # Override the NameColumn
- columns[ 0 ] = MatchedRepositoryGrid.NameColumn( "Name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False )
+ # First get all repositories that the current user is authorized to update.
+ username = trans.user.username
+ user_clause_list = []
+ for repository in trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ):
+ allow_push = repository.allow_push( trans.app )
+ if allow_push:
+ allow_push_usernames = allow_push.split( ',' )
+ if username in allow_push_usernames:
+ user_clause_list.append( model.Repository.table.c.id == repository.id )
+ if user_clause_list:
+ # We have the list of repositories that the current user is authorized to update, so filter further by latest metadata revisions that contain
+ # invalid tools.
+ revision_clause_list = []
+ for repository in trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
+ .filter( or_( *user_clause_list ) ):
+ changeset_revision = filter_by_latest_metadata_changeset_revision_that_has_invalid_tools( trans, repository )
+ if changeset_revision:
+ revision_clause_list.append( model.RepositoryMetadata.table.c.changeset_revision == changeset_revision )
+ if revision_clause_list:
+ return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deprecated == False,
+ model.Repository.table.c.deleted == False ) ) \
+ .join( model.User.table ) \
+ .filter( or_( *user_clause_list ) ) \
+ .join( model.RepositoryMetadata ) \
+ .filter( or_( *revision_clause_list ) )
+ # Return an empty query.
+ return trans.sa_session.query( model.Repository ) \
+ .filter( model.Repository.table.c.id < 0 )
class RepositoryMetadataGrid( grids.Grid ):
@@ -1136,6 +1131,73 @@
.join( model.User.table )
+class DatatypesGrid( RepositoryMetadataGrid ):
+
+
+ class DatatypesColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ datatype_str = ''
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ datatype_dicts = metadata.get( 'datatypes', [] )
+ if datatype_dicts:
+ # Create tuples of the attributes we want so we can sort them by extension.
+ datatype_tups = []
+ for datatype_dict in datatype_dicts:
+ # Example: {"display_in_upload": "true", "dtype": "galaxy.datatypes.blast:BlastXml", "extension": "blastxml", "mimetype": "application/xml"}
+ extension = datatype_dict.get( 'extension', '' )
+ dtype = datatype_dict.get( 'dtype', '' )
+ mimetype = datatype_dict.get( 'mimetype', '' )
+ display_in_upload = datatype_dict.get( 'display_in_upload', False )
+ # For now we'll just display extension and dtype.
+ if extension and dtype:
+ datatype_tups.append( ( extension, dtype ) )
+ sorted_datatype_tups = sorted( datatype_tups, key=lambda datatype_tup: datatype_tup[ 0 ] )
+ num_datatype_tups = len( sorted_datatype_tups )
+ for index, datatype_tup in enumerate( sorted_datatype_tups ):
+ extension = datatype_tup[ 0 ]
+ dtype = datatype_tup[ 1 ]
+ datatype_str += '<a href="browse_datatypes?operation=view_or_manage_repository&id=%s">' % trans.security.encode_id( repository_metadata.id )
+ datatype_str += '<b>%s:</b> %s' % ( escape_html( extension ), escape_html( dtype ) )
+ datatype_str += '</a>'
+ if index < num_datatype_tups - 1:
+ datatype_str += '<br/>'
+ return datatype_str
+
+ title = "Custom datatypes in this tool shed"
+ default_sort_key = "Repository.name"
+ columns = [
+ DatatypesColumn( "Datatype extension and class",
+ attach_popup=False ),
+ RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
+ model_class=model.Repository,
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False,
+ key="Repository.name" ),
+ RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" ),
+ RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
+ attach_popup=False )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
+ cols_to_filter=[ columns[1], columns[2] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.RepositoryMetadata.table.c.includes_datatypes == True,
+ model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table )
+
+
class ToolDependenciesGrid( RepositoryMetadataGrid ):
@@ -1275,71 +1337,137 @@
.join( model.User.table )
-class DatatypesGrid( RepositoryMetadataGrid ):
+class ValidCategoryGrid( CategoryGrid ):
- class DatatypesColumn( grids.TextColumn ):
+ class RepositoriesColumn( grids.TextColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- datatype_str = ''
- if repository_metadata:
- metadata = repository_metadata.metadata
- if metadata:
- datatype_dicts = metadata.get( 'datatypes', [] )
- if datatype_dicts:
- # Create tuples of the attributes we want so we can sort them by extension.
- datatype_tups = []
- for datatype_dict in datatype_dicts:
- # Example: {"display_in_upload": "true", "dtype": "galaxy.datatypes.blast:BlastXml", "extension": "blastxml", "mimetype": "application/xml"}
- extension = datatype_dict.get( 'extension', '' )
- dtype = datatype_dict.get( 'dtype', '' )
- mimetype = datatype_dict.get( 'mimetype', '' )
- display_in_upload = datatype_dict.get( 'display_in_upload', False )
- # For now we'll just display extension and dtype.
- if extension and dtype:
- datatype_tups.append( ( extension, dtype ) )
- sorted_datatype_tups = sorted( datatype_tups, key=lambda datatype_tup: datatype_tup[ 0 ] )
- num_datatype_tups = len( sorted_datatype_tups )
- for index, datatype_tup in enumerate( sorted_datatype_tups ):
- extension = datatype_tup[ 0 ]
- dtype = datatype_tup[ 1 ]
- datatype_str += '<a href="browse_datatypes?operation=view_or_manage_repository&id=%s">' % trans.security.encode_id( repository_metadata.id )
- datatype_str += '<b>%s:</b> %s' % ( escape_html( extension ), escape_html( dtype ) )
- datatype_str += '</a>'
- if index < num_datatype_tups - 1:
- datatype_str += '<br/>'
- return datatype_str
+ def get_value( self, trans, grid, category ):
+ if category.repositories:
+ viewable_repositories = 0
+ for rca in category.repositories:
+ repository = rca.repository
+ if not repository.deleted and not repository.deprecated and repository.downloadable_revisions:
+ viewable_repositories += 1
+ return viewable_repositories
+ return 0
- title = "Custom datatypes in this tool shed"
- default_sort_key = "Repository.name"
+ title = "Categories of valid repositories"
+ model_class = model.Category
+ template='/webapps/tool_shed/category/valid_grid.mako'
+ default_sort_key = "name"
columns = [
- DatatypesColumn( "Datatype extension and class",
- attach_popup=False ),
- RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
- model_class=model.Repository,
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False,
- key="Repository.name" ),
- RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
- model_class=model.User,
- attach_popup=False,
- key="User.username" ),
- RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
- attach_popup=False )
+ CategoryGrid.NameColumn( "Name",
+ key="Category.name",
+ link=( lambda item: dict( operation="valid_repositories_by_category", id=item.id ) ),
+ attach_popup=False ),
+ CategoryGrid.DescriptionColumn( "Description",
+ key="Category.description",
+ attach_popup=False ),
+ # Columns that are valid for filtering but are not visible.
+ RepositoriesColumn( "Valid repositories",
+ model_class=model.Repository,
+ attach_popup=False )
]
- columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
- cols_to_filter=[ columns[1], columns[2] ],
+ # Override these
+ default_filter = {}
+ global_actions = []
+ operations = []
+ standard_filters = []
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = False
+
+
+class ValidRepositoryGrid( RepositoryGrid ):
+ # This grid filters out repositories that have been marked as either deleted or deprecated.
+
+
+ class CategoryColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository ):
+ rval = '<ul>'
+ if repository.categories:
+ for rca in repository.categories:
+ rval += '<li><a href="browse_repositories?operation=valid_repositories_by_category&id=%s">%s</a></li>' \
+ % ( trans.security.encode_id( rca.category.id ), rca.category.name )
+ else:
+ rval += '<li>not set</li>'
+ rval += '</ul>'
+ return rval
+
+
+ class RepositoryCategoryColumn( grids.GridColumn ):
+
+ def filter( self, trans, user, query, column_filter ):
+ """Modify query to filter by category."""
+ if column_filter == "All":
+ return query
+ return query.filter( model.Category.name == column_filter )
+
+
+ class InstallableRevisionColumn( grids.GridColumn ):
+
+ def __init__( self, col_name ):
+ grids.GridColumn.__init__( self, col_name )
+
+ def get_value( self, trans, grid, repository ):
+ """Display a SelectField whose options are the changeset_revision strings of all download-able revisions of this repository."""
+ select_field = grids_util.build_changeset_revision_select_field( trans, repository, downloadable=True )
+ if len( select_field.options ) > 1:
+ return select_field.get_html()
+ elif len( select_field.options ) == 1:
+ return select_field.options[ 0 ][ 0 ]
+ return ''
+
+ title = "Valid repositories"
+ columns = [
+ RepositoryGrid.NameColumn( "Name",
+ key="name",
+ attach_popup=False ),
+ RepositoryGrid.DescriptionColumn( "Synopsis",
+ key="description",
+ attach_popup=False ),
+ InstallableRevisionColumn( "Installable Revisions" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools Verified" ),
+ RepositoryGrid.UserColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False ),
+ # Columns that are valid for filtering but are not visible.
+ RepositoryCategoryColumn( "Category",
+ model_class=model.Category,
+ key="Category.name",
+ visible=False )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
key="free-text-search",
visible=False,
filterable="standard" ) )
+ operations = []
+ use_paging = False
def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.RepositoryMetadata.table.c.includes_datatypes == True,
- model.Repository.table.c.deleted == False,
+ if 'id' in kwd:
+ # The user is browsing categories of valid repositories, so filter the request by the received id, which is a category id.
+ return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.RepositoryMetadata.table ) \
+ .join( model.User.table ) \
+ .join( model.RepositoryCategoryAssociation.table ) \
+ .join( model.Category.table ) \
+ .filter( and_( model.Category.table.c.id == trans.security.decode_id( kwd[ 'id' ] ),
+ model.RepositoryMetadata.table.c.downloadable == True ) )
+ # The user performed a free text search on the ValidCategoryGrid.
+ return trans.sa_session.query( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deleted == False,
model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table )
+ .join( model.RepositoryMetadata.table ) \
+ .join( model.User.table ) \
+ .outerjoin( model.RepositoryCategoryAssociation.table ) \
+ .outerjoin( model.Category.table ) \
+ .filter( model.RepositoryMetadata.table.c.downloadable == True )
# ------ utility methods -------------------
@@ -1380,8 +1508,46 @@
return repository_metadata.changeset_revision
return None
+def filter_by_latest_metadata_changeset_revision_that_has_invalid_tools( trans, repository ):
+ """
+ Inspect the latest changeset revision with associated metadata for the received repository to see if it has invalid tools.
+ """
+ encoded_repository_id = trans.security.encode_id( repository.id )
+ repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
+ tip_ctx = str( repo.changectx( repo.changelog.tip() ) )
+ repository_metadata = get_latest_repository_metadata_if_it_includes_invalid_tools( trans, repository )
+ if repository_metadata:
+ return repository_metadata.changeset_revision
+ return None
+
+def get_latest_repository_metadata_if_it_includes_invalid_tools( trans, repository ):
+ """Return the latest repository_metadata record for the received repository that contains invalid tools if one exists."""
+ encoded_repository_id = trans.security.encode_id( repository.id )
+ repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
+ tip_ctx = str( repo.changectx( repo.changelog.tip() ) )
+ repository_metadata = None
+ try:
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, tip_ctx )
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata and 'invalid_tools' in metadata:
+ return repository_metadata
+ return None
+ return None
+ except:
+ latest_installable_revision = suc.get_previous_metadata_changeset_revision( repository, repo, tip_ctx, downloadable=False )
+ if latest_installable_revision == suc.INITIAL_CHANGELOG_HASH:
+ return None
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, latest_installable_revision )
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata and 'invalid_tools' in metadata:
+ return repository_metadata
+ return None
+ return None
+
def get_latest_installable_repository_metadata_if_it_includes_tools( trans, repository ):
- """Return the latest installable repository_metadata record for the received repository if one exists."""
+ """Return the latest installable repository_metadata record for the received repository that contains valid tools if one exists."""
encoded_repository_id = trans.security.encode_id( repository.id )
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
tip_ctx = str( repo.changectx( repo.changelog.tip() ) )
@@ -1392,7 +1558,7 @@
return repository_metadata
return None
except:
- latest_installable_revision = suc.get_previous_downloadable_changeset_revision( repository, repo, tip_ctx )
+ latest_installable_revision = suc.get_previous_metadata_changeset_revision( repository, repo, tip_ctx, downloadable=True )
if latest_installable_revision == suc.INITIAL_CHANGELOG_HASH:
return None
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, latest_installable_revision )
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -520,7 +520,7 @@
Return the installable changeset_revision in the repository changelog after the changeset to which after_changeset_revision refers. If there
isn't one, return None.
"""
- changeset_revisions = get_ordered_downloadable_changeset_revisions( repository, repo )
+ changeset_revisions = get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True )
if len( changeset_revisions ) == 1:
changeset_revision = changeset_revisions[ 0 ]
if changeset_revision == after_changeset_revision:
@@ -560,10 +560,14 @@
dist_to_shed=False )
return repository
-def get_ordered_downloadable_changeset_revisions( repository, repo ):
- """Return an ordered list of changeset_revisions defined by a repository changelog."""
+def get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True ):
+ """Return an ordered list of changeset_revisions that are associated with metadata where order is defined by the repository changelog."""
+ if downloadable:
+ metadata_revisions = repository.downloadable_revisions
+ else:
+ metadata_revisions = repository.metadata_revisions
changeset_tups = []
- for repository_metadata in repository.downloadable_revisions:
+ for repository_metadata in metadata_revisions:
changeset_revision = repository_metadata.changeset_revision
ctx = get_changectx_for_changeset( repo, changeset_revision )
if ctx:
@@ -575,12 +579,12 @@
sorted_changeset_revisions = [ changeset_tup[ 1 ] for changeset_tup in sorted_changeset_tups ]
return sorted_changeset_revisions
-def get_previous_downloadable_changeset_revision( repository, repo, before_changeset_revision ):
+def get_previous_metadata_changeset_revision( repository, repo, before_changeset_revision, downloadable=True ):
"""
- Return the installable changeset_revision in the repository changelog prior to the changeset to which before_changeset_revision
- refers. If there isn't one, return the hash value of an empty repository changelog, INITIAL_CHANGELOG_HASH.
+ Return the changeset_revision in the repository changelog that has associated metadata prior to the changeset to which
+ before_changeset_revision refers. If there isn't one, return the hash value of an empty repository changelog, INITIAL_CHANGELOG_HASH.
"""
- changeset_revisions = get_ordered_downloadable_changeset_revisions( repository, repo )
+ changeset_revisions = get_ordered_metadata_changeset_revisions( repository, repo, downloadable=downloadable )
if len( changeset_revisions ) == 1:
changeset_revision = changeset_revisions[ 0 ]
if changeset_revision == before_changeset_revision:
@@ -1091,7 +1095,7 @@
"""
# To set excluded_lower_bounds_changeset_revision, calling methods should do the following, where the value of changeset_revision
# is a downloadable changeset_revision.
- # excluded_lower_bounds_changeset_revision = get_previous_downloadable_changeset_revision( repository, repo, changeset_revision )
+ # excluded_lower_bounds_changeset_revision = get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=? )
if excluded_lower_bounds_changeset_revision == INITIAL_CHANGELOG_HASH:
appending_started = True
else:
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 templates/webapps/tool_shed/admin/index.mako
--- a/templates/webapps/tool_shed/admin/index.mako
+++ b/templates/webapps/tool_shed/admin/index.mako
@@ -60,58 +60,8 @@
<div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_repository_metadata' )}">Browse metadata</a></div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_invalid_tools', cntrller='admin' )}">Browse invalid tools</a>
- </div></div></div>
- %if can_review_repositories:
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Reviewing Repositories
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_ready_for_review' )}">Repositories ready for review</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_without_reviews' )}">All repositories with no reviews</a>
- </div>
- %if trans.user.repository_reviews:
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_reviewed_by_me' )}">Repositories reviewed by me</a>
- </div>
- %endif
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_with_reviews' )}">All reviewed repositories</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_components' )}">Manage review components</a>
- </div>
- </div>
- </div>
- <div class="toolSectionPad"></div>
- <div class="toolSectionTitle">
- Reviewing Repositories With Tools
- </div>
- <div class="toolSectionBody">
- <div class="toolSectionPad"></div>
- <div class="toolSectionBody">
- <div class="toolSectionBg">
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_missing_tool_test_components' )}">Latest revision missing tool tests</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_with_failing_tool_tests' )}">Latest revision failing tool tests</a>
- </div>
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_with_no_failing_tool_tests' )}">Latest revision all tool tests pass</a>
- </div>
- </div>
- </div>
- </div>
- %endif
<div class="toolSectionPad"></div><div class="toolSectionTitle">
Categories
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 templates/webapps/tool_shed/index.mako
--- a/templates/webapps/tool_shed/index.mako
+++ b/templates/webapps/tool_shed/index.mako
@@ -113,16 +113,16 @@
<a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories' )}">My writable repositories</a></div><div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories_missing_tool_test_components' )}">Latest revision missing tool tests</a>
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories_missing_tool_test_components' )}">Latest revision: missing tool tests</a></div><div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories_with_failing_tool_tests' )}">Latest revision failing tool tests</a>
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories_with_failing_tool_tests' )}">Latest revision: failing tool tests</a></div><div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories_with_no_failing_tool_tests' )}">Latest revision all tool tests pass</a>
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories_with_no_failing_tool_tests' )}">Latest revision: all tool tests pass</a></div><div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_invalid_tools', cntrller='repository' )}">My invalid tools</a>
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_my_writable_repositories_with_invalid_tools' )}">Latest revision: invalid tools</a></div><div class="toolSectionPad"></div><div class="toolSectionTitle">
@@ -164,13 +164,16 @@
<div class="toolSectionBody"><div class="toolSectionBg"><div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_missing_tool_test_components' )}">Latest revision missing tool tests</a>
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_missing_tool_test_components' )}">Latest revision: missing tool tests</a></div><div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_with_failing_tool_tests' )}">Latest revision failing tool tests</a>
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_with_failing_tool_tests' )}">Latest revision: failing tool tests</a></div><div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_with_no_failing_tool_tests' )}">Latest revision all tool tests pass</a>
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_with_no_failing_tool_tests' )}">Latest revision: all tool tests pass</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories_with_invalid_tools' )}">Latest revision: invalid tools</a></div></div></div>
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 templates/webapps/tool_shed/repository/browse_invalid_tools.mako
--- a/templates/webapps/tool_shed/repository/browse_invalid_tools.mako
+++ /dev/null
@@ -1,44 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- %if invalid_tools_dict:
- <div class="toolFormTitle">Invalid tools<i> - click the tool config file name to see why the tool is invalid</i></div>
- <div class="form-row">
- <table class="grid">
- <tr>
- <th>Tool config</th>
- <th>Repository name</th>
- <th>Repository owner</th>
- <th>Changeset revision</th>
- </tr>
- %for invalid_tool_config, repository_tup in invalid_tools_dict.items():
- <% repository_id, repository_name, repository_owner, changeset_revision = repository_tup %>
- <tr>
- <td>
- <a class="view-info" href="${h.url_for( controller='repository', action='load_invalid_tool', repository_id=trans.security.encode_id( repository_id ), tool_config=invalid_tool_config, changeset_revision=changeset_revision )}">
- ${invalid_tool_config}
- </a>
- </td>
- <td>${repository_name | h}</td>
- <td>${repository_owner | h}</td>
- <td>${changeset_revision | h}</td>
- </tr>
- %endfor
- </table>
- </div>
- </div>
- %else:
- <div class="form-row">
- %if cntrller == 'admin' and trans.user_is_admin():
- No repositories in this tool shed contain invalid tools.
- %else:
- None of your repositories contain invalid tools.
- %endif
- </div>
- %endif
-</div>
diff -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 -r c2c22e38826b65c67202b39e2f7e789c1761c892 templates/webapps/tool_shed/repository/display_tool_functional_test_results.mako
--- a/templates/webapps/tool_shed/repository/display_tool_functional_test_results.mako
+++ /dev/null
@@ -1,309 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/webapps/tool_shed/common/common.mako" import="*" />
-<%namespace file="/webapps/tool_shed/repository/common.mako" import="*" />
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/tool_shed/base_panels.mako'
- else:
- return '/base.mako'
-%>
-
-<%inherit file="${inherit(context)}"/>
-
-<%def name="render_functional_test_text( functional_test_text )">
- <%
- from tool_shed.util.shed_util_common import to_safe_string
- %>
- <style type="text/css">
- #functional_test_table{ table-layout:fixed;
- width:100%;
- overflow-wrap:normal;
- overflow:hidden;
- border:0px;
- word-break:keep-all;
- word-wrap:break-word;
- line-break:strict; }
- </style>
- <table id="functional_test_table">
- <tr><td>${ to_safe_string( functional_test_text, to_html=True ) }</td></tr>
- </table>
-</%def>
-
-<%
- from galaxy.web.framework.helpers import time_ago
-
- changeset_revision = repository_metadata.changeset_revision
- has_metadata = repository.metadata_revisions
- has_readme = metadata and 'readme' in metadata
- is_admin = trans.user_is_admin()
- is_new = repository.is_new( trans.app )
- is_deprecated = repository.deprecated
-
- can_browse_contents = trans.webapp.name == 'tool_shed' and not is_new
- can_contact_owner = trans.user and trans.user != repository.user
- can_download = not is_new and ( not is_malicious or can_push )
- can_manage = is_admin or repository.user == trans.user
- can_push = trans.app.security_agent.can_push( trans.app, trans.user, repository )
- can_rate = repository.user != trans.user
- can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
- can_upload = can_push
- can_view_change_log = trans.webapp.name == 'tool_shed' and not is_new
- if repository_metadata.tool_test_results:
- # The tool_test_results will contain a dictionary that includes information about the test environment even if all tests passed and the
- # repository_metadata.tools_functionally_correct column is set to True.
- tool_test_results = repository_metadata.tool_test_results
- test_environment_dict = tool_test_results.get( 'test_environment', None )
- missing_test_components = tool_test_results.get( 'missing_test_components', [] )
- failed_tests = tool_test_results.get( 'failed_tests', [] )
- passed_tests = tool_test_results.get( 'passed_tests', [] )
- else:
- tool_test_results = None
- test_environment_dict = {}
- missing_test_components = []
- failed_tests = []
- passed_tests = []
-
- if can_push:
- browse_label = 'Browse or delete repository tip files'
- else:
- browse_label = 'Browse repository tip files'
-%>
-
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_review_repository:
- %if reviewed_by_user:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=review_id )}">Manage my review of this revision</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
- %endif
- %endif
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">Repository revision</div>
- <div class="toolFormBody">
- <div class="form-row">
- <label>Revision:</label>
- %if can_view_change_log:
- <a href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">${revision_label}</a>
- %else:
- ${revision_label}
- %endif
- </div>
- </div>
-</div>
-<p/>
-%if can_download:
- <div class="toolForm">
- <div class="toolFormTitle">Repository '${repository.name}'</div>
- <div class="toolFormBody">
- <div class="form-row">
- <label>Clone this repository:</label>
- ${render_clone_str( repository )}
- </div>
- </div>
- </div>
-%else:
- <b>Repository name:</b><br/>
- ${repository.name}
-%endif
-%if missing_test_components or tool_test_results or passed_tests:
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Tool functional test results</div>
- <div class="toolFormBody">
- <div class="form-row">
- <label>Time tested:</label>
- ${time_ago( repository_metadata.time_last_tested ) | h}
- </div>
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%"><td><b>Tool Shed environment</td></tr>
- </table>
- </div>
- <div class="form-row">
- <label>Tool shed version:</label>
- ${test_environment_dict.get( 'tool_shed_revision', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Tool shed database version:</label>
- ${test_environment_dict.get( 'tool_shed_database_version', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Mercurial version:</label>
- ${test_environment_dict.get( 'tool_shed_mercurial_version', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%"><td><b>Galaxy environment</td></tr>
- </table>
- </div>
- <div class="form-row">
- <label>Galaxy version:</label>
- ${test_environment_dict.get( 'galaxy_revision', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Galaxy database version:</label>
- ${test_environment_dict.get( 'galaxy_database_version', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Architecture:</label>
- ${test_environment_dict.get( 'architecture', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Operating system:</label>
- ${test_environment_dict.get( 'system', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Python version:</label>
- ${test_environment_dict.get( 'python_version', 'unknown' ) | h}
- <div style="clear: both"></div>
- </div>
- %if failed_tests:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%"><td><b>Tests that failed</td></tr>
- </table>
- </div>
- <div class="form-row">
- <table class="grid">
- %for test_results_dict in failed_tests:
- <%
- test_id = test_results_dict.get( 'test_id', 'unknown' )
- tool_id = test_results_dict.get( 'tool_id', 'unknown' )
- tool_version = test_results_dict.get( 'tool_version', 'unknown' )
- test_status = '<font color="red">Test failed</font>'
- stderr = test_results_dict.get( 'stderr', '' )
- traceback = test_results_dict.get( 'traceback', '' )
- %>
- <tr>
- <td colspan="2" bgcolor="#FFFFCC">Tool id: <b>${tool_id}</b> version: <b>${tool_version}</b></td>
- </tr>
- <tr>
- <td><b>Test id</b></td>
- <td>${test_id}</td>
- </tr>
- <tr>
- <td><b>Status</b></td>
- <td>${test_status}</td>
- </tr>
- <tr>
- <td><b>Stderr</b></td>
- <td>${render_functional_test_text( stderr )}</td>
- </tr>
- <tr>
- <td><b>Traceback</b></td>
- <td>${render_functional_test_text( traceback )}</td>
- </tr>
- %endfor
- </table>
- <div style="clear: both"></div>
- </div>
- %endif
- %if passed_tests:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%"><td><b>Tests that passed successfully</td></tr>
- </table>
- </div>
- <div class="form-row">
- <table class="grid">
- %for test_results_dict in passed_tests:
- <%
- test_id = test_results_dict.get( 'test_id', 'unknown' )
- tool_id = test_results_dict.get( 'tool_id', 'unknown' )
- tool_version = test_results_dict.get( 'tool_version', 'unknown' )
- test_status = '<font color="green">Test passed</font>'
- %>
- <tr>
- <td colspan="2" bgcolor="#FFFFCC">Tool id: <b>${tool_id}</b> version: <b>${tool_version}</b></td>
- </tr>
- <tr>
- <td><b>Test id</b></td>
- <td>${test_id}</td>
- </tr>
- <tr>
- <td><b>Status</b></td>
- <td>${test_status}</td>
- </tr>
- %endfor
- </table>
- </div>
- %endif
- %if missing_test_components:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%"><td><b>Invalid tests</td></tr>
- </table>
- </div>
- <div class="form-row">
- <table class="grid">
- %for test_results_dict in missing_test_components:
- <%
- guid = test_results_dict.get( 'tool_guid', None )
- tool_id = test_results_dict.get( 'tool_id', None )
- tool_version = test_results_dict.get( 'tool_version', None )
- missing_components = test_results_dict.get( 'missing_components', None )
- %>
- %if tool_id or tool_version:
- <tr>
- <td colspan="2" bgcolor="#FFFFCC">Tool id: <b>${tool_id}</b> version: <b>${tool_version}</b></td>
- </tr>
- %endif
- %if missing_components:
- <tr>
- <td><b>Reason test is invalid</b></td>
- <td>${render_functional_test_text( missing_components )}</td>
- </tr>
- %endif
- %endfor
- </table>
- </div>
- %endif
- </div>
- </div>
-%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: inithello: Update repository metadata generation to provide the file path for tool functional test output files. Update script that checks for tool functional tests and test data to use the updated metadata structure.
by commits-noreply@bitbucket.org 01 May '13
by commits-noreply@bitbucket.org 01 May '13
01 May '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4fce5cfe8be5/
Changeset: 4fce5cfe8be5
User: inithello
Date: 2013-05-01 16:23:13
Summary: Update repository metadata generation to provide the file path for tool functional test output files. Update script that checks for tool functional tests and test data to use the updated metadata structure.
Affected #: 2 files
diff -r cd6c9cc0079ce10685c04d003e735d6054a4a8c6 -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 lib/tool_shed/scripts/check_repositories_for_functional_tests.py
--- a/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
+++ b/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
@@ -387,16 +387,9 @@
missing_test_files = []
required_test_files = []
for test_dict in test_definition:
- for input_file in test_dict[ 'required_files' ]:
- if input_file not in required_test_files:
- required_test_files.append( input_file )
- for output in test_dict[ 'outputs' ]:
- fieldname, filename = output
- # In rare cases, the filename may be None. If that is the case, skip that output definition.
- if filename is None:
- continue
- if filename not in required_test_files:
- required_test_files.append( filename )
+ for required_file in test_dict[ 'required_files' ]:
+ if required_file not in required_test_files:
+ required_test_files.append( required_file )
# Make sure each specified file actually does exist in the test data path of the cloned repository.
for required_file in required_test_files:
required_file_full_path = os.path.join( test_data_path, required_file )
diff -r cd6c9cc0079ce10685c04d003e735d6054a4a8c6 -r 4fce5cfe8be5724f27a1a909dac135c3f010fe30 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -825,6 +825,8 @@
for output in ttb.outputs:
name, file_name, extra = output
outputs.append( ( name, suc.strip_path( file_name ) if file_name else None ) )
+ if file_name not in required_files and file_name is not None:
+ required_files.append( file_name )
test_dict = dict( name=ttb.name,
required_files=required_files,
inputs=inputs,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0