galaxy-commits
Threads by month
- ----- 2026 -----
- 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: Migrated lastz and bowtie tools to the tool shed. Added a target_file feature to the tool dependency installation process.
by Bitbucket 26 Nov '12
by Bitbucket 26 Nov '12
26 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/87828175dfe7/
changeset: 87828175dfe7
user: inithello
date: 2012-11-26 16:18:47
summary: Migrated lastz and bowtie tools to the tool shed. Added a target_file feature to the tool dependency installation process.
affected #: 54 files
Diff too large to display.
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: Improvements in the display of repository dependencies and contents in the tool shed.
by Bitbucket 26 Nov '12
by Bitbucket 26 Nov '12
26 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/519b7df6d72a/
changeset: 519b7df6d72a
user: greg
date: 2012-11-26 16:15:45
summary: Improvements in the display of repository dependencies and contents in the tool shed.
affected #: 14 files
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -1050,23 +1050,6 @@
trans.sa_session.add( tool_dependency )
trans.sa_session.flush()
return removed, error_message
-def to_html_str( text ):
- """Translates the characters in text to an html string"""
- translated = []
- for c in text:
- if c in VALID_CHARS:
- translated.append( c )
- elif c in MAPPED_CHARS:
- translated.append( MAPPED_CHARS[ c ] )
- elif c == ' ':
- translated.append( ' ' )
- elif c == '\t':
- translated.append( ' ' )
- elif c == '\n':
- translated.append( '<br/>' )
- elif c not in [ '\r' ]:
- translated.append( '' )
- return ''.join( translated )
def tool_shed_from_repository_clone_url( repository_clone_url ):
return clean_repository_clone_url( repository_clone_url ).split( 'repos' )[ 0 ].rstrip( '/' )
def translate_string( raw_text, to_html=True ):
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/util/shed_util_common.py
--- a/lib/galaxy/util/shed_util_common.py
+++ b/lib/galaxy/util/shed_util_common.py
@@ -1331,6 +1331,23 @@
except:
file_name = fpath
return file_name
+def to_html_str( text ):
+ """Translates the characters in text to an html string"""
+ translated = []
+ for c in text:
+ if c in VALID_CHARS:
+ translated.append( c )
+ elif c in MAPPED_CHARS:
+ translated.append( MAPPED_CHARS[ c ] )
+ elif c == ' ':
+ translated.append( ' ' )
+ elif c == '\t':
+ translated.append( ' ' )
+ elif c == '\n':
+ translated.append( '<br/>' )
+ elif c not in [ '\r' ]:
+ translated.append( '' )
+ return ''.join( translated )
def update_existing_tool_dependency( app, repository, original_dependency_dict, new_dependencies_dict ):
"""
Update an exsiting tool dependency whose definition was updated in a change set pulled by a Galaxy administrator when getting updates
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -1,11 +1,13 @@
-import os, string, socket, logging, simplejson, binascii, tempfile, filecmp
+import os, string, socket, logging, simplejson, binascii, tempfile, filecmp, threading
from time import strftime
from datetime import *
from galaxy.datatypes.checkers import *
from galaxy.tools import *
+from galaxy.util.odict import odict
from galaxy.util.json import from_json_string, to_json_string
from galaxy.util.hash_util import *
from galaxy.util.shed_util_common import *
+from galaxy.webapps.community.util.container_util import *
from galaxy.web.base.controller import *
from galaxy.web.base.controllers.admin import *
from galaxy.webapps.community import model
@@ -73,9 +75,6 @@
'${host}'
"""
-# String separator
-STRSEP = '__ESEP__'
-
# States for passing messages
SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
@@ -105,6 +104,62 @@
trans.sa_session.flush()
return item_rating
+def build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ):
+ containers_dict = dict( datatypes=None,
+ invalid_tools=None,
+ repository_dependencies=None,
+ tool_dependencies=None,
+ valid_tools=None,
+ workflows=None )
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ lock = threading.Lock()
+ lock.acquire( True )
+ try:
+ folder_id = 0
+ # Datatypes container.
+ if metadata and 'datatypes' in metadata:
+ datatypes = metadata[ 'datatypes' ]
+ folder_id, datatypes_root_folder = build_datatypes_folder( folder_id, datatypes )
+ containers_dict[ 'datatypes' ] = datatypes_root_folder
+ # Invalid tools container.
+ if metadata and 'invalid_tools' in metadata:
+ invalid_tool_configs = metadata[ 'invalid_tools' ]
+ folder_id, invalid_tools_root_folder = build_invalid_tools_folder( folder_id,
+ invalid_tool_configs,
+ repository,
+ changeset_revision,
+ label='Invalid tools' )
+ containers_dict[ 'invalid_tools' ] = invalid_tools_root_folder
+ # Repository dependencies container.
+ folder_id, repository_dependencies_root_folder = build_repository_dependencies_folder( repository,
+ changeset_revision,
+ folder_id,
+ repository_dependencies )
+ if repository_dependencies_root_folder:
+ containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder
+ # Tool dependencies container.
+ if metadata and 'tool_dependencies' in metadata:
+ tool_dependencies = metadata[ 'tool_dependencies' ]
+ folder_id, tool_dependencies_root_folder = build_tool_dependencies_folder( folder_id, tool_dependencies )
+ containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder
+ # Valid tools container.
+ if metadata and 'tools' in metadata:
+ valid_tools = metadata[ 'tools' ]
+ folder_id, valid_tools_root_folder = build_tools_folder( folder_id, valid_tools, repository, changeset_revision, label='Valid tools' )
+ containers_dict[ 'valid_tools' ] = valid_tools_root_folder
+ # Workflows container.
+ if metadata and 'workflows' in metadata:
+ workflows = metadata[ 'workflows' ]
+ folder_id, workflows_root_folder = build_workflows_folder( folder_id, workflows, repository_metadata, label='Workflows' )
+ containers_dict[ 'workflows' ] = workflows_root_folder
+ except Exception, e:
+ repository_dependencies_root_folder = None
+ tool_dependencies_root_folder = None
+ log.debug( "Exception in build_repository_containers: %s" % str( e ) )
+ finally:
+ lock.release()
+ return containers_dict
def add_tool_versions( trans, id, repository_metadata, changeset_revisions ):
# Build a dictionary of { 'tool id' : 'parent tool id' } pairs for each tool in repository_metadata.
metadata = repository_metadata.metadata
@@ -183,18 +238,6 @@
else:
tmp_filename = None
return tmp_filename
-def copy_file_from_manifest( repo, ctx, filename, dir ):
- """Copy the latest version of the file named filename from the repository manifest to the directory to which dir refers."""
- for changeset in reversed_upper_bounded_changelog( repo, ctx ):
- changeset_ctx = repo.changectx( changeset )
- fctx = get_file_context_from_ctx( changeset_ctx, filename )
- if fctx and fctx not in [ 'DELETED' ]:
- file_path = os.path.join( dir, filename )
- fh = open( file_path, 'wb' )
- fh.write( fctx.data() )
- fh.close()
- return file_path
- return None
def generate_tool_guid( trans, repository, tool ):
"""
Generate a guid for the received tool. The form of the guid is
@@ -285,11 +328,28 @@
fh.close()
return tmp_filename
return None
-def get_previous_downloadable_changset_revision( repository, repo, before_changeset_revision ):
+def get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision ):
"""
- Return the downloadable changeset_revision in the repository changelog just prior to the changeset to which before_changeset_revision
- refers. If there isn't one, return the hash value of an empty repository changlog, INITIAL_CHANGELOG_HASH.
+ Return the installable changeset_revision in the repository changelog after to the changeset to which after_changeset_revision
+ refers. If there isn't one, return None.
"""
+ changeset_revisions = get_ordered_downloadable_changeset_revisions( repository, repo )
+ if len( changeset_revisions ) == 1:
+ changeset_revision = changeset_revisions[ 0 ]
+ if changeset_revision == after_changeset_revision:
+ return None
+ found_after_changeset_revision = False
+ for changeset in repo.changelog:
+ changeset_revision = str( repo.changectx( changeset ) )
+ if found_after_changeset_revision:
+ if changeset_revision in downloadable_changeset_revisions:
+ return changeset_revision
+ elif not found_after_changeset_revision and changeset_revision == after_changeset_revision:
+ # We've found the changeset in the changelog for which we need to get the next downloadable changset.
+ found_after_changeset_revision = True
+ return None
+def get_ordered_downloadable_changeset_revisions( repository, repo ):
+ """Return an ordered list of changeset_revisions defined by a repository changelog."""
changeset_tups = []
for repository_metadata in repository.downloadable_revisions:
changeset_revision = repository_metadata.changeset_revision
@@ -299,24 +359,30 @@
else:
rev = '-1'
changeset_tups.append( ( rev, changeset_revision ) )
- if len( changeset_tups ) == 1:
- changeset_tup = changeset_tups[ 0 ]
- current_changeset_revision = changeset_tup[ 1 ]
- if current_changeset_revision == before_changeset_revision:
+ sorted_changeset_tups = sorted( changeset_tups )
+ sorted_changeset_revisions = [ changeset_tup[ 1 ] for changeset_tup in sorted_changeset_tups ]
+ return sorted_changeset_revisions
+def get_previous_downloadable_changset_revision( repository, repo, before_changeset_revision ):
+ """
+ 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.
+ """
+ changeset_revisions = get_ordered_downloadable_changeset_revisions( repository, repo )
+ if len( changeset_revisions ) == 1:
+ changeset_revision = changeset_revisions[ 0 ]
+ if changeset_revision == before_changeset_revision:
return INITIAL_CHANGELOG_HASH
- return current_changeset_revision
+ return changeset_revision
previous_changeset_revision = None
- current_changeset_revision = None
- for changeset_tup in sorted( changeset_tups ):
- current_changeset_revision = changeset_tup[ 1 ]
- if current_changeset_revision == before_changeset_revision:
+ for changeset_revision in changeset_revisions:
+ if changeset_revision == before_changeset_revision:
if previous_changeset_revision:
return previous_changeset_revision
else:
- # Return the hash value of an empty repository changlog - note that this will not be a valid changset revision.
+ # Return the hash value of an empty repository changelog - note that this will not be a valid changeset revision.
return INITIAL_CHANGELOG_HASH
else:
- previous_changeset_revision = current_changeset_revision
+ previous_changeset_revision = changeset_revision
def get_previous_repository_reviews( trans, repository, changeset_revision ):
"""Return an ordered dictionary of repository reviews up to and including the received changeset revision."""
repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
@@ -332,6 +398,110 @@
previous_reviews_dict[ previous_changeset_revision ] = dict( changeset_revision_label=previous_changeset_revision_label,
reviews=revision_reviews )
return previous_reviews_dict
+def get_repository_by_name( trans, name ):
+ """Get a repository from the database via name"""
+ return trans.sa_session.query( trans.model.Repository ).filter_by( name=name ).one()
+def get_repository_by_name_and_owner( trans, name, owner ):
+ """Get a repository from the database via name and owner"""
+ user = get_user_by_username( trans, owner )
+ return trans.sa_session.query( trans.model.Repository ) \
+ .filter( and_( trans.model.Repository.table.c.name == name,
+ trans.model.Repository.table.c.user_id == user.id ) ) \
+ .first()
+def get_repository_dependencies_for_changeset_revision( trans, repo, repository, repository_metadata, toolshed_base_url, repository_dependencies=None,
+ all_repository_dependencies=None ):
+ """
+ Return a dictionary of all repositories upon which the contents of the received repository_metadata record depend. The dictionary keys
+ are name-spaced values consisting of tool_shed_base_url/repository_name/repository_owner/changeset_revision and the values are lists of
+ repository_dependency tuples consisting of ( tool_shed_base_url, repository_name, repository_owner, changeset_revision ). This is a
+ recursive method, so it ensures that all required repositories to the nth degree are returned.
+ """
+ if all_repository_dependencies is None:
+ all_repository_dependencies = odict()
+ if repository_dependencies is None:
+ repository_dependencies = []
+ metadata = repository_metadata.metadata
+ if metadata and 'repository_dependencies' in metadata:
+ repository_dependencies_root_key = generate_repository_dependencies_key_for_repository( repository, repository_metadata.changeset_revision )
+ for repository_dependency in metadata[ 'repository_dependencies' ]:
+ if repository_dependency not in repository_dependencies:
+ repository_dependencies.append( repository_dependency )
+ else:
+ repository_dependencies_root_key = None
+ if repository_dependencies:
+ repository_dependency = repository_dependencies.pop( 0 )
+ tool_shed, name, owner, changeset_revision = repository_dependency
+ if repository_dependencies_root_key:
+ if repository_dependencies_root_key in all_repository_dependencies:
+ # See if this repository_dependency is contained in the list associated with the repository_dependencies_root_key.
+ all_repository_dependencies_val = all_repository_dependencies[ repository_dependencies_root_key ]
+ if repository_dependency not in all_repository_dependencies_val:
+ all_repository_dependencies_val.append( repository_dependency )
+ all_repository_dependencies[ repository_dependencies_root_key ] = all_repository_dependencies_val
+ else:
+ # Insert this repository_dependency.
+ all_repository_dependencies[ repository_dependencies_root_key ] = [ repository_dependency ]
+ if tool_shed_is_this_tool_shed( tool_shed ):
+ # The repository is in the current tool shed.
+ required_repository = get_repository_by_name_and_owner( trans, name, owner )
+ required_repository_metadata = get_repository_metadata_by_repository_id_changset_revision( trans,
+ trans.security.encode_id( required_repository.id ),
+ changeset_revision )
+ if required_repository_metadata:
+ required_repo_dir = required_repository.repo_path( trans.app )
+ required_repo = hg.repository( get_configured_ui(), required_repo_dir )
+ else:
+ # The repository changeset_revision is no longer installable, so see if there's been an update.
+ required_repo_dir = required_repository.repo_path( trans.app )
+ required_repo = hg.repository( get_configured_ui(), required_repo_dir )
+ required_repository_metadata = get_next_downloadable_changeset_revision( required_repository, required_repo, changeset_revision )
+ if required_repository_metadata:
+ # The required_repository_metadata changeset_revision is installable.
+ required_metadata = required_repository_metadata.metadata
+ if required_metadata:
+ return get_repository_dependencies_for_changeset_revision( trans=trans,
+ repo=required_repo,
+ repository=required_repository,
+ repository_metadata=required_repository_metadata,
+ toolshed_base_url=tool_shed,
+ repository_dependencies=repository_dependencies,
+ all_repository_dependencies=all_repository_dependencies )
+ else:
+ # The repository is in a different tool shed, so build an url and send a request.
+ raise Exception( "Repository dependencies that refer to repositories in other tool sheds is not yet supported." )
+ return all_repository_dependencies
+def get_repository_metadata_by_id( trans, id ):
+ """Get repository metadata from the database"""
+ return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) )
+def get_repository_metadata_by_repository_id( trans, id ):
+ """Get all metadata records for a specified repository."""
+ return trans.sa_session.query( trans.model.RepositoryMetadata ) \
+ .filter( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ) )
+def get_repository_metadata_by_repository_id_changset_revision( trans, id, changeset_revision ):
+ """Get a specified metadata record for a specified repository."""
+ return trans.sa_session.query( trans.model.RepositoryMetadata ) \
+ .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ),
+ trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \
+ .first()
+def get_repository_metadata_revisions_for_review( repository, reviewed=True ):
+ repository_metadata_revisions = []
+ metadata_changeset_revision_hashes = []
+ if reviewed:
+ for metadata_revision in repository.metadata_revisions:
+ metadata_changeset_revision_hashes.append( metadata_revision.changeset_revision )
+ for review in repository.reviews:
+ if review.changeset_revision in metadata_changeset_revision_hashes:
+ rmcr_hashes = [ rmr.changeset_revision for rmr in repository_metadata_revisions ]
+ if review.changeset_revision not in rmcr_hashes:
+ repository_metadata_revisions.append( review.repository_metadata )
+ else:
+ for review in repository.reviews:
+ if review.changeset_revision not in metadata_changeset_revision_hashes:
+ metadata_changeset_revision_hashes.append( review.changeset_revision )
+ for metadata_revision in repository.metadata_revisions:
+ if metadata_revision.changeset_revision not in metadata_changeset_revision_hashes:
+ repository_metadata_revisions.append( metadata_revision )
+ return repository_metadata_revisions
def get_rev_label_changeset_revision_from_repository_metadata( trans, repository_metadata, repository=None ):
if repository is None:
repository = repository_metadata.repository
@@ -359,42 +529,6 @@
for changeset in repo.changelog:
reversed_changelog.insert( 0, changeset )
return reversed_changelog
-def get_repository_by_name( trans, name ):
- """Get a repository from the database via name"""
- return trans.sa_session.query( trans.model.Repository ).filter_by( name=name ).one()
-def get_repository_by_name_and_owner( trans, name, owner ):
- """Get a repository from the database via name and owner"""
- user = get_user_by_username( trans, owner )
- return trans.sa_session.query( trans.model.Repository ) \
- .filter( and_( trans.model.Repository.table.c.name == name,
- trans.model.Repository.table.c.user_id == user.id ) ) \
- .first()
-def get_repository_metadata_by_id( trans, id ):
- """Get repository metadata from the database"""
- return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) )
-def get_repository_metadata_by_repository_id( trans, id ):
- """Get all metadata records for a specified repository."""
- return trans.sa_session.query( trans.model.RepositoryMetadata ) \
- .filter( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ) )
-def get_repository_metadata_revisions_for_review( repository, reviewed=True ):
- repository_metadata_revisions = []
- metadata_changeset_revision_hashes = []
- if reviewed:
- for metadata_revision in repository.metadata_revisions:
- metadata_changeset_revision_hashes.append( metadata_revision.changeset_revision )
- for review in repository.reviews:
- if review.changeset_revision in metadata_changeset_revision_hashes:
- rmcr_hashes = [ rmr.changeset_revision for rmr in repository_metadata_revisions ]
- if review.changeset_revision not in rmcr_hashes:
- repository_metadata_revisions.append( review.repository_metadata )
- else:
- for review in repository.reviews:
- if review.changeset_revision not in metadata_changeset_revision_hashes:
- metadata_changeset_revision_hashes.append( review.changeset_revision )
- for metadata_revision in repository.metadata_revisions:
- if metadata_revision.changeset_revision not in metadata_changeset_revision_hashes:
- repository_metadata_revisions.append( metadata_revision )
- return repository_metadata_revisions
def get_review( trans, id ):
"""Get a repository_review from the database via id"""
return trans.sa_session.query( trans.model.RepositoryReview ).get( trans.security.decode_id( id ) )
@@ -693,6 +827,8 @@
id=trans.security.encode_id( repository.id ),
message=error_message,
status='error' ) )
+def tool_shed_is_this_tool_shed( toolshed_base_url ):
+ return toolshed_base_url.rstrip( '/' ) == str( url_for( '/', qualified=True ) ).rstrip( '/' )
def update_for_browsing( trans, repository, current_working_dir, commit_message='' ):
# This method id deprecated, but we'll keep it around for a while in case we need it. The problem is that hg purge
# is not supported by the mercurial API.
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -1748,9 +1748,11 @@
add_id_to_name=False,
downloadable=False )
revision_label = get_revision_label( trans, repository, repository.tip( trans.app ) )
+ repository_metadata = None
repository_metadata_id = None
metadata = None
is_malicious = False
+ repository_dependencies = []
if changeset_revision != INITIAL_CHANGELOG_HASH:
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
@@ -1768,6 +1770,15 @@
repository_metadata_id = trans.security.encode_id( repository_metadata.id )
metadata = repository_metadata.metadata
is_malicious = repository_metadata.malicious
+ if repository_metadata:
+ # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ repository_dependencies = get_repository_dependencies_for_changeset_revision( trans,
+ repo,
+ repository,
+ repository_metadata,
+ str( url_for( '/', qualified=True ) ).rstrip( '/' ),
+ repository_dependencies=None,
+ all_repository_dependencies=None )
if is_malicious:
if trans.app.security_agent.can_push( trans.app, trans.user, repository ):
message += malicious_error_can_push
@@ -1787,6 +1798,7 @@
review_id = trans.security.encode_id( review.id )
else:
review_id = None
+ containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata )
return trans.fill_template( '/webapps/community/repository/manage_repository.mako',
cntrller=cntrller,
repo_name=repo_name,
@@ -1796,6 +1808,7 @@
allow_push_select_field=allow_push_select_field,
repo=repo,
repository=repository,
+ containers_dict=containers_dict,
repository_metadata_id=repository_metadata_id,
changeset_revision=changeset_revision,
reviewed_by_user=reviewed_by_user,
@@ -1865,22 +1878,35 @@
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
repository = get_repository_in_tool_shed( trans, repository_id )
+ repo_dir = repository.repo_path( trans.app )
+ repo = hg.repository( get_configured_ui(), repo_dir )
changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip( trans.app ) ) )
repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
repository_metadata_id = trans.security.encode_id( repository_metadata.id ),
metadata = repository_metadata.metadata
+ # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ repository_dependencies = get_repository_dependencies_for_changeset_revision( trans,
+ repo,
+ repository,
+ repository_metadata,
+ str( url_for( '/', qualified=True ) ).rstrip( '/' ),
+ repository_dependencies=None,
+ all_repository_dependencies=None )
else:
repository_metadata_id = None
metadata = None
+ repository_dependencies = None
revision_label = get_revision_label( trans, repository, changeset_revision )
changeset_revision_select_field = build_changeset_revision_select_field( trans,
repository,
selected_value=changeset_revision,
add_id_to_name=False,
downloadable=False )
+ containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata )
return trans.fill_template( '/webapps/community/repository/preview_tools_in_changeset.mako',
repository=repository,
+ containers_dict=containers_dict,
repository_metadata_id=repository_metadata_id,
changeset_revision=changeset_revision,
revision_label=revision_label,
@@ -2408,6 +2434,7 @@
email_alerts = from_json_string( repository.email_alerts )
else:
email_alerts = []
+ repository_dependencies = []
user = trans.user
if user and params.get( 'receive_email_alerts_button', False ):
flush_needed = False
@@ -2434,8 +2461,16 @@
revision_label = get_revision_label( trans, repository, changeset_revision )
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
- repository_metadata_id = trans.security.encode_id( repository_metadata.id ),
+ repository_metadata_id = trans.security.encode_id( repository_metadata.id )
metadata = repository_metadata.metadata
+ # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ repository_dependencies = get_repository_dependencies_for_changeset_revision( trans,
+ repo,
+ repository,
+ repository_metadata,
+ str( url_for( '/', qualified=True ) ).rstrip( '/' ),
+ repository_dependencies=None,
+ all_repository_dependencies=None )
else:
repository_metadata_id = None
metadata = None
@@ -2456,12 +2491,14 @@
review_id = trans.security.encode_id( review.id )
else:
review_id = None
+ containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata )
return trans.fill_template( '/webapps/community/repository/view_repository.mako',
cntrller=cntrller,
repo=repo,
repository=repository,
repository_metadata_id=repository_metadata_id,
metadata=metadata,
+ containers_dict=containers_dict,
avg_rating=avg_rating,
display_reviews=display_reviews,
num_ratings=num_ratings,
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/repository_review.py
--- a/lib/galaxy/webapps/community/controllers/repository_review.py
+++ b/lib/galaxy/webapps/community/controllers/repository_review.py
@@ -7,6 +7,7 @@
from galaxy.model.orm import *
from sqlalchemy.sql.expression import func
from common import *
+from galaxy.webapps.community.util.container_util import STRSEP
from repository import RepositoryGrid
from galaxy.util.shed_util_common import *
from galaxy.util.odict import odict
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/workflow.py
--- a/lib/galaxy/webapps/community/controllers/workflow.py
+++ b/lib/galaxy/webapps/community/controllers/workflow.py
@@ -151,7 +151,7 @@
changeset_revision=repository_metadata.changeset_revision,
repository_metadata_id=repository_metadata_id,
workflow_name=workflow_name,
- metadata=repository_metadata,
+ metadata=repository_metadata.metadata,
message=message,
status=status )
@web.expose
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/util/container_util.py
--- /dev/null
+++ b/lib/galaxy/webapps/community/util/container_util.py
@@ -0,0 +1,314 @@
+import logging
+from galaxy.web import url_for
+
+log = logging.getLogger( __name__ )
+
+# String separator
+STRSEP = '__ESEP__'
+
+class Folder( object ):
+ """Container object."""
+ def __init__( self, id=None, key=None, label=None ):
+ self.id = id
+ self.key = key
+ self.label = label
+ self.datatypes = []
+ self.folders = []
+ self.invalid_tools = []
+ self.valid_tools = []
+ self.tool_dependencies = []
+ self.repository_dependencies = []
+ self.workflows = []
+ def contains_folder( self, folder ):
+ for index, contained_folder in enumerate( self.folders ):
+ if folder == contained_folder:
+ return index, contained_folder
+ return 0, None
+
+class Datatype( object ):
+ """Datatype object"""
+ def __init__( self, id=None, extension=None, type=None, mimetype=None, subclass=None ):
+ self.id = id
+ self.extension = extension
+ self.type = type
+ self.mimetype = mimetype
+ self.subclass = subclass
+
+class InvalidTool( object ):
+ """Invalid tool object"""
+ def __init__( self, id=None, tool_config=None, repository_id=None, changeset_revision=None ):
+ self.id = id
+ self.tool_config = tool_config
+ self.repository_id = repository_id
+ self.changeset_revision = changeset_revision
+
+class RepositoryDependency( object ):
+ """Repository dependency object"""
+ def __init__( self, id=None, toolshed=None, repository_name=None, repository_owner=None, changeset_revision=None ):
+ self.id = id
+ self.toolshed = toolshed
+ self.repository_name = repository_name
+ self.repository_owner = repository_owner
+ self.changeset_revision = changeset_revision
+
+class Tool( object ):
+ """Tool object"""
+ def __init__( self, id=None, tool_config=None, tool_id=None, name=None, description=None, version=None, requirements=None,
+ repository_id=None, changeset_revision=None ):
+ self.id = id
+ self.tool_config = tool_config
+ self.tool_id = tool_id
+ self.name = name
+ self.description = description
+ self.version = version
+ self.requirements = requirements
+ self.repository_id = repository_id
+ self.changeset_revision = changeset_revision
+
+class ToolDependency( object ):
+ """Tool dependency object"""
+ def __init__( self, id=None, name=None, version=None, type=None ):
+ self.id = id
+ self.name = name
+ self.version = version
+ self.type = type
+
+class Workflow( object ):
+ """Workflow object"""
+ def __init__( self, id=None, repository_metadata_id=None, workflow_name=None, steps=None, format_version=None, annotation=None ):
+ self.id = id
+ self.repository_metadata_id = repository_metadata_id
+ self.workflow_name = workflow_name
+ self.steps = steps
+ self.format_version = format_version
+ self.annotation = annotation
+
+def build_datatypes_folder( folder_id, datatypes, label='Datatypes' ):
+ """Return a folder hierarchy containing datatypes."""
+ if datatypes:
+ datatype_id = 0
+ folder_id += 1
+ datatypes_root_folder = Folder( id=folder_id, key='root', label='root' )
+ folder_id += 1
+ folder = Folder( id=folder_id, key='datatypes', label=label )
+ datatypes_root_folder.folders.append( folder )
+ # Insert a header row.
+ datatype_id += 1
+ datatype = Datatype( id=datatype_id,
+ extension='extension',
+ type='type',
+ mimetype='mimetype',
+ subclass='subclass' )
+ folder.datatypes.append( datatype )
+ for datatypes_dict in datatypes:
+ datatype_id += 1
+ datatype = Datatype( id=datatype_id,
+ extension=datatypes_dict.get( 'extension', '' ),
+ type=datatypes_dict.get( 'dtype', '' ),
+ mimetype=datatypes_dict.get( 'mimetype', '' ),
+ subclass=datatypes_dict.get( 'subclass', '' ) )
+ folder.datatypes.append( datatype )
+ else:
+ datatypes_root_folder = None
+ return folder_id, datatypes_root_folder
+def build_invalid_tools_folder( folder_id, invalid_tool_configs, repository, changeset_revision, label='Invalid tools' ):
+ """Return a folder hierarchy containing invalid tools."""
+ if invalid_tool_configs:
+ invalid_tool_id = 0
+ folder_id += 1
+ invalid_tools_root_folder = Folder( id=folder_id, key='root', label='root' )
+ folder_id += 1
+ folder = Folder( id=folder_id, key='invalid_tools', label=label )
+ invalid_tools_root_folder.folders.append( folder )
+ for invalid_tool_config in invalid_tool_configs:
+ invalid_tool_id += 1
+ invalid_tool = InvalidTool( id=invalid_tool_id,
+ tool_config=invalid_tool_config,
+ repository_id=repository.id,
+ changeset_revision=changeset_revision )
+ folder.invalid_tools.append( invalid_tool )
+ else:
+ invalid_tools_root_folder = None
+ return folder_id, invalid_tools_root_folder
+def build_repository_dependencies_folder( repository, changeset_revision, folder_id, repository_dependencies, label='Repository dependencies' ):
+ """Return a folder hierarchy containing repository dependencies."""
+ if repository_dependencies:
+ repository_dependency_id = 0
+ folder_id += 1
+ # Create the root folder.
+ repository_dependencies_root_folder = Folder( id=folder_id, key='root', label='root' )
+ folder_id += 1
+ # Create the Repository dependencies folder and add it to the root folder.
+ key = generate_repository_dependencies_key_for_repository( repository, changeset_revision )
+ repository_dependencies_folder = Folder( id=folder_id, key=key, label=label )
+ repository_dependencies_root_folder.folders.append( repository_dependencies_folder )
+ # Process the repository dependencies.
+ for key, val in repository_dependencies.items():
+ # Only create a new folder object if necessary.
+ folder = get_folder( repository_dependencies_root_folder, key )
+ if not folder:
+ # Create a new folder.
+ folder_id += 1
+ label = generate_repository_dependencies_folder_label_from_key( repository, changeset_revision, key )
+ folder = Folder( id=folder_id, key=key, label=label )
+ for repository_dependency_tup in val:
+ toolshed, name, owner, changeset_revision = repository_dependency_tup
+ if not is_folder( repository_dependencies.keys(), toolshed, name, owner, changeset_revision ):
+ # Create a new repository_dependency.
+ repository_dependency_id += 1
+ repository_dependency = RepositoryDependency( id=repository_dependency_id,
+ toolshed=toolshed,
+ repository_name=name,
+ repository_owner=owner,
+ changeset_revision=changeset_revision )
+ # Insert the repository_dependency into the folder.
+ folder.repository_dependencies.append( repository_dependency )
+ if not get_folder( repository_dependencies_folder, key ):
+ # Insert the folder into the list.
+ repository_dependencies_folder.folders.append( folder )
+ else:
+ repository_dependencies_root_folder = None
+ return folder_id, repository_dependencies_root_folder
+def build_tools_folder( folder_id, tool_dicts, repository, changeset_revision, valid=True, label='Valid tools' ):
+ """Return a folder hierarchy containing valid tools."""
+ if tool_dicts:
+ tool_id = 0
+ folder_id += 1
+ tools_root_folder = Folder( id=folder_id, key='root', label='root' )
+ folder_id += 1
+ folder = Folder( id=folder_id, key='tools', label=label )
+ tools_root_folder.folders.append( folder )
+ # Insert a header row.
+ tool_id += 1
+ tool = Tool( id=tool_id,
+ tool_config='',
+ tool_id='',
+ name='Name',
+ description='Description',
+ version='Version',
+ requirements='',
+ repository_id='',
+ changeset_revision='' )
+ folder.valid_tools.append( tool )
+ for tool_dict in tool_dicts:
+ tool_id += 1
+ if 'requirements' in tool_dict:
+ requirements = tool_dict[ 'requirements' ]
+ requirements_str = ''
+ for requirement_dict in requirements:
+ requirements_str += '%s (%s), ' % ( requirement_dict[ 'name' ], requirement_dict[ 'type' ] )
+ requirements_str = requirements_str.rstrip( ', ' )
+ else:
+ requirements_str = 'none'
+ tool = Tool( id=tool_id,
+ tool_config=tool_dict[ 'tool_config' ],
+ tool_id=tool_dict[ 'id' ],
+ name=tool_dict[ 'name' ],
+ description=tool_dict[ 'description' ],
+ version=tool_dict[ 'version' ],
+ requirements=requirements_str,
+ repository_id=repository.id,
+ changeset_revision=changeset_revision )
+ folder.valid_tools.append( tool )
+ else:
+ tools_root_folder = None
+ return folder_id, tools_root_folder
+def build_tool_dependencies_folder( folder_id, tool_dependencies, label='Tool dependencies' ):
+ """Return a folder hierarchy containing tool dependencies."""
+ if tool_dependencies:
+ tool_dependency_id = 0
+ folder_id += 1
+ tool_dependencies_root_folder = Folder( id=folder_id, key='root', label='root' )
+ folder_id += 1
+ folder = Folder( id=folder_id, key='tool_dependencies', label=label )
+ tool_dependencies_root_folder.folders.append( folder )
+ # Insert a header row.
+ tool_dependency_id += 1
+ tool_dependency = ToolDependency( id=tool_dependency_id,
+ name='Name',
+ version='Version',
+ type='Type' )
+ folder.tool_dependencies.append( tool_dependency )
+ for dependency_key, requirements_dict in tool_dependencies.items():
+ tool_dependency_id += 1
+ if dependency_key == 'set_environment':
+ version = None
+ else:
+ version = requirements_dict[ 'version' ]
+ tool_dependency = ToolDependency( id=tool_dependency_id,
+ name=requirements_dict[ 'name' ],
+ version=version,
+ type=requirements_dict[ 'type' ] )
+ folder.tool_dependencies.append( tool_dependency )
+ else:
+ tool_dependencies_root_folder = None
+ return folder_id, tool_dependencies_root_folder
+def build_workflows_folder( folder_id, workflows, repository_metadata, label='Workflows' ):
+ """Return a folder hierarchy containing invalid tools."""
+ if workflows:
+ workflow_id = 0
+ folder_id += 1
+ workflows_root_folder = Folder( id=folder_id, key='root', label='root' )
+ folder_id += 1
+ folder = Folder( id=folder_id, key='workflows', label=label )
+ workflows_root_folder.folders.append( folder )
+ # Insert a header row.
+ workflow_id += 1
+ workflow = Workflow( id=workflow_id,
+ repository_metadata_id=None,
+ workflow_name='Name',
+ steps='steps',
+ format_version='format-version',
+ annotation='annotation' )
+ folder.workflows.append( workflow )
+ for workflow_tup in workflows:
+ workflow_dict=workflow_tup[ 1 ]
+ steps = workflow_dict.get( 'steps', [] )
+ if steps:
+ steps = str( len( steps ) )
+ else:
+ steps = 'unknown'
+ workflow_id += 1
+ workflow = Workflow( id=workflow_id,
+ repository_metadata_id=repository_metadata.id,
+ workflow_name=workflow_dict[ 'name' ],
+ steps=steps,
+ format_version=workflow_dict[ 'format-version' ],
+ annotation=workflow_dict[ 'annotation' ] )
+ folder.workflows.append( workflow )
+ else:
+ workflows_root_folder = None
+ return folder_id, workflows_root_folder
+def generate_repository_dependencies_folder_label_from_key( repository, changeset_revision, key ):
+ """Return a repository dependency label based on the repository dependency key."""
+ if key_is_current_repositorys_key( repository, changeset_revision, key ):
+ label = 'Repository dependencies'
+ else:
+ toolshed_base_url, name, owner, revision = get_components_from_key( key )
+ label = "Repository <b>%s</b> revision <b>%s</b> owned by <b>%s</b>" % ( name, revision, owner )
+ return label
+def generate_repository_dependencies_key_for_repository( repository, changeset_revision ):
+ # FIXME: assumes tool shed is current tool shed since repository dependencies across tool sheds is not yet supported.
+ toolshed_base_url = str( url_for( '/', qualified=True ) ).rstrip( '/' )
+ return '%s%s%s%s%s%s%s' % ( toolshed_base_url, STRSEP, repository.name, STRSEP, repository.user.username, STRSEP, changeset_revision )
+def get_folder( folder, key ):
+ if folder and folder.key == key:
+ return folder
+ for sub_folder in folder.folders:
+ return get_folder( sub_folder, key )
+ return None
+def get_components_from_key( key ):
+ # FIXME: assumes tool shed is current tool shed since repository dependencies across tool sheds is not yet supported.
+ items = key.split( STRSEP )
+ toolshed_base_url = items[ 0 ]
+ repository_name = items[ 1 ]
+ repository_owner = items[ 2 ]
+ changeset_revision = items[ 3 ]
+ return toolshed_base_url, repository_name, repository_owner, changeset_revision
+def is_folder( folder_keys, toolshed_base_url, repository_name, repository_owner, changeset_revision ):
+ key = '%s%s%s%s%s%s%s' % ( toolshed_base_url, STRSEP, repository_name, STRSEP, repository_owner, STRSEP, changeset_revision )
+ return key in folder_keys
+def key_is_current_repositorys_key( repository, changeset_revision, key ):
+ toolshed_base_url, repository_name, repository_owner, changeset_revision = get_components_from_key( key )
+ return repository_name == repository.name and repository_owner == repository.user.username and repository_changeset_revision == changeset_revision
+
\ No newline at end of file
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/common.mako
--- a/templates/webapps/community/repository/common.mako
+++ b/templates/webapps/community/repository/common.mako
@@ -75,6 +75,93 @@
</script></%def>
+<%def name="dependency_javascripts()">
+ <script type="text/javascript">
+ var init_dependencies = function() {
+ var storage_id = "library-expand-state-${trans.security.encode_id(10000)}";
+ var restore_folder_state = function() {
+ var state = $.jStorage.get(storage_id);
+ if (state) {
+ for (var id in state) {
+ if (state[id] === true) {
+ var row = $("#" + id),
+ index = row.parent().children().index(row);
+ row.addClass("expanded").show();
+ row.siblings().filter("tr[parent='" + index + "']").show();
+ }
+ }
+ }
+ };
+ var save_folder_state = function() {
+ var state = {};
+ $("tr.folderRow").each( function() {
+ var folder = $(this);
+ state[folder.attr("id")] = folder.hasClass("expanded");
+ });
+ $.jStorage.set(storage_id, state);
+ };
+ $(".container-table").each(function() {
+ //var container_id = this.id.split( "-" )[0];
+ //alert( container_id );
+ var child_of_parent_cache = {};
+ // Recursively fill in children and descendants of each row
+ var process_row = function(q, parents) {
+ // Find my index
+ var parent = q.parent(),
+ this_level = child_of_parent_cache[parent] || (child_of_parent_cache[parent] = parent.children());
+ var index = this_level.index(q);
+ // Find my immediate children
+ var children = $(par_child_dict[index]);
+ // Recursively handle them
+ var descendants = children;
+ children.each( function() {
+ child_descendants = process_row( $(this), parents.add(q) );
+ descendants = descendants.add(child_descendants);
+ });
+ // Set up expand / hide link
+ var expand_fn = function() {
+ if ( q.hasClass("expanded") ) {
+ descendants.hide();
+ descendants.removeClass("expanded");
+ q.removeClass("expanded");
+ } else {
+ children.show();
+ q.addClass("expanded");
+ }
+ save_folder_state();
+ };
+ $("." + q.attr("id") + "-click").click(expand_fn);
+ // return descendants for use by parent
+ return descendants;
+ }
+ // Initialize dict[parent_id] = rows_which_have_that_parent_id_as_parent_attr
+ var par_child_dict = {},
+ no_parent = [];
+ $(this).find("tbody tr").each( function() {
+ if ( $(this).attr("parent")) {
+ var parent = $(this).attr("parent");
+ if (par_child_dict[parent] !== undefined) {
+ par_child_dict[parent].push(this);
+ } else {
+ par_child_dict[parent] = [this];
+ }
+ } else {
+ no_parent.push(this);
+ }
+ });
+ $(no_parent).each( function() {
+ descendants = process_row( $(this), $([]) );
+ descendants.hide();
+ });
+ });
+ restore_folder_state();
+ };
+ $(function() {
+ init_dependencies();
+ });
+ </script>
+</%def>
+
<%def name="render_clone_str( repository )"><%
from galaxy.util.shed_util_common import generate_clone_url_for_repository_in_tool_shed
@@ -83,272 +170,337 @@
hg clone <a href="${clone_str}">${clone_str}</a></%def>
-<%def name="render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=False )">
- <% from galaxy.tool_shed.encoding_util import tool_shed_encode %>
- %if metadata or can_set_metadata:
+<%def name="render_folder( folder, folder_pad, parent=None, row_counter=None, is_root_folder=False )">
+ <%
+ encoded_id = trans.security.encode_id( folder.id )
+
+ if is_root_folder:
+ pad = folder_pad
+ expander = h.url_for("/static/images/silk/resultset_bottom.png")
+ folder_img = h.url_for("/static/images/silk/folder_page.png")
+ else:
+ pad = folder_pad + 20
+ expander = h.url_for("/static/images/silk/resultset_next.png")
+ folder_img = h.url_for("/static/images/silk/folder.png")
+ my_row = None
+ %>
+ %if not is_root_folder:
+ <%
+ if parent is None:
+ bg_str = 'bgcolor="#D8D8D8"'
+ else:
+ bg_str = ''
+ %>
+ <tr id="folder-${encoded_id}" ${bg_str} class="folderRow libraryOrFolderRow"
+ %if parent is not None:
+ parent="${parent}"
+ style="display: none;"
+ %endif
+ >
+ <%
+ col_span_str = ''
+ if folder.datatypes:
+ label = folder.label
+ col_span_str = 'colspan="4"'
+ elif folder.label == 'Repository dependencies':
+ label = "%s<i> - this repository requires installation of these additional repositories</i>" % folder.label
+ elif folder.repository_dependencies:
+ label = folder.label
+ elif folder.invalid_tools:
+ label = "%s<i> - click the tool config file name to see why the tool is invalid</i>" % folder.label
+ elif folder.tool_dependencies:
+ label = "%s<i> - this repository's tools require installation of these dependencies</i>" % folder.label
+ col_span_str = 'colspan="3"'
+ elif folder.valid_tools:
+ label = "%s<i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i>" % folder.label
+ col_span_str = 'colspan="3"'
+ elif folder.workflows:
+ label = folder.label
+ col_span_str = 'colspan="4"'
+ %>
+ <td ${col_span_str} style="padding-left: ${folder_pad}px;">
+ <span class="expandLink folder-${encoded_id}-click">
+ <div style="float: left; margin-left: 2px;" class="expandLink folder-${encoded_id}-click">
+ <a class="folder-${encoded_id}-click" href="javascript:void(0);">
+ ${label}
+ </a>
+ </div>
+ </span>
+ <td>
+ </tr>
+ <%
+ my_row = row_counter.count
+ row_counter.increment()
+ %>
+ %endif
+ %for sub_folder in folder.folders:
+ ${render_folder( sub_folder, pad, parent=my_row, row_counter=row_counter, is_root_folder=False )}
+ %endfor
+ %for repository_dependency in folder.repository_dependencies:
+ ${render_repository_dependency( repository_dependency, pad, my_row, row_counter )}
+ %endfor
+ %for index, tool_dependency in enumerate( folder.tool_dependencies ):
+ <% row_is_header = index == 0 %>
+ ${render_tool_dependency( tool_dependency, pad, my_row, row_counter, row_is_header )}
+ %endfor
+ %if folder.valid_tools:
+ %for index, tool in enumerate( folder.valid_tools ):
+ <% row_is_header = index == 0 %>
+ ${render_tool( tool, pad, my_row, row_counter, row_is_header )}
+ %endfor
+ %endif
+ %for invalid_tool in folder.invalid_tools:
+ ${render_invalid_tool( invalid_tool, pad, my_row, row_counter )}
+ %endfor
+ %if folder.workflows:
+ %for index, workflow in enumerate( folder.workflows ):
+ <% row_is_header = index == 0 %>
+ ${render_workflow( workflow, pad, my_row, row_counter, row_is_header )}
+ %endfor
+ %endif
+ %if folder.datatypes:
+ %for index, datatype in enumerate( folder.datatypes ):
+ <% row_is_header = index == 0 %>
+ ${render_datatype( datatype, pad, my_row, row_counter, row_is_header )}
+ %endfor
+ %endif
+</%def>
+
+<%def name="render_datatype( datatype, pad, parent, row_counter, row_is_header=False )">
+ <%
+ encoded_id = trans.security.encode_id( datatype.id )
+ if row_is_header:
+ cell_type = 'th'
+ else:
+ cell_type = 'td'
+ %>
+ <tr class="datasetRow"
+ %if parent is not None:
+ parent="${parent}"
+ %endif
+ id="libraryItem-${encoded_id}">
+ <${cell_type} style="padding-left: ${pad+20}px;">${datatype.extension | h}</${cell_type}>
+ <${cell_type}>${datatype.type | h}</${cell_type}>
+ <${cell_type}>${datatype.mimetype | h}</${cell_type}>
+ <${cell_type}>${datatype.subclass | h}</${cell_type}>
+ </tr>
+ <%
+ my_row = row_counter.count
+ row_counter.increment()
+ %>
+</%def>
+
+<%def name="render_invalid_tool( invalid_tool, pad, parent, row_counter, valid=True )">
+ <% encoded_id = trans.security.encode_id( invalid_tool.id ) %>
+ <tr class="datasetRow"
+ %if parent is not None:
+ parent="${parent}"
+ %endif
+ id="libraryItem-${encoded_id}">
+ <td style="padding-left: ${pad+20}px;">
+ <a class="view-info" href="${h.url_for( controller='repository', action='load_invalid_tool', repository_id=trans.security.encode_id( invalid_tool.repository_id ), tool_config=invalid_tool.tool_config, changeset_revision=invalid_tool.changeset_revision )}">
+ ${invalid_tool.tool_config | h}
+ </a>
+ </td>
+ </tr>
+ <%
+ my_row = row_counter.count
+ row_counter.increment()
+ %>
+</%def>
+
+<%def name="render_repository_dependency( repository_dependency, pad, parent, row_counter )">
+
+ <% encoded_id = trans.security.encode_id( repository_dependency.id ) %>
+ <tr class="datasetRow"
+ %if parent is not None:
+ parent="${parent}"
+ %endif
+ id="libraryItem-${encoded_id}">
+ ##<td style="padding-left: ${pad+20}px;">${repository_dependency.toolshed | h}</td>
+ <td style="padding-left: ${pad+20}px;">Repository <b>${repository_dependency.repository_name | h}</b> revision <b>${repository_dependency.changeset_revision | h}</b> owned by <b>${repository_dependency.repository_owner | h}</b></td>
+ </tr>
+ <%
+ my_row = row_counter.count
+ row_counter.increment()
+ %>
+</%def>
+
+<%def name="render_tool( tool, pad, parent, row_counter, row_is_header )">
+ <%
+ encoded_id = trans.security.encode_id( tool.id )
+ if row_is_header:
+ cell_type = 'th'
+ else:
+ cell_type = 'td'
+ %>
+ <tr class="datasetRow"
+ %if parent is not None:
+ parent="${parent}"
+ %endif
+ id="libraryItem-${encoded_id}">
+ %if row_is_header:
+ <th style="padding-left: ${pad+20}px;">${tool.name | h}</th>
+ %else:
+ <td style="padding-left: ${pad+20}px;">
+ <div style="float:left;" class="menubutton split popup" id="tool-${encoded_id}-popup">
+ <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( tool.repository_id ), tool_config=tool.tool_config, changeset_revision=tool.changeset_revision )}">${tool.name | h}</a>
+ </div>
+ <div popupmenu="tool-${encoded_id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( tool.repository_id ), changeset_revision=tool.changeset_revision, tool_id=tool.tool_id )}">View tool metadata</a>
+ </div>
+ </td>
+ %endif
+ <${cell_type}>${tool.description | h}</${cell_type}>
+ <${cell_type}>${tool.version | h}</${cell_type}>
+ ##<${cell_type}>${tool.requirements | h}</${cell_type}>
+ </tr>
+ <%
+ my_row = row_counter.count
+ row_counter.increment()
+ %>
+</%def>
+
+<%def name="render_tool_dependency( tool_dependency, pad, parent, row_counter, row_is_header )">
+ <%
+ encoded_id = trans.security.encode_id( tool_dependency.id )
+ if row_is_header:
+ cell_type = 'th'
+ else:
+ cell_type = 'td'
+ %>
+ <tr class="datasetRow"
+ %if parent is not None:
+ parent="${parent}"
+ %endif
+ id="libraryItem-${encoded_id}">
+ <${cell_type} style="padding-left: ${pad+20}px;">${tool_dependency.name | h}</${cell_type}>
+ <${cell_type}>
+ <%
+ if tool_dependency.version:
+ version_str = tool_dependency.version
+ else:
+ version_str = ''
+ %>
+ ${version_str | h}
+ </${cell_type}>
+ <${cell_type}>${tool_dependency.type | h}</${cell_type}>
+ </tr>
+ <%
+ my_row = row_counter.count
+ row_counter.increment()
+ %>
+</%def>
+
+<%def name="render_workflow( workflow, pad, parent, row_counter, row_is_header=False )">
+ <%
+ from galaxy.tool_shed.encoding_util import tool_shed_encode
+ encoded_id = trans.security.encode_id( workflow.id )
+ if row_is_header:
+ cell_type = 'th'
+ else:
+ cell_type = 'td'
+ %>
+ <tr class="datasetRow"
+ %if parent is not None:
+ parent="${parent}"
+ %endif
+ id="libraryItem-${encoded_id}">
+ <${cell_type} style="padding-left: ${pad+20}px;">
+ %if row_is_header:
+ ${workflow.workflow_name | h}
+ %else:
+ <a href="${h.url_for( controller='workflow', action='view_workflow', repository_metadata_id=trans.security.encode_id( workflow.repository_metadata_id ), workflow_name=tool_shed_encode( workflow.workflow_name ) )}">${workflow.workflow_name | h}</a>
+ %endif
+ </${cell_type}>
+ <${cell_type}>${workflow.steps | h}</${cell_type}>
+ <${cell_type}>${workflow.format_version | h}</${cell_type}>
+ <${cell_type}>${workflow.annotation | h}</${cell_type}>
+ </tr>
+ <%
+ my_row = row_counter.count
+ row_counter.increment()
+ %>
+</%def>
+
+<%def name="render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=False )">
+ <%
+ from galaxy.tool_shed.encoding_util import tool_shed_encode
+
+ has_datatypes = metadata and 'datatypes' in metadata
+ has_readme = metadata and 'readme' in metadata
+ has_workflows = metadata and 'workflows' in metadata
+
+ datatypes_root_folder = containers_dict[ 'datatypes' ]
+ invalid_tools_root_folder = containers_dict[ 'invalid_tools' ]
+ repository_dependencies_root_folder = containers_dict[ 'repository_dependencies' ]
+ tool_dependencies_root_folder = containers_dict[ 'tool_dependencies' ]
+ valid_tools_root_folder = containers_dict[ 'valid_tools' ]
+ workflows_root_folder = containers_dict[ 'workflows' ]
+
+ has_contents = datatypes_root_folder, invalid_tools_root_folder or valid_tools_root_folder or workflows_root_folder
+
+ class RowCounter( object ):
+ def __init__( self ):
+ self.count = 0
+ def increment( self ):
+ self.count += 1
+ def __str__( self ):
+ return str( self.count )
+ %>
+ %if repository_dependencies_root_folder or tool_dependencies_root_folder:
+ <div class="toolForm">
+ <div class="toolFormTitle">Dependencies of this repository</div>
+ <div class="toolFormBody">
+ %if repository_dependencies_root_folder:
+ <p/>
+ <% row_counter = RowCounter() %>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="repository_dependencies">
+ ${self.render_folder( repository_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+ </table>
+ %endif
+ %if tool_dependencies_root_folder:
+ <p/>
+ <% row_counter = RowCounter() %>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="tool_dependencies">
+ ${self.render_folder( tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+ </table>
+ %endif
+ </div>
+ </div>
+ %endif
+ %if has_contents:
<p/><div class="toolForm">
- <div class="toolFormTitle">Preview tools and inspect metadata by tool version</div>
+ <div class="toolFormTitle">Contents of this repository</div><div class="toolFormBody">
- %if metadata:
- %if 'repository_dependencies' in metadata:
- <div class="form-row">
- <table class="grid">
- <tr>
- <td><b>tool shed</b></td>
- <td><b>name</b></td>
- <td><b>version</b></td>
- <td><b>type</b></td>
- </tr>
- %for repository_dependency_tup in metadata[ 'repository_dependencies' ]:
- <% toolshed, name, owner, changeset_revision = repository_dependency_tup %>
- <tr>
- <td>${toolshed | h}</td>
- <td>${name | h}</td>
- <td>${owner | h}</td>
- <td>${changeset_revision | h}</td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %if 'tool_dependencies' in metadata:
- <%
- # See if tool dependencies are packages, environment settings or both.
- tool_dependencies = metadata[ 'tool_dependencies' ]
- contains_packages = False
- for k in tool_dependencies.keys():
- if k != 'set_environment':
- contains_packages = True
- break
- contains_env_settings = 'set_environment' in tool_dependencies.keys()
- %>
- %if contains_packages:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>The following tool dependencies can optionally be automatically installed</i></td>
- </tr>
- </table>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>version</b></td>
- <td><b>type</b></td>
- </tr>
- %for dependency_key, requirements_dict in tool_dependencies.items():
- %if dependency_key != 'set_environment':
- <%
- name = requirements_dict[ 'name' ]
- version = requirements_dict[ 'version' ]
- type = requirements_dict[ 'type' ]
- %>
- <tr>
- <td>${name | h}</td>
- <td>${version | h}</td>
- <td>${type | h}</td>
- </tr>
- %endif
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %if contains_env_settings:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>The following environment settings can optionally be handled as part of the installation</i></td>
- </tr>
- </table>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>type</b></td>
- </tr>
- <% environment_settings = tool_dependencies[ 'set_environment' ] %>
- %for requirements_dict in environment_settings:
- <tr>
- <td>${requirements_dict[ 'name' ] | h}</td>
- <td>${requirements_dict[ 'type' ] | h}</td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %endif
- %if 'tools' in metadata:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Valid tools</b><i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i></td>
- </tr>
- </table>
- </div>
- <div class="form-row">
- <% tool_dicts = metadata[ 'tools' ] %>
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>description</b></td>
- <td><b>version</b></td>
- <td><b>requirements</b></td>
- </tr>
- %for index, tool_dict in enumerate( tool_dicts ):
- <tr>
- <td>
- <div style="float:left;" class="menubutton split popup" id="tool-${index}-popup">
- <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ], changeset_revision=changeset_revision )}">${tool_dict[ 'name' ]}</a>
- </div>
- <div popupmenu="tool-${index}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, tool_id=tool_dict[ 'id' ] )}">View tool metadata</a>
- </div>
- </td>
- <td>${tool_dict[ 'description' ] | h}</td>
- <td>${tool_dict[ 'version' ] | h}</td>
- <td>
- <%
- if 'requirements' in tool_dict:
- requirements = tool_dict[ 'requirements' ]
- else:
- requirements = None
- %>
- %if requirements:
- <%
- requirements_str = ''
- for requirement_dict in tool_dict[ 'requirements' ]:
- requirements_str += '%s (%s), ' % ( requirement_dict[ 'name' ], requirement_dict[ 'type' ] )
- requirements_str = requirements_str.rstrip( ', ' )
- %>
- ${requirements_str | h}
- %else:
- none
- %endif
- </td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %if 'invalid_tools' in metadata:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Invalid tools</b><i> - click the tool config file name to see why the tool is invalid</i></td>
- </tr>
- </table>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <% invalid_tool_configs = metadata[ 'invalid_tools' ] %>
- <table class="grid">
- %for invalid_tool_config in invalid_tool_configs:
- <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 | h}
- </a>
- </td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %if 'workflows' in metadata:
- ## metadata[ 'workflows' ] is a list of tuples where each contained tuple is
- ## [ <relative path to the .ga file in the repository>, <exported workflow dict> ]
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Workflows</b></td>
- </tr>
- </table>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <% workflow_tups = metadata[ 'workflows' ] %>
- <table class="grid">
- <tr>
- <td><b>name</b></td>
- <td><b>steps</b></td>
- <td><b>format-version</b></td>
- <td><b>annotation</b></td>
- </tr>
- %for workflow_tup in workflow_tups:
- <%
- relative_path = workflow_tup[0]
- workflow_dict = workflow_tup[1]
- workflow_name = workflow_dict[ 'name' ]
- ## Initially steps were not stored in the metadata record.
- steps = workflow_dict.get( 'steps', [] )
- format_version = workflow_dict[ 'format-version' ]
- annotation = workflow_dict[ 'annotation' ]
- %>
- <tr>
- <td>
- <a href="${h.url_for( controller='workflow', action='view_workflow', repository_metadata_id=repository_metadata_id, workflow_name=tool_shed_encode( workflow_name ) )}">${workflow_name | h}</a>
- </td>
- <td>
- %if steps:
- ${len( steps )}
- %else:
- unknown
- %endif
- </td>
- <td>${format_version | h}</td>
- <td>${annotation | h}</td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
- %if 'datatypes' in metadata:
- <div class="form-row">
- <table width="100%">
- <tr bgcolor="#D8D8D8" width="100%">
- <td><b>Data types</b></td>
- </tr>
- </table>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <% datatypes_dicts = metadata[ 'datatypes' ] %>
- <table class="grid">
- <tr>
- <td><b>extension</b></td>
- <td><b>type</b></td>
- <td><b>mimetype</b></td>
- <td><b>subclass</b></td>
- </tr>
- %for datatypes_dict in datatypes_dicts:
- <%
- extension = datatypes_dict.get( 'extension', ' ' )
- dtype = datatypes_dict.get( 'dtype', ' ' )
- mimetype = datatypes_dict.get( 'mimetype', ' ' )
- subclass = datatypes_dict.get( 'subclass', ' ' )
- %>
- <tr>
- <td>${extension | h}</td>
- <td>${dtype | h}</td>
- <td>${mimetype | h}</td>
- <td>${subclass | h}</td>
- </tr>
- %endfor
- </table>
- </div>
- <div style="clear: both"></div>
- %endif
+ %if valid_tools_root_folder:
+ <p/>
+ <% row_counter = RowCounter() %>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="valid_tools">
+ ${self.render_folder( valid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+ </table>
+ %endif
+ %if invalid_tools_root_folder:
+ <p/>
+ <% row_counter = RowCounter() %>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="invalid_tools">
+ ${self.render_folder( invalid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+ </table>
+ %endif
+ %if workflows_root_folder:
+ <p/>
+ <% row_counter = RowCounter() %>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="workflows">
+ ${self.render_folder( workflows_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+ </table>
+ %endif
+ %if datatypes_root_folder:
+ <p/>
+ <% row_counter = RowCounter() %>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="datatypes">
+ ${self.render_folder( datatypes_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+ </table>
%endif
</div></div>
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/manage_repository.mako
--- a/templates/webapps/community/repository/manage_repository.mako
+++ b/templates/webapps/community/repository/manage_repository.mako
@@ -16,10 +16,6 @@
can_set_metadata = not is_new and not is_deprecated
can_rate = not is_new and not is_deprecated 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_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip( trans.app )
can_deprecate = not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated
can_undeprecate = trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated
@@ -27,6 +23,11 @@
has_readme = metadata and 'readme' in metadata
can_review_repository = not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
reviewing_repository = cntrller and cntrller == 'repository_review'
+
+ if can_push:
+ browse_label = 'Browse or delete repository tip files'
+ else:
+ browse_label = 'Browse repository tip files'
if changeset_revision == repository.tip( trans.app ):
tip_str = 'repository tip'
else:
@@ -42,10 +43,15 @@
%><%inherit file="${inherit(context)}"/>
+<%def name="stylesheets()">
+ ${parent.stylesheets()}
+ ${h.css( "library" )}
+</%def>
+
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "libs/jquery/jquery.rating" )}
- ${common_javascripts(repository)}
+ ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
+ ${dependency_javascripts()}
</%def><br/><br/>
@@ -204,7 +210,7 @@
</form></div></div>
-${render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=True )}
+${render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=True )}
<p/><div class="toolForm"><div class="toolFormTitle">Manage categories</div>
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/preview_tools_in_changeset.mako
--- a/templates/webapps/community/repository/preview_tools_in_changeset.mako
+++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako
@@ -28,10 +28,15 @@
%><%inherit file="${inherit(context)}"/>
+<%def name="stylesheets()">
+ ${parent.stylesheets()}
+ ${h.css( "library" )}
+</%def>
+
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "libs/jquery/jquery.rating" )}
- ${common_javascripts(repository)}
+ ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
+ ${dependency_javascripts()}
</%def><br/><br/>
@@ -79,4 +84,4 @@
</div></div><p/>
-${render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=False )}
+${render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=False )}
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/view_repository.mako
--- a/templates/webapps/community/repository/view_repository.mako
+++ b/templates/webapps/community/repository/view_repository.mako
@@ -32,10 +32,15 @@
%><%inherit file="${inherit(context)}"/>
+<%def name="stylesheets()">
+ ${parent.stylesheets()}
+ ${h.css( "library" )}
+</%def>
+
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "libs/jquery/jquery.rating" )}
- ${common_javascripts(repository)}
+ ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )}
+ ${dependency_javascripts()}
</%def><br/><br/>
@@ -181,7 +186,7 @@
%endif
</div></div>
-${render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=False )}
+${render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=False )}
%if repository.categories:
<p/><div class="toolForm">
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository_review/browse_review.mako
--- a/templates/webapps/community/repository_review/browse_review.mako
+++ b/templates/webapps/community/repository_review/browse_review.mako
@@ -4,7 +4,7 @@
<%
from galaxy.web.form_builder import CheckboxField
- from galaxy.webapps.community.controllers.common import STRSEP
+ from galaxy.webapps.community.util.container_util import STRSEP
can_manage_repository = is_admin or repository.user == trans.user
%>
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository_review/edit_review.mako
--- a/templates/webapps/community/repository_review/edit_review.mako
+++ b/templates/webapps/community/repository_review/edit_review.mako
@@ -5,7 +5,7 @@
<%
from galaxy.web.form_builder import CheckboxField
from galaxy.webapps.community.controllers.repository_review import build_approved_select_field
- from galaxy.webapps.community.controllers.common import STRSEP
+ from galaxy.webapps.community.util.container_util import STRSEP
can_manage_repository = is_admin or repository.user == trans.user
%>
diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository_review/reviews_of_changeset_revision.mako
--- a/templates/webapps/community/repository_review/reviews_of_changeset_revision.mako
+++ b/templates/webapps/community/repository_review/reviews_of_changeset_revision.mako
@@ -5,7 +5,7 @@
<%
from galaxy.webapps.community.controllers.repository_review import build_approved_select_field
- from galaxy.webapps.community.controllers.common import STRSEP
+ from galaxy.webapps.community.util.container_util import STRSEP
is_admin = trans.user_is_admin()
is_new = repository.is_new( trans.app )
can_browse_contents = not is_new
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 the tool migration process that was broken due to the recent changes in the imports to various Galaxy framework files, mostly the Galaxy model.
by Bitbucket 24 Nov '12
by Bitbucket 24 Nov '12
24 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/eea034b7cc62/
changeset: eea034b7cc62
user: greg
date: 2012-11-24 16:21:48
summary: Fix the tool migration process that was broken due to the recent changes in the imports to various Galaxy framework files, mostly the Galaxy model.
affected #: 4 files
diff -r 1d078ed70cb8faf207c6367761a683bf6d9c3e68 -r eea034b7cc625fa294fdd1e071d99defb40f67d3 lib/galaxy/tool_shed/__init__.py
--- a/lib/galaxy/tool_shed/__init__.py
+++ b/lib/galaxy/tool_shed/__init__.py
@@ -2,7 +2,7 @@
Classes encapsulating the management of repositories installed from Galaxy tool sheds.
"""
import os
-import galaxy.util.shed_util
+from galaxy.util.shed_util import *
from galaxy.model.orm import *
from galaxy import eggs
@@ -27,7 +27,7 @@
ElementInclude.include( root )
tool_path = root.get( 'tool_path', None )
if tool_path:
- tool_shed = galaxy.util.shed_util.clean_tool_shed_url( tool_shed_repository.tool_shed )
+ tool_shed = clean_tool_shed_url( tool_shed_repository.tool_shed )
relative_path = os.path.join( tool_path,
tool_shed,
'repos',
@@ -44,13 +44,13 @@
.order_by( self.model.ToolShedRepository.table.c.id ):
relative_install_dir = self.get_repository_install_dir( tool_shed_repository )
if relative_install_dir:
- installed_repository_dict = galaxy.util.shed_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
+ installed_repository_dict = load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
if installed_repository_dict:
self.installed_repository_dicts.append( installed_repository_dict )
def load_proprietary_converters_and_display_applications( self, deactivate=False ):
for installed_repository_dict in self.installed_repository_dicts:
if installed_repository_dict[ 'converter_path' ]:
- galaxy.util.shed_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
+ load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
if installed_repository_dict[ 'display_path' ]:
- galaxy.util.shed_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
+ load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
\ No newline at end of file
diff -r 1d078ed70cb8faf207c6367761a683bf6d9c3e68 -r eea034b7cc625fa294fdd1e071d99defb40f67d3 lib/galaxy/tool_shed/migrate/common.py
--- a/lib/galaxy/tool_shed/migrate/common.py
+++ b/lib/galaxy/tool_shed/migrate/common.py
@@ -2,6 +2,7 @@
import galaxy.config
import galaxy.datatypes.registry
from galaxy import tools
+from galaxy.tools.data import *
import galaxy.model.mapping
import galaxy.tools.search
from galaxy.objectstore import build_object_store_from_config
@@ -42,8 +43,8 @@
# Load the data types in the Galaxy distribution, which are defined in self.config.datatypes_config.
self.datatypes_registry.load_datatypes( self.config.root, self.config.datatypes_config )
# Initialize tool data tables using the config defined by self.config.tool_data_table_config_path.
- self.tool_data_tables = galaxy.tools.data.ToolDataTableManager( tool_data_path=self.config.tool_data_path,
- config_filename=self.config.tool_data_table_config_path )
+ self.tool_data_tables = ToolDataTableManager( tool_data_path=self.config.tool_data_path,
+ config_filename=self.config.tool_data_table_config_path )
# Load additional entries defined by self.config.shed_tool_data_table_config into tool data tables.
self.tool_data_tables.load_from_config_file( config_filename=self.config.shed_tool_data_table_config,
tool_data_path=self.tool_data_tables.tool_data_path,
diff -r 1d078ed70cb8faf207c6367761a683bf6d9c3e68 -r eea034b7cc625fa294fdd1e071d99defb40f67d3 lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -1,7 +1,6 @@
import os, tempfile, shutil, logging, urllib2
from galaxy import util
from galaxy.datatypes.checkers import *
-from galaxy.datatypes.sniff import is_column_based
from galaxy.util.json import *
from galaxy.util.shed_util_common import *
from galaxy.tools.search import ToolBoxSearch
@@ -475,13 +474,6 @@
else:
tool_section = None
return tool_section
-def generate_workflow_metadata( relative_path, exported_workflow_dict, metadata_dict ):
- """Update the received metadata_dict with changes that have been applied to the received exported_workflow_dict."""
- if 'workflows' in metadata_dict:
- metadata_dict[ 'workflows' ].append( ( relative_path, exported_workflow_dict ) )
- else:
- metadata_dict[ 'workflows' ] = [ ( relative_path, exported_workflow_dict ) ]
- return metadata_dict
def get_config( config_file, repo, ctx, dir ):
"""Return the latest version of config_filename from the repository manifest."""
config_file = strip_path( config_file )
@@ -817,6 +809,24 @@
parent_id=tool_version_using_parent_id.id )
sa_session.add( tool_version_association )
sa_session.flush()
+def is_column_based( fname, sep='\t', skip=0, is_multi_byte=False ):
+ """See if the file is column based with respect to a separator."""
+ headers = get_headers( fname, sep, is_multi_byte=is_multi_byte )
+ count = 0
+ if not headers:
+ return False
+ for hdr in headers[ skip: ]:
+ if hdr and hdr[ 0 ] and not hdr[ 0 ].startswith( '#' ):
+ if len( hdr ) > 1:
+ count = len( hdr )
+ break
+ if count < 2:
+ return False
+ for hdr in headers[ skip: ]:
+ if hdr and hdr[ 0 ] and not hdr[ 0 ].startswith( '#' ):
+ if len( hdr ) != count:
+ return False
+ return True
def is_data_index_sample_file( file_path ):
"""
Attempt to determine if a .sample file is appropriate for copying to ~/tool-data when a tool shed repository is being installed
diff -r 1d078ed70cb8faf207c6367761a683bf6d9c3e68 -r eea034b7cc625fa294fdd1e071d99defb40f67d3 lib/galaxy/util/shed_util_common.py
--- a/lib/galaxy/util/shed_util_common.py
+++ b/lib/galaxy/util/shed_util_common.py
@@ -2,6 +2,7 @@
from galaxy import util
from galaxy.tools import parameters
from galaxy.util import inflector
+from galaxy.util.json import *
from galaxy.web import url_for
from galaxy.web.form_builder import SelectField
from galaxy.datatypes.checkers import *
@@ -724,6 +725,13 @@
else:
metadata_dict[ 'tools' ] = [ tool_dict ]
return metadata_dict
+def generate_workflow_metadata( relative_path, exported_workflow_dict, metadata_dict ):
+ """Update the received metadata_dict with changes that have been applied to the received exported_workflow_dict."""
+ if 'workflows' in metadata_dict:
+ metadata_dict[ 'workflows' ].append( ( relative_path, exported_workflow_dict ) )
+ else:
+ metadata_dict[ 'workflows' ] = [ ( relative_path, exported_workflow_dict ) ]
+ return metadata_dict
def get_changectx_for_changeset( repo, changeset_revision, **kwd ):
"""Retrieve a specified changectx from a repository"""
for changeset in repo.changelog:
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: Added tool shed functional test features for tool metadata.
by Bitbucket 21 Nov '12
by Bitbucket 21 Nov '12
21 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/1d078ed70cb8/
changeset: 1d078ed70cb8
user: inithello
date: 2012-11-21 22:32:17
summary: Added tool shed functional test features for tool metadata.
affected #: 2 files
diff -r 7d278a17747ad9cb35b1af5ec011e46f814c339a -r 1d078ed70cb8faf207c6367761a683bf6d9c3e68 test/tool_shed/base/twilltestcase.py
--- a/test/tool_shed/base/twilltestcase.py
+++ b/test/tool_shed/base/twilltestcase.py
@@ -30,6 +30,11 @@
if strings_not_displayed:
for string in strings_not_displayed:
self.check_string_not_in_page( string )
+ def check_for_tool_metadata(self, repository, changeset_revision, tool_id, strings_displayed=[], strings_not_displayed=[] ):
+ url = '/repository/view_tool_metadata?repository_id=%s&changeset_revision=%s&tool_id=%s' % \
+ ( self.security.encode_id( repository.id ), changeset_revision, tool_id )
+ self.visit_url( url )
+ self.check_for_strings( strings_displayed, strings_not_displayed )
def check_for_valid_tools( self, repository ):
self.manage_repository( repository )
self.check_page_for_string( '<b>Valid tools</b><i> - click the name to preview the tool' )
@@ -118,6 +123,14 @@
tc.fv( "3", "allow_push", '+%s' % username )
tc.submit( 'user_access_button' )
self.check_for_strings( strings_displayed, strings_not_displayed )
+ def load_display_tool_page( self, repository, tool_xml_filename, changeset_revision, strings_displayed=[], strings_not_displayed=[] ):
+ repository_id = self.security.encode_id( repository.id )
+ repo_subdirectory = '%03d' % int( repository.id / 1000 )
+ tool_xml_path = '%2f'.join( [ 'database', 'community_files', repo_subdirectory, 'repo_%d' % repository.id, tool_xml_filename ] )
+ url = '/repository/display_tool?repository_id=%s&tool_config=%s&changeset_revision=%s' % \
+ ( repository_id, tool_xml_path, changeset_revision )
+ self.visit_url( url )
+ self.check_for_strings( strings_displayed, strings_not_displayed )
def manage_repository( self, repository, strings_displayed=[], strings_not_displayed=[] ):
url = '/repository/manage_repository?id=%s' % self.security.encode_id( repository.id )
self.visit_url( url )
diff -r 7d278a17747ad9cb35b1af5ec011e46f814c339a -r 1d078ed70cb8faf207c6367761a683bf6d9c3e68 test/tool_shed/functional/test_0000_create_repository.py
--- a/test/tool_shed/functional/test_0000_create_repository.py
+++ b/test/tool_shed/functional/test_0000_create_repository.py
@@ -69,11 +69,18 @@
strings_displayed=[ "The file '%s' has been successfully uploaded to the repository." % filter_filename ], \
commit_message="Uploaded filtering 1.1.0" )
self.check_for_valid_tools( repository )
- latest_changeset_revision = self.get_latest_repository_metadata_for_repository( repository )
+ latest_repository_metadata = self.get_latest_repository_metadata_for_repository( repository )
+ changeset_revision = latest_repository_metadata.changeset_revision
self.check_repository_changelog( repository, strings_displayed=[ 'Repository metadata is associated with this change set.' ] )
self.set_repository_malicious( repository, strings_displayed=[ 'The repository tip has been defined as malicious.' ] )
self.unset_repository_malicious( repository, strings_displayed=[ 'The repository tip has been defined as <b>not</b> malicious.' ] )
-# self.check_tool_metadata( repository, latest_changeset_revision, strings_displayed=[ 'Filter1' ] )
+ self.load_display_tool_page( repository, tool_xml_filename='filtering.xml', \
+ changeset_revision=changeset_revision, \
+ strings_displayed=[ 'Filter (version 1.1.0)', "c1=='chr1'" ], \
+ strings_not_displayed=[] )
+ tool = latest_repository_metadata.metadata[ 'tools' ][0]
+ metadata_strings_displayed = [ tool[ 'guid' ], tool[ 'version' ], tool[ 'id' ], tool[ 'name' ], tool[ 'description' ], changeset_revision ]
+ self.check_for_tool_metadata( repository, changeset_revision, 'Filter1', strings_displayed=metadata_strings_displayed )
def test_0035_repository_browse_page( self ):
'''Visit the repository browse page'''
repository = get_repository_by_name( repository_name, admin_username )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: history panel: documenting fix to show display and edit attributes buttons for HDA in the error state.
by Bitbucket 21 Nov '12
by Bitbucket 21 Nov '12
21 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/7d278a17747a/
changeset: 7d278a17747a
user: carlfeberhard
date: 2012-11-21 20:02:58
summary: history panel: documenting fix to show display and edit attributes buttons for HDA in the error state.
affected #: 2 files
diff -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 -r 7d278a17747ad9cb35b1af5ec011e46f814c339a static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -181,7 +181,8 @@
* @returns {jQuery} rendered DOM
*/
_render_displayButton : function(){
- // don't show display if not in ready state, error'd, or not accessible
+ // don't show display if not in ready state or not accessible
+ // DO show if in error (ala previous history panel)
if( ( !this.model.inReadyState() )
//|| ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR )
|| ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
diff -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 -r 7d278a17747ad9cb35b1af5ec011e46f814c339a static/scripts/mvc/dataset/hda-edit.js
--- a/static/scripts/mvc/dataset/hda-edit.js
+++ b/static/scripts/mvc/dataset/hda-edit.js
@@ -64,8 +64,8 @@
* @returns {jQuery} rendered DOM
*/
_render_editButton : function(){
- // don't show edit while uploading
- //TODO??: error?
+ // don't show edit while uploading, in-accessible
+ // DO show if in error (ala previous history panel)
//TODO??: not viewable/accessible are essentially the same (not viewable set from accessible)
if( ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.UPLOAD )
//|| ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR )
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
21 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/8481560e2c32/
changeset: 8481560e2c32
user: carlfeberhard
date: 2012-11-21 19:28:33
summary: history panel: moved refresh into 'History' header bar. Moved 'Collapse Expanded Datasets', 'Show/Hide Deleted Datasets', and 'Show/Hide Hidden Datasets' into 'History' gear menu. Removed gear menu from current history. Packed scripts.
affected #: 15 files
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -183,7 +183,7 @@
_render_displayButton : function(){
// don't show display if not in ready state, error'd, or not accessible
if( ( !this.model.inReadyState() )
- || ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR )
+ //|| ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR )
|| ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
|| ( !this.model.get( 'accessible' ) ) ){
this.displayButton = null;
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/mvc/dataset/hda-edit.js
--- a/static/scripts/mvc/dataset/hda-edit.js
+++ b/static/scripts/mvc/dataset/hda-edit.js
@@ -68,7 +68,7 @@
//TODO??: error?
//TODO??: not viewable/accessible are essentially the same (not viewable set from accessible)
if( ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.UPLOAD )
- || ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR )
+ //|| ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR )
|| ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
|| ( !this.model.get( 'accessible' ) ) ){
this.editButton = null;
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/mvc/dataset/hda-model.js
--- a/static/scripts/mvc/dataset/hda-model.js
+++ b/static/scripts/mvc/dataset/hda-model.js
@@ -125,6 +125,8 @@
*/
inReadyState : function(){
var state = this.get( 'state' );
+ //TODO: to list inclusion test
+ //TODO: class level readyStates list
return (
( state === HistoryDatasetAssociation.STATES.NEW )
|| ( state === HistoryDatasetAssociation.STATES.OK )
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -127,7 +127,6 @@
/** event map
*/
events : {
- 'click #history-refresh' : function(){ window.location.reload(); },
'click #history-tag' : 'loadAndDisplayTags'
},
@@ -253,7 +252,6 @@
//NOTE: this is done before the items, since item views should handle theirs themselves
newRender.append( HistoryPanel.templates.historyPanel( modelJson ) );
newRender.find( '.tooltip' ).tooltip({ placement: 'bottom' });
- this._setUpActionButton( newRender.find( '#history-action-popup' ) );
// render hda views (if any and any shown (show_deleted/hidden)
//TODO: this seems too elaborate
@@ -305,22 +303,6 @@
return historyView.urls;
},
- /** Set up history actions popup menu
- * @param {jQuery} $button jQuery dom object to turn into the 'button' that activates the menu
- * @see make_popupmenu (galaxy-base.js)
- */
- _setUpActionButton : function( $button ){
- var historyPanel = this,
- show_deletedText = ( this.storage.get( 'show_deleted' ) )?( 'Hide deleted' ):( 'Show deleted' ),
- show_hiddenText = ( this.storage.get( 'show_hidden' ) )?( 'Hide hidden' ):( 'Show hidden' ),
- menuActions = {};
- //menuActions[ _l( 'refresh' ) ] = function(){ window.location.reload(); };
- menuActions[ _l( 'collapse all' ) ] = function(){ historyPanel.hideAllHdaBodies(); };
- menuActions[ _l( show_deletedText ) ] = function(){ historyPanel.toggleShowDeleted(); };
- menuActions[ _l( show_hiddenText ) ] = function(){ historyPanel.toggleShowHidden(); };
- make_popupmenu( $button, menuActions );
- },
-
/** Set up/render a view for each HDA to be shown, init with model and listeners.
* HDA views are cached to the map this.hdaViews (using the model.id as key).
* @param {jQuery} $whereTo what dom element to prepend the HDA views to
@@ -441,7 +423,7 @@
/** Collapse all hda bodies and clear expandedHdas in the storage
*/
- hideAllHdaBodies : function(){
+ collapseAllHdaBodies : function(){
_.each( this.hdaViews, function( item ){
item.toggleBodyVisibility( null, false );
});
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-var HDABaseView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urls=this._renderUrls(a.urlTemplates,this.model.toJSON());this.expanded=a.expanded||false;this.model.bind("change",this.render,this)},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{c[f]=_.template(e,a)}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"});this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((!this.model.inReadyState())||(this.model.get("state")===HistoryDatasetAssociation.STATES.ERROR)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("Display data in browser");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_types")}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_apps")}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+state+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.expanded){a.show()}else{a.hide()}return a},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+".</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to unpause")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred running this job")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this,d=this.$el.find(".historyItemBody");a=(a===undefined)?(!d.is(":visible")):(a);if(a){d.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{d.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
+var HDABaseView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urls=this._renderUrls(a.urlTemplates,this.model.toJSON());this.expanded=a.expanded||false;this.model.bind("change",this.render,this)},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{c[f]=_.template(e,a)}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"});this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((!this.model.inReadyState())||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("Display data in browser");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_types")}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_apps")}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+state+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.expanded){a.show()}else{a.hide()}return a},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+".</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to unpause")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred running this job")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this,d=this.$el.find(".historyItemBody");a=(a===undefined)?(!d.is(":visible")):(a);if(a){d.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{d.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/packed/mvc/dataset/hda-edit.js
--- a/static/scripts/packed/mvc/dataset/hda-edit.js
+++ b/static/scripts/packed/mvc/dataset/hda-edit.js
@@ -1,1 +1,1 @@
-var HDAEditView=HDABaseView.extend(LoggableMixin).extend({initialize:function(a){HDABaseView.prototype.initialize.call(this,a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_editButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===HistoryDatasetAssociation.STATES.ERROR)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false;if(c){b.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(a){b.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var a={title:_l("Delete"),href:this.urls["delete"],id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if(this.model.get("deleted")||this.model.get("purged")){a={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(a,{dbkey_unknown_and_editable:true})}return HDABaseView.templates.hdaSummary(a)},_render_errButton:function(){if(this.model.get("state")!==HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var c=this.model.get("dbkey"),a=this.model.get("visualizations"),f=this.urls.visualization,d={},g={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(!(this.model.hasData())||!(a&&a.length)||!(f)){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:f,icon_class:"chart_curve"})});var b=this.visualizationsButton.render().$el;b.addClass("visualize-icon");if(c){g.dbkey=c}function e(h){switch(h){case"trackster":return create_trackster_action_fn(f,g,c);case"scatterplot":return create_scatterplot_action_fn(f,g);default:return function(){window.parent.location=f+"/"+h+"?"+$.param(g)}}}if(a.length===1){b.attr("title",a[0]);b.click(e(a[0]))}else{_.each(a,function(i){var h=i.charAt(0).toUpperCase()+i.slice(1);d[_l(h)]=e(i)});make_popupmenu(b,d)}return b},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||(!this.urls.tags.get)){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||(!this.urls.annotation.get)){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(HDAEditView.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(HDAEditView.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_body_error:function(a){HDABaseView.prototype._render_body_error.call(this,a);var b=a.find("#primary-actions-"+this.model.get("id"));b.prepend(this._render_errButton())},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!jQuery.trim(a.html())){$.ajax({url:this.urls.tags.get,error:function(){alert(_l("Tagging failed"))},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.urls.annotation.set;if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.urls.annotation.get,error:function(){alert(_l("Annotations failed"))},success:function(e){if(e===""){e="<em>"+_l("Describe or add notes to dataset")+"</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDAView("+a+")"}});HDAEditView.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function create_scatterplot_action_fn(a,b){action=function(){var d=$(window.parent.document).find("iframe#galaxy_main"),c=a+"/scatterplot?"+$.param(b);d.attr("src",c);$("div.popmenu-wrapper").remove();return false};return action}function create_trackster_action_fn(a,c,b){return function(){var d={};if(b){d.dbkey=b}$.ajax({url:a+"/list_tracks?f-"+$.param(d),dataType:"html",error:function(){alert(_l("Could not add this dataset to browser")+".")},success:function(e){var f=window.parent;f.show_modal(_l("View Data in a New or Saved Visualization"),"",{Cancel:function(){f.hide_modal()},"View in saved visualization":function(){f.show_modal(_l("Add Data to Saved Visualization"),e,{Cancel:function(){f.hide_modal()},"Add to visualization":function(){$(f.document).find("input[name=id]:checked").each(function(){var g=$(this).val();c.id=g;f.location=a+"/trackster?"+$.param(c)})}})},"View in new visualization":function(){f.location=a+"/trackster?"+$.param(c)}})}});return false}};
\ No newline at end of file
+var HDAEditView=HDABaseView.extend(LoggableMixin).extend({initialize:function(a){HDABaseView.prototype.initialize.call(this,a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_editButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false;if(c){b.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(a){b.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var a={title:_l("Delete"),href:this.urls["delete"],id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if(this.model.get("deleted")||this.model.get("purged")){a={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(a,{dbkey_unknown_and_editable:true})}return HDABaseView.templates.hdaSummary(a)},_render_errButton:function(){if(this.model.get("state")!==HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var c=this.model.get("dbkey"),a=this.model.get("visualizations"),f=this.urls.visualization,d={},g={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(!(this.model.hasData())||!(a&&a.length)||!(f)){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:f,icon_class:"chart_curve"})});var b=this.visualizationsButton.render().$el;b.addClass("visualize-icon");if(c){g.dbkey=c}function e(h){switch(h){case"trackster":return create_trackster_action_fn(f,g,c);case"scatterplot":return create_scatterplot_action_fn(f,g);default:return function(){window.parent.location=f+"/"+h+"?"+$.param(g)}}}if(a.length===1){b.attr("title",a[0]);b.click(e(a[0]))}else{_.each(a,function(i){var h=i.charAt(0).toUpperCase()+i.slice(1);d[_l(h)]=e(i)});make_popupmenu(b,d)}return b},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||(!this.urls.tags.get)){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||(!this.urls.annotation.get)){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(HDAEditView.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(HDAEditView.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_body_error:function(a){HDABaseView.prototype._render_body_error.call(this,a);var b=a.find("#primary-actions-"+this.model.get("id"));b.prepend(this._render_errButton())},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!jQuery.trim(a.html())){$.ajax({url:this.urls.tags.get,error:function(){alert(_l("Tagging failed"))},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.urls.annotation.set;if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.urls.annotation.get,error:function(){alert(_l("Annotations failed"))},success:function(e){if(e===""){e="<em>"+_l("Describe or add notes to dataset")+"</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDAView("+a+")"}});HDAEditView.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function create_scatterplot_action_fn(a,b){action=function(){var d=$(window.parent.document).find("iframe#galaxy_main"),c=a+"/scatterplot?"+$.param(b);d.attr("src",c);$("div.popmenu-wrapper").remove();return false};return action}function create_trackster_action_fn(a,c,b){return function(){var d={};if(b){d.dbkey=b}$.ajax({url:a+"/list_tracks?f-"+$.param(d),dataType:"html",error:function(){alert(_l("Could not add this dataset to browser")+".")},success:function(e){var f=window.parent;f.show_modal(_l("View Data in a New or Saved Visualization"),"",{Cancel:function(){f.hide_modal()},"View in saved visualization":function(){f.show_modal(_l("Add Data to Saved Visualization"),e,{Cancel:function(){f.hide_modal()},"Add to visualization":function(){$(f.document).find("input[name=id]:checked").each(function(){var g=$(this).val();c.id=g;f.location=a+"/trackster?"+$.param(c)})}})},"View in new visualization":function(){f.location=a+"/trackster?"+$.param(c)}})}});return false}};
\ No newline at end of file
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-var HistoryPanel=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-refresh":function(){window.location.reload()},"click #history-tag":"loadAndDisplayTags"},initialize:function(a){this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.hdaViews={};this.urls={}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log("this.storage:",this.storage.get());if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log("(init'd) this.storage:",this.storage.get())},add:function(a){},addAll:function(){this.render()},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});this._setUpActionButton(c.find("#history-action-popup"));if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},_setUpActionButton:function(e){var c=this,d=(this.storage.get("show_deleted"))?("Hide deleted"):("Show deleted"),a=(this.storage.get("show_hidden"))?("Hide hidden"):("Show hidden"),b={};b[_l("collapse all")]=function(){c.hideAllHdaBodies()};b[_l(d)]=function(){c.toggleShowDeleted()};b[_l(a)]=function(){c.toggleShowHidden()};make_popupmenu(e,b)},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render()},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render()},hideAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(c){this.log(this+".loadAndDisplayTags",c);var d=this.$el.find("#history-tag-area"),b=d.find(".tag-elt");this.log("\t tagArea",d," tagElt",b);if(d.is(":hidden")){if(!jQuery.trim(b.html())){var a=this;$.ajax({url:a.urls.tag,error:function(){alert(_l("Tagging failed"))},success:function(e){b.html(e);b.find(".tooltip").tooltip();d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
+var HistoryPanel=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-tag":"loadAndDisplayTags"},initialize:function(a){this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.hdaViews={};this.urls={}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log("this.storage:",this.storage.get());if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log("(init'd) this.storage:",this.storage.get())},add:function(a){},addAll:function(){this.render()},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render()},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render()},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(c){this.log(this+".loadAndDisplayTags",c);var d=this.$el.find("#history-tag-area"),b=d.find(".tag-elt");this.log("\t tagArea",d," tagElt",b);if(d.is(":hidden")){if(!jQuery.trim(b.html())){var a=this;$.ajax({url:a.urls.tag,error:function(){alert(_l("Tagging failed"))},success:function(e){b.html(e);b.find(".tooltip").tooltip();d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/packed/templates/compiled/template-history-historyPanel.js
--- a/static/scripts/packed/templates/compiled/template-history-historyPanel.js
+++ b/static/scripts/packed/templates/compiled/template-history-historyPanel.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(j,C,A,r,J){A=A||j.helpers;var B="",n,m,x=this,f="function",c=A.blockHelperMissing,e=this.escapeExpression;function u(O,N){var L="",M,K;L+='\n <div id="history-name" class="tooltip editable-text"\n title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(2,t,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(2,t,N)})}if(M||M===0){L+=M}L+='">';K=A.name;if(K){M=K.call(O,{hash:{}})}else{M=O.name;M=typeof M===f?M():M}L+=e(M)+"</div>\n ";return L}function t(L,K){return"Click to rename history"}function s(O,N){var L="",M,K;L+='\n <div id="history-name" class="tooltip"\n title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(5,q,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(5,q,N)})}if(M||M===0){L+=M}L+='">';K=A.name;if(K){M=K.call(O,{hash:{}})}else{M=O.name;M=typeof M===f?M():M}L+=e(M)+"</div>\n ";return L}function q(L,K){return"You must be logged in to edit your history name"}function p(O,N){var L="",M,K;L+='\n <a id="history-tag" title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(8,l,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(8,l,N)})}if(M||M===0){L+=M}L+='"\n class="icon-button tags tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n <a id="history-annotate" title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(10,I,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(10,I,N)})}if(M||M===0){L+=M}L+='"\n class="icon-button annotate tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n ';return L}function l(L,K){return"Edit history tags"}function I(L,K){return"Edit history annotation"}function H(L,K){return"Refresh this display"}function G(L,K){return"Click to see more actions for this history"}function F(O,N){var L="",M,K;L+="\n ";K=A.warningmessagesmall;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(17,E,N)})}else{M=O.warningmessagesmall;M=typeof M===f?M():M}if(!A.warningmessagesmall){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(17,E,N)})}if(M||M===0){L+=M}L+="\n ";return L}function E(N,M){var L,K;K=A.local;if(K){L=K.call(N,{hash:{},inverse:x.noop,fn:x.program(18,D,M)})}else{L=N.local;L=typeof L===f?L():L}if(!A.local){L=c.call(N,L,{hash:{},inverse:x.noop,fn:x.program(18,D,M)})}if(L||L===0){return L}else{return""}}function D(L,K){return"You are currently viewing a deleted history!"}function o(O,N){var L="",M,K;L+='\n <div id="history-tag-annotation">\n\n <div id="history-tag-area" style="display: none">\n <strong>';K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(21,k,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(21,k,N)})}if(M||M===0){L+=M}L+=':</strong>\n <div class="tag-elt"></div>\n </div>\n\n <div id="history-annotation-area" style="display: none">\n <strong>';K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(23,i,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(23,i,N)})}if(M||M===0){L+=M}L+=':</strong>\n <div id="history-annotation-container">\n <div id="history-annotation" class="tooltip editable-text"\n title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(25,h,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(25,h,N)})}if(M||M===0){L+=M}L+='">\n ';M=O.annotation;M=A["if"].call(O,M,{hash:{},inverse:x.program(29,d,N),fn:x.program(27,g,N)});if(M||M===0){L+=M}L+="\n </div>\n </div>\n </div>\n </div>\n ";return L}function k(L,K){return"Tags"}function i(L,K){return"Annotation"}function h(L,K){return"Click to edit annotation"}function g(O,N){var L="",M,K;L+="\n ";K=A.annotation;if(K){M=K.call(O,{hash:{}})}else{M=O.annotation;M=typeof M===f?M():M}L+=e(M)+"\n ";return L}function d(O,N){var L="",M,K;L+="\n <em>";K=A.local;if(K){M=K.call(O,{hash:{},inverse:x.noop,fn:x.program(30,z,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:x.noop,fn:x.program(30,z,N)})}if(M||M===0){L+=M}L+="</em>\n ";return L}function z(L,K){return"Describe or add notes to history"}function y(O,N){var L="",M,K;L+='\n <div id="message-container">\n <div class="';K=A.status;if(K){M=K.call(O,{hash:{}})}else{M=O.status;M=typeof M===f?M():M}L+=e(M)+'message">\n ';K=A.message;if(K){M=K.call(O,{hash:{}})}else{M=O.message;M=typeof M===f?M():M}L+=e(M)+"\n </div><br />\n </div>\n ";return L}function w(L,K){return"You are over your disk quota.\n Tool execution is on hold until your disk usage drops below your allocated quota."}function v(L,K){return"Your history is empty. Click 'Get Data' on the left pane to start"}B+='<div id="history-controls">\n <div id="history-title-area" class="historyLinks">\n\n ';B+='\n <div id="history-name-container">\n ';B+="\n ";n=C.user;n=n==null||n===false?n:n.email;n=A["if"].call(C,n,{hash:{},inverse:x.program(4,s,J),fn:x.program(1,u,J)});if(n||n===0){B+=n}B+='\n </div>\n </div>\n\n <div id="history-subtitle-area">\n <div id="history-size" style="float:left;">';m=A.nice_size;if(m){n=m.call(C,{hash:{}})}else{n=C.nice_size;n=typeof n===f?n():n}B+=e(n)+'</div>\n\n <div id="history-secondary-links" style="float: right;">\n ';n=C.user;n=n==null||n===false?n:n.email;n=A["if"].call(C,n,{hash:{},inverse:x.noop,fn:x.program(7,p,J)});if(n||n===0){B+=n}B+='\n <a id="history-refresh" class="tooltip" title="';m=A.local;if(m){n=m.call(C,{hash:{},inverse:x.noop,fn:x.program(12,H,J)})}else{n=C.local;n=typeof n===f?n():n}if(!A.local){n=c.call(C,n,{hash:{},inverse:x.noop,fn:x.program(12,H,J)})}if(n||n===0){B+=n}B+='"\n href="javascript:void(0);">\n <span class="ficon refresh large"></span>\n </a>\n <a id="history-action-popup" class="tooltip" title="';m=A.local;if(m){n=m.call(C,{hash:{},inverse:x.noop,fn:x.program(14,G,J)})}else{n=C.local;n=typeof n===f?n():n}if(!A.local){n=c.call(C,n,{hash:{},inverse:x.noop,fn:x.program(14,G,J)})}if(n||n===0){B+=n}B+='"\n href="javascript:void(0);">\n <span class="ficon cogs large"></span>\n </a>\n </div>\n <div style="clear: both;"></div>\n </div>\n\n ';n=C.deleted;n=A["if"].call(C,n,{hash:{},inverse:x.noop,fn:x.program(16,F,J)});if(n||n===0){B+=n}B+="\n\n ";B+="\n ";B+="\n ";n=C.user;n=n==null||n===false?n:n.email;n=A["if"].call(C,n,{hash:{},inverse:x.noop,fn:x.program(20,o,J)});if(n||n===0){B+=n}B+="\n\n ";n=C.message;n=A["if"].call(C,n,{hash:{},inverse:x.noop,fn:x.program(32,y,J)});if(n||n===0){B+=n}B+='\n\n <div id="quota-message-container" style="display: none">\n <div id="quota-message" class="errormessage">\n ';m=A.local;if(m){n=m.call(C,{hash:{},inverse:x.noop,fn:x.program(34,w,J)})}else{n=C.local;n=typeof n===f?n():n}if(!A.local){n=c.call(C,n,{hash:{},inverse:x.noop,fn:x.program(34,w,J)})}if(n||n===0){B+=n}B+='\n </div>\n </div>\n</div>\n\n<div id="';m=A.id;if(m){n=m.call(C,{hash:{}})}else{n=C.id;n=typeof n===f?n():n}B+=e(n)+'-datasets" class="history-datasets-list"></div>\n\n<div class="infomessagesmall" id="emptyHistoryMessage" style="display: none;">\n ';m=A.local;if(m){n=m.call(C,{hash:{},inverse:x.noop,fn:x.program(36,v,J)})}else{n=C.local;n=typeof n===f?n():n}if(!A.local){n=c.call(C,n,{hash:{},inverse:x.noop,fn:x.program(36,v,J)})}if(n||n===0){B+=n}B+="\n</div>";return B})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(j,z,x,q,H){x=x||j.helpers;var y="",n,m,u=this,e="function",c=x.blockHelperMissing,d=this.escapeExpression;function t(M,L){var J="",K,I;J+='\n <div id="history-name" class="tooltip editable-text"\n title="';I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(2,s,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(2,s,L)})}if(K||K===0){J+=K}J+='">';I=x.name;if(I){K=I.call(M,{hash:{}})}else{K=M.name;K=typeof K===e?K():K}J+=d(K)+"</div>\n ";return J}function s(J,I){return"Click to rename history"}function r(M,L){var J="",K,I;J+='\n <div id="history-name" class="tooltip"\n title="';I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(5,p,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(5,p,L)})}if(K||K===0){J+=K}J+='">';I=x.name;if(I){K=I.call(M,{hash:{}})}else{K=M.name;K=typeof K===e?K():K}J+=d(K)+"</div>\n ";return J}function p(J,I){return"You must be logged in to edit your history name"}function o(M,L){var J="",K,I;J+='\n <a id="history-tag" title="';I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(8,l,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(8,l,L)})}if(K||K===0){J+=K}J+='"\n class="icon-button tags tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n <a id="history-annotate" title="';I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(10,G,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(10,G,L)})}if(K||K===0){J+=K}J+='"\n class="icon-button annotate tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n ';return J}function l(J,I){return"Edit history tags"}function G(J,I){return"Edit history annotation"}function F(M,L){var J="",K,I;J+="\n ";I=x.warningmessagesmall;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(13,E,L)})}else{K=M.warningmessagesmall;K=typeof K===e?K():K}if(!x.warningmessagesmall){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(13,E,L)})}if(K||K===0){J+=K}J+="\n ";return J}function E(L,K){var J,I;I=x.local;if(I){J=I.call(L,{hash:{},inverse:u.noop,fn:u.program(14,D,K)})}else{J=L.local;J=typeof J===e?J():J}if(!x.local){J=c.call(L,J,{hash:{},inverse:u.noop,fn:u.program(14,D,K)})}if(J||J===0){return J}else{return""}}function D(J,I){return"You are currently viewing a deleted history!"}function C(M,L){var J="",K,I;J+='\n <div id="history-tag-annotation">\n\n <div id="history-tag-area" style="display: none">\n <strong>';I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(17,B,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(17,B,L)})}if(K||K===0){J+=K}J+=':</strong>\n <div class="tag-elt"></div>\n </div>\n\n <div id="history-annotation-area" style="display: none">\n <strong>';I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(19,A,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(19,A,L)})}if(K||K===0){J+=K}J+=':</strong>\n <div id="history-annotation-container">\n <div id="history-annotation" class="tooltip editable-text"\n title="';I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(21,k,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(21,k,L)})}if(K||K===0){J+=K}J+='">\n ';K=M.annotation;K=x["if"].call(M,K,{hash:{},inverse:u.program(25,h,L),fn:u.program(23,i,L)});if(K||K===0){J+=K}J+="\n </div>\n </div>\n </div>\n </div>\n ";return J}function B(J,I){return"Tags"}function A(J,I){return"Annotation"}function k(J,I){return"Click to edit annotation"}function i(M,L){var J="",K,I;J+="\n ";I=x.annotation;if(I){K=I.call(M,{hash:{}})}else{K=M.annotation;K=typeof K===e?K():K}J+=d(K)+"\n ";return J}function h(M,L){var J="",K,I;J+="\n <em>";I=x.local;if(I){K=I.call(M,{hash:{},inverse:u.noop,fn:u.program(26,g,L)})}else{K=M.local;K=typeof K===e?K():K}if(!x.local){K=c.call(M,K,{hash:{},inverse:u.noop,fn:u.program(26,g,L)})}if(K||K===0){J+=K}J+="</em>\n ";return J}function g(J,I){return"Describe or add notes to history"}function f(M,L){var J="",K,I;J+='\n <div id="message-container">\n <div class="';I=x.status;if(I){K=I.call(M,{hash:{}})}else{K=M.status;K=typeof K===e?K():K}J+=d(K)+'message">\n ';I=x.message;if(I){K=I.call(M,{hash:{}})}else{K=M.message;K=typeof K===e?K():K}J+=d(K)+"\n </div><br />\n </div>\n ";return J}function w(J,I){return"You are over your disk quota.\n Tool execution is on hold until your disk usage drops below your allocated quota."}function v(J,I){return"Your history is empty. Click 'Get Data' on the left pane to start"}y+='<div id="history-controls">\n <div id="history-title-area" class="historyLinks">\n\n ';y+='\n <div id="history-name-container">\n ';y+="\n ";n=z.user;n=n==null||n===false?n:n.email;n=x["if"].call(z,n,{hash:{},inverse:u.program(4,r,H),fn:u.program(1,t,H)});if(n||n===0){y+=n}y+='\n </div>\n </div>\n\n <div id="history-subtitle-area">\n <div id="history-size" style="float:left;">';m=x.nice_size;if(m){n=m.call(z,{hash:{}})}else{n=z.nice_size;n=typeof n===e?n():n}y+=d(n)+'</div>\n\n <div id="history-secondary-links" style="float: right;">\n ';n=z.user;n=n==null||n===false?n:n.email;n=x["if"].call(z,n,{hash:{},inverse:u.noop,fn:u.program(7,o,H)});if(n||n===0){y+=n}y+='\n </div>\n <div style="clear: both;"></div>\n </div>\n\n ';n=z.deleted;n=x["if"].call(z,n,{hash:{},inverse:u.noop,fn:u.program(12,F,H)});if(n||n===0){y+=n}y+="\n\n ";y+="\n ";y+="\n ";n=z.user;n=n==null||n===false?n:n.email;n=x["if"].call(z,n,{hash:{},inverse:u.noop,fn:u.program(16,C,H)});if(n||n===0){y+=n}y+="\n\n ";n=z.message;n=x["if"].call(z,n,{hash:{},inverse:u.noop,fn:u.program(28,f,H)});if(n||n===0){y+=n}y+='\n\n <div id="quota-message-container" style="display: none">\n <div id="quota-message" class="errormessage">\n ';m=x.local;if(m){n=m.call(z,{hash:{},inverse:u.noop,fn:u.program(30,w,H)})}else{n=z.local;n=typeof n===e?n():n}if(!x.local){n=c.call(z,n,{hash:{},inverse:u.noop,fn:u.program(30,w,H)})}if(n||n===0){y+=n}y+='\n </div>\n </div>\n</div>\n\n<div id="';m=x.id;if(m){n=m.call(z,{hash:{}})}else{n=z.id;n=typeof n===e?n():n}y+=d(n)+'-datasets" class="history-datasets-list"></div>\n\n<div class="infomessagesmall" id="emptyHistoryMessage" style="display: none;">\n ';m=x.local;if(m){n=m.call(z,{hash:{},inverse:u.noop,fn:u.program(32,v,H)})}else{n=z.local;n=typeof n===e?n():n}if(!x.local){n=c.call(z,n,{hash:{},inverse:u.noop,fn:u.program(32,v,H)})}if(n||n===0){y+=n}y+="\n</div>";return y})})();
\ No newline at end of file
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/packed/templates/compiled/template-visualization-scatterplotControlForm.js
--- a/static/scripts/packed/templates/compiled/template-visualization-scatterplotControlForm.js
+++ b/static/scripts/packed/templates/compiled/template-visualization-scatterplotControlForm.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-scatterplotControlForm"]=b(function(g,n,f,m,l){f=f||g.helpers;var j="",d,i,h="function",k=this.escapeExpression,p=this;function e(u,t){var r="",s,q;r+='\n <option value="';q=f.index;if(q){s=q.call(u,{hash:{}})}else{s=u.index;s=typeof s===h?s():s}r+=k(s)+'">';q=f.name;if(q){s=q.call(u,{hash:{}})}else{s=u.name;s=typeof s===h?s():s}r+=k(s)+"</option>\n ";return r}function c(u,t){var r="",s,q;r+='\n <option value="';q=f.index;if(q){s=q.call(u,{hash:{}})}else{s=u.index;s=typeof s===h?s():s}r+=k(s)+'">';q=f.name;if(q){s=q.call(u,{hash:{}})}else{s=u.name;s=typeof s===h?s():s}r+=k(s)+"</option>\n ";return r}function o(u,t){var r="",s,q;r+='\n <option value="';q=f.index;if(q){s=q.call(u,{hash:{}})}else{s=u.index;s=typeof s===h?s():s}r+=k(s)+'">';q=f.name;if(q){s=q.call(u,{hash:{}})}else{s=u.name;s=typeof s===h?s():s}r+=k(s)+"</option>\n ";return r}j+='\n\n<ul class="nav nav-tabs">\n <li class="active">\n <a data-toggle="tab" href="#data-settings">Data Controls</a>\n </li>\n <li><a data-toggle="tab" href="#chart-settings">Plot Controls</a></li>\n <li><a data-toggle="tab" href="#chart-stats">Statistics</a></li>\n</ul>\n\n';j+='\n<div class="tab-content">\n<div id="data-settings" class="tab-pane active">\n\n <p class="help-text">\n Use the following controls to change the data used by the chart.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n </p>\n \n ';j+='\n <div class="column-select">\n <label for="X-select">Data column for X: </label>\n <select name="X" id="X-select">\n ';d=n.numericColumns;d=f.each.call(n,d,{hash:{},inverse:p.noop,fn:p.program(1,e,l)});if(d||d===0){j+=d}j+='\n </select>\n </div>\n <div class="column-select">\n <label for="Y-select">Data column for Y: </label>\n <select name="Y" id="Y-select">\n ';d=n.numericColumns;d=f.each.call(n,d,{hash:{},inverse:p.noop,fn:p.program(3,c,l)});if(d||d===0){j+=d}j+="\n </select>\n </div>\n \n ";j+='\n <div id="include-id">\n <label for="include-id-checkbox">Include a third column as data point IDs?</label>\n <input type="checkbox" name="include-id" id="include-id-checkbox" />\n <p class="help-text-small">\n These will be displayed (along with the x and y values) when you hover over\n a data point.\n </p>\n </div>\n <div class="column-select" style="display: none">\n <label for="ID-select">Data column for IDs: </label>\n <select name="ID" id="ID-select">\n ';d=n.allColumns;d=f.each.call(n,d,{hash:{},inverse:p.noop,fn:p.program(5,o,l)});if(d||d===0){j+=d}j+='\n </select>\n </div>\n \n <input id="render-button" type="button" value="Draw" />\n <input id="save-button" type="button" value="Download Plot as SVG" style="display: none;" />\n <div class="clear"></div>\n</div>\n\n<div id="chart-settings" class="tab-pane">\n</div>\n\n<div id="chart-stats" class="tab-pane">\n</div>\n</div>';j+="\n\n";j+='\n<div id="loading-indicator" style="display: none;">\n <img class="loading-img" src="';i=f.loadingIndicatorImagePath;if(i){d=i.call(n,{hash:{}})}else{d=n.loadingIndicatorImagePath;d=typeof d===h?d():d}j+=k(d)+'" />\n <span class="loading-message">';i=f.message;if(i){d=i.call(n,{hash:{}})}else{d=n.message;d=typeof d===h?d():d}j+=k(d)+"</span>\n</div>";return j})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-scatterplotControlForm"]=b(function(g,n,f,m,l){f=f||g.helpers;var j="",d,i,h="function",k=this.escapeExpression,p=this;function e(u,t){var r="",s,q;r+='\n <option value="';q=f.index;if(q){s=q.call(u,{hash:{}})}else{s=u.index;s=typeof s===h?s():s}r+=k(s)+'">';q=f.name;if(q){s=q.call(u,{hash:{}})}else{s=u.name;s=typeof s===h?s():s}r+=k(s)+"</option>\n ";return r}function c(u,t){var r="",s,q;r+='\n <option value="';q=f.index;if(q){s=q.call(u,{hash:{}})}else{s=u.index;s=typeof s===h?s():s}r+=k(s)+'">';q=f.name;if(q){s=q.call(u,{hash:{}})}else{s=u.name;s=typeof s===h?s():s}r+=k(s)+"</option>\n ";return r}function o(u,t){var r="",s,q;r+='\n <option value="';q=f.index;if(q){s=q.call(u,{hash:{}})}else{s=u.index;s=typeof s===h?s():s}r+=k(s)+'">';q=f.name;if(q){s=q.call(u,{hash:{}})}else{s=u.name;s=typeof s===h?s():s}r+=k(s)+"</option>\n ";return r}j+='\n\n<ul class="nav nav-tabs">\n <li class="active"><a data-toggle="tab" href="#data-settings">Data Controls</a></li>\n <li><a data-toggle="tab" href="#chart-settings">Plot Controls</a></li>\n <li><a data-toggle="tab" href="#chart-stats">Statistics</a></li>\n <li><a data-toggle="tab" href="#chart">Chart</a></li>\n</ul>\n\n';j+='\n<div class="tab-content">\n<div id="data-settings" class="tab-pane active">\n\n <p class="help-text">\n Use the following controls to change the data used by the chart.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n </p>\n \n ';j+='\n <div class="column-select">\n <label for="X-select">Data column for X: </label>\n <select name="X" id="X-select">\n ';d=n.numericColumns;d=f.each.call(n,d,{hash:{},inverse:p.noop,fn:p.program(1,e,l)});if(d||d===0){j+=d}j+='\n </select>\n </div>\n <div class="column-select">\n <label for="Y-select">Data column for Y: </label>\n <select name="Y" id="Y-select">\n ';d=n.numericColumns;d=f.each.call(n,d,{hash:{},inverse:p.noop,fn:p.program(3,c,l)});if(d||d===0){j+=d}j+="\n </select>\n </div>\n \n ";j+='\n <div id="include-id">\n <label for="include-id-checkbox">Include a third column as data point IDs?</label>\n <input type="checkbox" name="include-id" id="include-id-checkbox" />\n <p class="help-text-small">\n These will be displayed (along with the x and y values) when you hover over\n a data point.\n </p>\n </div>\n <div class="column-select" style="display: none">\n <label for="ID-select">Data column for IDs: </label>\n <select name="ID" id="ID-select">\n ';d=n.allColumns;d=f.each.call(n,d,{hash:{},inverse:p.noop,fn:p.program(5,o,l)});if(d||d===0){j+=d}j+='\n </select>\n </div>\n \n <input id="render-button" type="button" value="Draw" />\n <input id="save-button" type="button" value="Download Plot as SVG" style="display: none;" />\n <div class="clear"></div>\n</div>\n\n<div id="chart-settings" class="tab-pane">\n</div>\n\n<div id="chart-stats" class="tab-pane">\n</div>\n</div>';j+="\n\n";j+='\n<div id="loading-indicator" style="display: none;">\n <img class="loading-img" src="';i=f.loadingIndicatorImagePath;if(i){d=i.call(n,{hash:{}})}else{d=n.loadingIndicatorImagePath;d=typeof d===h?d():d}j+=k(d)+'" />\n <span class="loading-message">';i=f.message;if(i){d=i.call(n,{hash:{}})}else{d=n.message;d=typeof d===h?d():d}j+=k(d)+"</span>\n</div>";return j})})();
\ No newline at end of file
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/packed/viz/scatterplot.js
--- a/static/scripts/packed/viz/scatterplot.js
+++ b/static/scripts/packed/viz/scatterplot.js
@@ -1,1 +1,1 @@
-define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.animDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(t,r){var s=d3.select(this);s.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",0).attr("y2",s.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",s.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){this.log(this+".initialize, attributes:",c);this.dataset=null;this.chartConfig=null;this.plot=null;this.loader=null;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null;this.initializeFromAttributes(c);this.initializeChart(c);this.initializeDataLoader(c)},initializeFromAttributes:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ")}this.log("dataset:",this.dataset);if(!c.apiDatasetsURL){throw ("ScatterplotView requires a apiDatasetsURL")}else{this.dataURL=c.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("this.dataURL:",this.dataURL)},initializeChart:function(c){this.chartConfig=c.chartConfig||{};if(this.logger){this.chartConfig.debugging=true}this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config},initializeDataLoader:function(d){var c=this;this.loader=new LazyDataLoader({logger:(this.logger)?(this.logger):(null),url:null,start:d.start||0,total:d.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})}});$(this.loader).bind("error",function(g,e,f){c.log("ERROR:",e,f);alert("ERROR fetching data:\n"+e+"\n"+f);c.hideLoadingIndicator()})},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types,function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:(f+1),name:e})}d.allColumns.push({index:(f+1),name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");this.$dataSettingsPanel.find("#X-select").val(this.chartConfig.xColumn);this.$dataSettingsPanel.find("#Y-select").val(this.chartConfig.yColumn);if(this.chartConfig.idColumn!==undefined){this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked",true).trigger("change");this.$dataSettingsPanel.find("#ID-select").val(this.chartConfig.idColumn)}if(this.chartConfig.xColumn&&this.chartConfig.yColumn){this.renderPlot()}return this},isColumnNumeric:function(c){if((c>=0)&&(c<this.dataset.metadata_column_types.length)){var d=this.dataset.metadata_column_types[c];return(d==="int"||d==="float")}return false},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");function f(){var l=$(this),k=l.slider("value");g.text(k)}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-settings #render-button":"renderPlot","click #chart-settings #render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},renderPlot:function(){var c=this;c.data=null;c.meta=null;_.extend(this.chartConfig,this.getGraphSettings());this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("this.loader, url:",this.loader.url,"total:",this.loader.total);$(this.loader).bind("loaded.new",function(e,d){c.log(c+" loaded.new",d);c.postProcessDataFetchResponse(d);c.log("postprocessed data:",c.data,"meta:",c.meta);c.showLoadingIndicator("Rendering...",function(){c.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");c.plot.render(c.data,c.meta);c.renderStats(c.data,c.meta);c.hideLoadingIndicator()})});$(this.loader).bind("complete",function(d,e){c.log("complete",e);$(c.loader).unbind()});c.showLoadingIndicator("Fetching data...",function(){c.loader.load()})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var c=this;newGraphSettings=this.getGraphSettings();this.log("newGraphSettings:",newGraphSettings);_.extend(this.chartConfig,newGraphSettings);this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);if(c.data&&c.meta){c.showLoadingIndicator("Rendering...",function(){c.plot.render(c.data,c.meta);c.hideLoadingIndicator()})}else{this.renderPlot()}},postProcessDataFetchResponse:function(c){this.postProcessData(c.data);this.postProcessMeta(c.meta)},postProcessData:function(d){var c=this;if(c.data){_.each(d,function(f,e){c.data[e]=c.data[e].concat(f)})}else{c.data=d}},postProcessMeta:function(e){var c=this,d=this.dataset.metadata_column_types;if(c.meta){_.each(e,function(g,f){var k=c.meta[f],i=d[f];c.log(f+" postprocessing meta:",g);k.count+=(g.count)?(g.count):(0);c.log(f,"count:",k.count);if((i==="int")||(i==="float")){k.min=Math.min(g.min,k.min);k.max=Math.max(g.max,k.max);k.sum=g.sum+k.sum;k.mean=(k.count)?(k.sum/k.count):(null);var h=c.data[f].slice().sort(),j=Math.floor(h.length/2);if(h.length%2===0){k.median=((h[j]+h[(j+1)])/2)}else{k.median=h[j]}}})}else{c.meta=e;c.log("initial meta:",c.meta)}},getDataSettings:function(){var d=this.getColumnSelections(),c=[];this.log("columnSelections:",d);c=[d.X.colIndex,d.Y.colIndex];if(this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked")){c.push(d.ID.colIndex)}var e={data_type:"raw_data",columns:"["+c+"]"};this.log("params:",e);return e},getColumnSelections:function(){var c={};this.$dataSettingsPanel.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},getGraphSettings:function(){var e={},f=this.getColumnSelections();e.datapointSize=this.$chartSettingsPanel.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");e.width=this.$chartSettingsPanel.find("#width.numeric-slider-input").find(".slider").slider("value");e.height=this.$chartSettingsPanel.find("#height.numeric-slider-input").find(".slider").slider("value");var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();e.xLabel=(d==="X")?(f.X.colName):(d);e.yLabel=(c==="Y")?(f.Y.colName):(c);e.animDuration=10;if(this.$chartSettingsPanel.find("#animDuration.checkbox-input").is(":checked")){e.animDuration=500}this.log("graphSettings:",e);return e},toString:function(){return"ScatterplotControlForm("+((this.dataset)?(this.dataset.id):(""))+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}});
\ No newline at end of file
+define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.animDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(t,r){var s=d3.select(this);s.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",0).attr("y2",s.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",s.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){this.log(this+".initialize, attributes:",c);this.dataset=null;this.chartConfig=null;this.plot=null;this.loader=null;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null;this.initializeFromAttributes(c);this.initializeChart(c);this.initializeDataLoader(c)},initializeFromAttributes:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ")}this.log("dataset:",this.dataset);if(!c.apiDatasetsURL){throw ("ScatterplotView requires a apiDatasetsURL")}else{this.dataURL=c.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("this.dataURL:",this.dataURL)},initializeChart:function(c){this.chartConfig=c.chartConfig||{};if(this.logger){this.chartConfig.debugging=true}this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config},initializeDataLoader:function(d){var c=this;this.loader=new LazyDataLoader({logger:(this.logger)?(this.logger):(null),url:null,start:d.start||0,total:d.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})}});$(this.loader).bind("error",function(g,e,f){c.log("ERROR:",e,f);alert("ERROR fetching data:\n"+e+"\n"+f);c.hideLoadingIndicator()})},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types,function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:(f+1),name:e})}d.allColumns.push({index:(f+1),name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");this.$dataSettingsPanel.find("#X-select").val(this.chartConfig.xColumn);this.$dataSettingsPanel.find("#Y-select").val(this.chartConfig.yColumn);if(this.chartConfig.idColumn!==undefined){this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked",true).trigger("change");this.$dataSettingsPanel.find("#ID-select").val(this.chartConfig.idColumn)}if(this.chartConfig.xColumn&&this.chartConfig.yColumn){this.renderPlot()}return this},isColumnNumeric:function(c){if((c>=0)&&(c<this.dataset.metadata_column_types.length)){var d=this.dataset.metadata_column_types[c];return(d==="int"||d==="float")}return false},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");function f(){var l=$(this),k=l.slider("value");g.text(k)}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-settings #render-button":"renderPlot","click #chart-settings #render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},renderPlot:function(){var c=this;c.data=null;c.meta=null;_.extend(this.chartConfig,this.getGraphSettings());this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("this.loader, url:",this.loader.url,"total:",this.loader.total);$(this.loader).bind("loaded.new",function(e,d){c.log(c+" loaded.new",d);c.postProcessDataFetchResponse(d);c.log("postprocessed data:",c.data,"meta:",c.meta);c.showLoadingIndicator("Rendering...",function(){c.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");c.plot.render(c.data,c.meta);c.renderStats(c.data,c.meta);c.hideLoadingIndicator()})});$(this.loader).bind("complete",function(d,e){c.log("complete",e);$(c.loader).unbind()});c.showLoadingIndicator("Fetching data...",function(){c.loader.load()})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var c=this;newGraphSettings=this.getGraphSettings();this.log("newGraphSettings:",newGraphSettings);_.extend(this.chartConfig,newGraphSettings);this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);if(c.data&&c.meta){c.showLoadingIndicator("Rendering...",function(){c.plot.render(c.data,c.meta);c.hideLoadingIndicator()})}else{this.renderPlot()}},postProcessDataFetchResponse:function(c){this.postProcessData(c.data);this.postProcessMeta(c.meta)},postProcessData:function(d){var c=this;if(c.data){_.each(d,function(f,e){c.data[e]=c.data[e].concat(f)})}else{c.data=d}},postProcessMeta:function(e){var c=this,d=this.dataset.metadata_column_types;if(c.meta){_.each(e,function(g,f){var k=c.meta[f],i=d[f];c.log(f+" postprocessing meta:",g);k.count+=(g.count)?(g.count):(0);c.log(f,"count:",k.count);if((i==="int")||(i==="float")){k.min=Math.min(g.min,k.min);k.max=Math.max(g.max,k.max);k.sum=g.sum+k.sum;k.mean=(k.count)?(k.sum/k.count):(null);var h=c.data[f].slice().sort(),j=Math.floor(h.length/2);if(h.length%2===0){k.median=((h[j]+h[(j+1)])/2)}else{k.median=h[j]}}})}else{c.meta=e;c.log("initial meta:",c.meta)}},getDataSettings:function(){var d=this.getColumnSelections(),c=[];this.log("columnSelections:",d);c=[d.X.colIndex,d.Y.colIndex];if(this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked")){c.push(d.ID.colIndex)}var e={data_type:"raw_data",columns:"["+c+"]"};this.log("params:",e);return e},getColumnSelections:function(){var c={};this.$dataSettingsPanel.find("div.column-select select").each(function(){var d=$(this),e=parseInt(d.val(),10)-1;c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},getGraphSettings:function(){var e={},f=this.getColumnSelections();e.datapointSize=this.$chartSettingsPanel.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");e.width=this.$chartSettingsPanel.find("#width.numeric-slider-input").find(".slider").slider("value");e.height=this.$chartSettingsPanel.find("#height.numeric-slider-input").find(".slider").slider("value");var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();e.xLabel=(d==="X")?(f.X.colName):(d);e.yLabel=(c==="Y")?(f.Y.colName):(c);e.animDuration=10;if(this.$chartSettingsPanel.find("#animDuration.checkbox-input").is(":checked")){e.animDuration=500}this.log("graphSettings:",e);return e},toString:function(){return"ScatterplotControlForm("+((this.dataset)?(this.dataset.id):(""))+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}});
\ No newline at end of file
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/templates/compiled/template-history-historyPanel.js
--- a/static/scripts/templates/compiled/template-history-historyPanel.js
+++ b/static/scripts/templates/compiled/template-history-historyPanel.js
@@ -73,82 +73,72 @@
function program12(depth0,data) {
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n ";
+ foundHelper = helpers.warningmessagesmall;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(13, program13, data)}); }
+ else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(13, program13, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ return buffer;}
+function program13(depth0,data) {
- return "Refresh this display";}
-
+ var stack1, foundHelper;
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); }
+ if(stack1 || stack1 === 0) { return stack1; }
+ else { return ''; }}
function program14(depth0,data) {
- return "Click to see more actions for this history";}
+ return "You are currently viewing a deleted history!";}
function program16(depth0,data) {
var buffer = "", stack1, foundHelper;
- buffer += "\n ";
- foundHelper = helpers.warningmessagesmall;
+ buffer += "\n <div id=\"history-tag-annotation\">\n\n <div id=\"history-tag-area\" style=\"display: none\">\n <strong>";
+ foundHelper = helpers.local;
if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(17, program17, data)}); }
- else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(17, program17, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(17, program17, data)}); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n ";
- return buffer;}
-function program17(depth0,data) {
-
- var stack1, foundHelper;
+ buffer += ":</strong>\n <div class=\"tag-elt\"></div>\n </div>\n\n <div id=\"history-annotation-area\" style=\"display: none\">\n <strong>";
foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(18, program18, data)}); }
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(19, program19, data)}); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(18, program18, data)}); }
- if(stack1 || stack1 === 0) { return stack1; }
- else { return ''; }}
-function program18(depth0,data) {
-
-
- return "You are currently viewing a deleted history!";}
-
-function program20(depth0,data) {
-
- var buffer = "", stack1, foundHelper;
- buffer += "\n <div id=\"history-tag-annotation\">\n\n <div id=\"history-tag-area\" style=\"display: none\">\n <strong>";
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(19, program19, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += ":</strong>\n <div id=\"history-annotation-container\">\n <div id=\"history-annotation\" class=\"tooltip editable-text\"\n title=\"";
foundHelper = helpers.local;
if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(21, program21, data)}); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(21, program21, data)}); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ":</strong>\n <div class=\"tag-elt\"></div>\n </div>\n\n <div id=\"history-annotation-area\" style=\"display: none\">\n <strong>";
- foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(23, program23, data)}); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(23, program23, data)}); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ":</strong>\n <div id=\"history-annotation-container\">\n <div id=\"history-annotation\" class=\"tooltip editable-text\"\n title=\"";
- foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(25, program25, data)}); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(25, program25, data)}); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\">\n ";
stack1 = depth0.annotation;
- stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(29, program29, data),fn:self.program(27, program27, data)});
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(25, program25, data),fn:self.program(23, program23, data)});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n </div>\n </div>\n </div>\n ";
return buffer;}
-function program21(depth0,data) {
+function program17(depth0,data) {
return "Tags";}
-function program23(depth0,data) {
+function program19(depth0,data) {
return "Annotation";}
-function program25(depth0,data) {
+function program21(depth0,data) {
return "Click to edit annotation";}
-function program27(depth0,data) {
+function program23(depth0,data) {
var buffer = "", stack1, foundHelper;
buffer += "\n ";
@@ -158,23 +148,23 @@
buffer += escapeExpression(stack1) + "\n ";
return buffer;}
-function program29(depth0,data) {
+function program25(depth0,data) {
var buffer = "", stack1, foundHelper;
buffer += "\n <em>";
foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(30, program30, data)}); }
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(26, program26, data)}); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(30, program30, data)}); }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(26, program26, data)}); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "</em>\n ";
return buffer;}
-function program30(depth0,data) {
+function program26(depth0,data) {
return "Describe or add notes to history";}
-function program32(depth0,data) {
+function program28(depth0,data) {
var buffer = "", stack1, foundHelper;
buffer += "\n <div id=\"message-container\">\n <div class=\"";
@@ -188,12 +178,12 @@
buffer += escapeExpression(stack1) + "\n </div><br />\n </div>\n ";
return buffer;}
-function program34(depth0,data) {
+function program30(depth0,data) {
return "You are over your disk quota.\n Tool execution is on hold until your disk usage drops below your allocated quota.";}
-function program36(depth0,data) {
+function program32(depth0,data) {
return "Your history is empty. Click 'Get Data' on the left pane to start";}
@@ -214,38 +204,26 @@
stack1 = stack1 == null || stack1 === false ? stack1 : stack1.email;
stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(7, program7, data)});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n <a id=\"history-refresh\" class=\"tooltip\" title=\"";
- foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(12, program12, data)}); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(12, program12, data)}); }
+ buffer += "\n </div>\n <div style=\"clear: both;\"></div>\n </div>\n\n ";
+ stack1 = depth0.deleted;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(12, program12, data)});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\"\n href=\"javascript:void(0);\">\n <span class=\"ficon refresh large\"></span>\n </a>\n <a id=\"history-action-popup\" class=\"tooltip\" title=\"";
- foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\"\n href=\"javascript:void(0);\">\n <span class=\"ficon cogs large\"></span>\n </a>\n </div>\n <div style=\"clear: both;\"></div>\n </div>\n\n ";
- stack1 = depth0.deleted;
+ buffer += "\n\n ";
+ buffer += "\n ";
+ buffer += "\n ";
+ stack1 = depth0.user;
+ stack1 = stack1 == null || stack1 === false ? stack1 : stack1.email;
stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(16, program16, data)});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n ";
- buffer += "\n ";
- buffer += "\n ";
- stack1 = depth0.user;
- stack1 = stack1 == null || stack1 === false ? stack1 : stack1.email;
- stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(20, program20, data)});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n ";
stack1 = depth0.message;
- stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(32, program32, data)});
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(28, program28, data)});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div id=\"quota-message-container\" style=\"display: none\">\n <div id=\"quota-message\" class=\"errormessage\">\n ";
foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(34, program34, data)}); }
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(30, program30, data)}); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(34, program34, data)}); }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(30, program30, data)}); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n </div>\n</div>\n\n<div id=\"";
foundHelper = helpers.id;
@@ -253,9 +231,9 @@
else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
buffer += escapeExpression(stack1) + "-datasets\" class=\"history-datasets-list\"></div>\n\n<div class=\"infomessagesmall\" id=\"emptyHistoryMessage\" style=\"display: none;\">\n ";
foundHelper = helpers.local;
- if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(36, program36, data)}); }
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(32, program32, data)}); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(36, program36, data)}); }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(32, program32, data)}); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n</div>";
return buffer;});
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/templates/compiled/template-visualization-scatterplotControlForm.js
--- a/static/scripts/templates/compiled/template-visualization-scatterplotControlForm.js
+++ b/static/scripts/templates/compiled/template-visualization-scatterplotControlForm.js
@@ -46,7 +46,7 @@
buffer += escapeExpression(stack1) + "</option>\n ";
return buffer;}
- buffer += "\n\n<ul class=\"nav nav-tabs\">\n <li class=\"active\">\n <a data-toggle=\"tab\" href=\"#data-settings\">Data Controls</a>\n </li>\n <li><a data-toggle=\"tab\" href=\"#chart-settings\">Plot Controls</a></li>\n <li><a data-toggle=\"tab\" href=\"#chart-stats\">Statistics</a></li>\n</ul>\n\n";
+ buffer += "\n\n<ul class=\"nav nav-tabs\">\n <li class=\"active\"><a data-toggle=\"tab\" href=\"#data-settings\">Data Controls</a></li>\n <li><a data-toggle=\"tab\" href=\"#chart-settings\">Plot Controls</a></li>\n <li><a data-toggle=\"tab\" href=\"#chart-stats\">Statistics</a></li>\n <li><a data-toggle=\"tab\" href=\"#chart\">Chart</a></li>\n</ul>\n\n";
buffer += "\n<div class=\"tab-content\">\n<div id=\"data-settings\" class=\"tab-pane active\">\n\n <p class=\"help-text\">\n Use the following controls to change the data used by the chart.\n Use the 'Draw' button to render (or re-render) the chart with the current settings.\n </p>\n \n ";
buffer += "\n <div class=\"column-select\">\n <label for=\"X-select\">Data column for X: </label>\n <select name=\"X\" id=\"X-select\">\n ";
stack1 = depth0.numericColumns;
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 static/scripts/templates/history-templates.html
--- a/static/scripts/templates/history-templates.html
+++ b/static/scripts/templates/history-templates.html
@@ -28,14 +28,6 @@
<a id="history-annotate" title="{{#local}}Edit history annotation{{/local}}"
class="icon-button annotate tooltip" target="galaxy_main" href="javascript:void(0)"></a>
{{/if}}
- <a id="history-refresh" class="tooltip" title="{{#local}}Refresh this display{{/local}}"
- href="javascript:void(0);">
- <span class="ficon refresh large"></span>
- </a>
- <a id="history-action-popup" class="tooltip" title="{{#local}}Click to see more actions for this history{{/local}}"
- href="javascript:void(0);">
- <span class="ficon cogs large"></span>
- </a></div><div style="clear: both;"></div></div>
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 templates/root/alternate_history.mako
--- a/templates/root/alternate_history.mako
+++ b/templates/root/alternate_history.mako
@@ -378,8 +378,9 @@
quotaMeter.update()
}, quotaMeter );
-
- if( !Galaxy.currHistoryPanel ){ Galaxy.currHistoryPanel = historyPanel; }
+ // set it up to be accessible across iframes
+ //TODO:?? mem leak
+ top.Galaxy.currHistoryPanel = historyPanel;
return;
});
@@ -413,7 +414,7 @@
#history-name {
word-wrap: break-word;
font-weight: bold;
- color: black;
+ /*color: gray;*/
}
.editable-text {
border: solid transparent 1px;
@@ -422,7 +423,7 @@
width: 90%;
margin: -2px 0px -3px -4px;
font-weight: bold;
- color: black;
+ /*color: gray;*/
}
#quota-message-container {
diff -r 43e41e09206d2ddc52f4a46114303ef9fd067251 -r 8481560e2c3287a75f85e3a05e59b50b18bcd634 templates/root/index.mako
--- a/templates/root/index.mako
+++ b/templates/root/index.mako
@@ -40,11 +40,17 @@
"${_("Resume Paused Jobs")}": function() {
galaxy_history.location = "${h.url_for( controller='history', action='resume_paused_jobs', current=True)}";
},
- "${_("Show Deleted Datasets")}": function() {
- galaxy_history.location = "${h.url_for( controller='root', action='history', show_deleted=True)}";
+ "${_("Collapse Expanded Datasets")}": function() {
+ Galaxy.currHistoryPanel.collapseAllHdaBodies();
+ //galaxy_history.location = "${h.url_for( controller='root', action='history', show_deleted=True)}";
},
- "${_("Show Hidden Datasets")}": function() {
- galaxy_history.location = "${h.url_for( controller='root', action='history', show_hidden=True)}";
+ "${_("Show/Hide Deleted Datasets")}": function() {
+ Galaxy.currHistoryPanel.toggleShowDeleted();
+ //galaxy_history.location = "${h.url_for( controller='root', action='history', show_deleted=True)}";
+ },
+ "${_("Show/Hide Hidden Datasets")}": function() {
+ Galaxy.currHistoryPanel.toggleShowHidden();
+ //galaxy_history.location = "${h.url_for( controller='root', action='history', show_hidden=True)}";
},
"${_("Unhide Hidden Datasets")}": function() {
if ( confirm( "Really unhide all hidden datasets?" ) ) {
@@ -136,7 +142,14 @@
<div class="unified-panel-header" unselectable="on"><div class="unified-panel-header-inner"><div style="float: right">
- <a id="history-options-button" class='panel-header-button' href="${h.url_for( controller='root', action='history_options' )}" target="galaxy_main"><span class="ficon large cog"></span></a>
+ <a id="history-refresh-button" class='panel-header-button'
+ href="${h.url_for( controller='root', action='history' )}" target="galaxy_history">
+ <span class="ficon large refresh"></span>
+ </a>
+ <a id="history-options-button" class='panel-header-button'
+ href="${h.url_for( controller='root', action='history_options' )}" target="galaxy_main">
+ <span class="ficon large cog"></span>
+ </a></div><div class="panel-header-text">${_('History')}</div></div>
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
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/43e41e09206d/
changeset: 43e41e09206d
user: greg
date: 2012-11-21 16:50:52
summary: More shed_util refactoring.
affected #: 2 files
diff -r 5376431b78bf67afc967eb7dbebde50a02e69518 -r 43e41e09206d2ddc52f4a46114303ef9fd067251 lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -168,16 +168,6 @@
os.close( fd )
shutil.move( filename, os.path.abspath( config_filename ) )
os.chmod( config_filename, 0644 )
-def copy_disk_sample_files_to_dir( trans, repo_files_dir, dest_path ):
- sample_files = []
- for root, dirs, files in os.walk( repo_files_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name.endswith( '.sample' ):
- relative_path = os.path.join( root, name )
- copy_sample_file( trans.app, relative_path, dest_path=dest_path )
- sample_files.append( name )
- return sample_files
def clean_tool_shed_url( tool_shed_url ):
if tool_shed_url.find( ':' ) > 0:
# Eliminate the port, if any, since it will result in an invalid directory name.
@@ -544,17 +534,6 @@
if converter_path and display_path:
break
return converter_path, display_path
-def get_ctx_file_path_from_manifest( filename, repo, changeset_revision ):
- """Get the ctx file path for the latest revision of filename from the repository manifest up to the value of changeset_revision."""
- stripped_filename = strip_path( filename )
- for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
- manifest_changeset_revision = str( repo.changectx( changeset ) )
- manifest_ctx = repo.changectx( changeset )
- for ctx_file in manifest_ctx.files():
- ctx_file_name = strip_path( ctx_file )
- if ctx_file_name == stripped_filename:
- return manifest_ctx, ctx_file
- return None, None
def get_ctx_rev( tool_shed_url, name, owner, changeset_revision ):
url = url_join( tool_shed_url, 'repository/get_ctx_rev?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
response = urllib2.urlopen( url )
@@ -564,38 +543,6 @@
def get_installed_tool_shed_repository( trans, id ):
"""Get a repository on the Galaxy side from the database via id"""
return trans.sa_session.query( trans.model.ToolShedRepository ).get( trans.security.decode_id( id ) )
-def get_list_of_copied_sample_files( repo, ctx, dir ):
- """
- Find all sample files (files in the repository with the special .sample extension) in the reversed repository manifest up to ctx. Copy
- each discovered file to dir and return the list of filenames. If a .sample file was added in a changeset and then deleted in a later
- changeset, it will be returned in the deleted_sample_files list. The caller will set the value of app.config.tool_data_path to dir in
- order to load the tools and generate metadata for them.
- """
- deleted_sample_files = []
- sample_files = []
- for changeset in reversed_upper_bounded_changelog( repo, ctx ):
- changeset_ctx = repo.changectx( changeset )
- for ctx_file in changeset_ctx.files():
- ctx_file_name = strip_path( ctx_file )
- # If we decide in the future that files deleted later in the changelog should not be used, we can use the following if statement.
- # if ctx_file_name.endswith( '.sample' ) and ctx_file_name not in sample_files and ctx_file_name not in deleted_sample_files:
- if ctx_file_name.endswith( '.sample' ) and ctx_file_name not in sample_files:
- fctx = get_file_context_from_ctx( changeset_ctx, ctx_file )
- if fctx in [ 'DELETED' ]:
- # Since the possibly future used if statement above is commented out, the same file that was initially added will be
- # discovered in an earlier changeset in the change log and fall through to the else block below. In other words, if
- # a file named blast2go.loc.sample was added in change set 0 and then deleted in changeset 3, the deleted file in changeset
- # 3 will be handled here, but the later discovered file in changeset 0 will be handled in the else block below. In this
- # way, the file contents will always be found for future tools even though the file was deleted.
- if ctx_file_name not in deleted_sample_files:
- deleted_sample_files.append( ctx_file_name )
- else:
- sample_files.append( ctx_file_name )
- tmp_ctx_file_name = os.path.join( dir, ctx_file_name.replace( '.sample', '' ) )
- fh = open( tmp_ctx_file_name, 'wb' )
- fh.write( fctx.data() )
- fh.close()
- return sample_files, deleted_sample_files
def get_repository_owner( cleaned_repository_url ):
items = cleaned_repository_url.split( 'repos' )
repo_path = items[ 1 ]
@@ -916,31 +863,6 @@
def load_installed_display_applications( app, installed_repository_dict, deactivate=False ):
# Load or deactivate proprietary datatype display applications
app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict, deactivate=deactivate )
-def load_tool_from_tmp_config( trans, repo, ctx, ctx_file, work_dir ):
- tool = None
- message = ''
- tmp_tool_config = get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
- if tmp_tool_config:
- element_tree = util.parse_xml( tmp_tool_config )
- element_tree_root = element_tree.getroot()
- # Look for code files required by the tool config.
- tmp_code_files = []
- for code_elem in element_tree_root.findall( 'code' ):
- code_file_name = code_elem.get( 'file' )
- tmp_code_file_name = copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
- if tmp_code_file_name:
- tmp_code_files.append( tmp_code_file_name )
- tool, valid, message = load_tool_from_config( trans.app, tmp_tool_config )
- for tmp_code_file in tmp_code_files:
- try:
- os.unlink( tmp_code_file )
- except:
- pass
- try:
- os.unlink( tmp_tool_config )
- except:
- pass
- return tool, message
def panel_entry_per_tool( tool_section_dict ):
# Return True if tool_section_dict looks like this.
# {<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>}]}
diff -r 5376431b78bf67afc967eb7dbebde50a02e69518 -r 43e41e09206d2ddc52f4a46114303ef9fd067251 lib/galaxy/util/shed_util_common.py
--- a/lib/galaxy/util/shed_util_common.py
+++ b/lib/galaxy/util/shed_util_common.py
@@ -284,6 +284,28 @@
else:
message = ''
return message
+def copy_disk_sample_files_to_dir( trans, repo_files_dir, dest_path ):
+ sample_files = []
+ for root, dirs, files in os.walk( repo_files_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name.endswith( '.sample' ):
+ relative_path = os.path.join( root, name )
+ copy_sample_file( trans.app, relative_path, dest_path=dest_path )
+ sample_files.append( name )
+ return sample_files
+def copy_file_from_manifest( repo, ctx, filename, dir ):
+ """Copy the latest version of the file named filename from the repository manifest to the directory to which dir refers."""
+ for changeset in reversed_upper_bounded_changelog( repo, ctx ):
+ changeset_ctx = repo.changectx( changeset )
+ fctx = get_file_context_from_ctx( changeset_ctx, filename )
+ if fctx and fctx not in [ 'DELETED' ]:
+ file_path = os.path.join( dir, filename )
+ fh = open( file_path, 'wb' )
+ fh.write( fctx.data() )
+ fh.close()
+ return file_path
+ return None
def copy_sample_file( app, filename, dest_path=None ):
"""Copy xxx.sample to dest_path/xxx.sample and dest_path/xxx. The default value for dest_path is ~/tool-data."""
if dest_path is None:
@@ -603,10 +625,12 @@
is_valid = False
if is_valid:
for repository_elem in root.findall( 'repository' ):
- repository_dependencies_tups.append( ( repository_elem.attrib[ 'toolshed' ],
- repository_elem.attrib[ 'name' ],
- repository_elem.attrib[ 'owner'],
- repository_elem.attrib[ 'changeset_revision' ] ) )
+ repository_dependencies_tup = ( repository_elem.attrib[ 'toolshed' ],
+ repository_elem.attrib[ 'name' ],
+ repository_elem.attrib[ 'owner'],
+ repository_elem.attrib[ 'changeset_revision' ] )
+ if repository_dependencies_tup not in repository_dependencies_tups:
+ repository_dependencies_tups.append( repository_dependencies_tup )
if repository_dependencies_tups:
metadata_dict[ 'repository_dependencies' ] = repository_dependencies_tups
return metadata_dict
@@ -723,6 +747,17 @@
# quiet = True
_ui.setconfig( 'ui', 'quiet', True )
return _ui
+def get_ctx_file_path_from_manifest( filename, repo, changeset_revision ):
+ """Get the ctx file path for the latest revision of filename from the repository manifest up to the value of changeset_revision."""
+ stripped_filename = strip_path( filename )
+ for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
+ manifest_changeset_revision = str( repo.changectx( changeset ) )
+ manifest_ctx = repo.changectx( changeset )
+ for ctx_file in manifest_ctx.files():
+ ctx_file_name = strip_path( ctx_file )
+ if ctx_file_name == stripped_filename:
+ return manifest_ctx, ctx_file
+ return None, None
def get_file_context_from_ctx( ctx, filename ):
# We have to be careful in determining if we found the correct file because multiple files with the same name may be in different directories
# within ctx if the files were moved within the change set. For example, in the following ctx.files() list, the former may have been moved to
@@ -743,6 +778,77 @@
if deleted:
return 'DELETED'
return None
+def get_list_of_copied_sample_files( repo, ctx, dir ):
+ """
+ Find all sample files (files in the repository with the special .sample extension) in the reversed repository manifest up to ctx. Copy
+ each discovered file to dir and return the list of filenames. If a .sample file was added in a changeset and then deleted in a later
+ changeset, it will be returned in the deleted_sample_files list. The caller will set the value of app.config.tool_data_path to dir in
+ order to load the tools and generate metadata for them.
+ """
+ deleted_sample_files = []
+ sample_files = []
+ for changeset in reversed_upper_bounded_changelog( repo, ctx ):
+ changeset_ctx = repo.changectx( changeset )
+ for ctx_file in changeset_ctx.files():
+ ctx_file_name = strip_path( ctx_file )
+ # If we decide in the future that files deleted later in the changelog should not be used, we can use the following if statement.
+ # if ctx_file_name.endswith( '.sample' ) and ctx_file_name not in sample_files and ctx_file_name not in deleted_sample_files:
+ if ctx_file_name.endswith( '.sample' ) and ctx_file_name not in sample_files:
+ fctx = get_file_context_from_ctx( changeset_ctx, ctx_file )
+ if fctx in [ 'DELETED' ]:
+ # Since the possibly future used if statement above is commented out, the same file that was initially added will be
+ # discovered in an earlier changeset in the change log and fall through to the else block below. In other words, if
+ # a file named blast2go.loc.sample was added in change set 0 and then deleted in changeset 3, the deleted file in changeset
+ # 3 will be handled here, but the later discovered file in changeset 0 will be handled in the else block below. In this
+ # way, the file contents will always be found for future tools even though the file was deleted.
+ if ctx_file_name not in deleted_sample_files:
+ deleted_sample_files.append( ctx_file_name )
+ else:
+ sample_files.append( ctx_file_name )
+ tmp_ctx_file_name = os.path.join( dir, ctx_file_name.replace( '.sample', '' ) )
+ fh = open( tmp_ctx_file_name, 'wb' )
+ fh.write( fctx.data() )
+ fh.close()
+ return sample_files, deleted_sample_files
+def get_named_tmpfile_from_ctx( ctx, filename, dir ):
+ filename = strip_path( filename )
+ for ctx_file in ctx.files():
+ ctx_file_name = strip_path( ctx_file )
+ if filename == ctx_file_name:
+ try:
+ # If the file was moved, its destination file contents will be returned here.
+ fctx = ctx[ ctx_file ]
+ except LookupError, e:
+ # Continue looking in case the file was moved.
+ fctx = None
+ continue
+ if fctx:
+ fh = tempfile.NamedTemporaryFile( 'wb', dir=dir )
+ tmp_filename = fh.name
+ fh.close()
+ fh = open( tmp_filename, 'wb' )
+ fh.write( fctx.data() )
+ fh.close()
+ return tmp_filename
+ return None
+def get_parent_id( trans, id, old_id, version, guid, changeset_revisions ):
+ parent_id = None
+ # Compare from most recent to oldest.
+ changeset_revisions.reverse()
+ for changeset_revision in changeset_revisions:
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
+ metadata = repository_metadata.metadata
+ tools_dicts = metadata.get( 'tools', [] )
+ for tool_dict in tools_dicts:
+ if tool_dict[ 'guid' ] == guid:
+ # The tool has not changed between the compared changeset revisions.
+ continue
+ if tool_dict[ 'id' ] == old_id and tool_dict[ 'version' ] != version:
+ # The tool version is different, so we've found the parent.
+ return tool_dict[ 'guid' ]
+ if parent_id is None:
+ # The tool did not change through all of the changeset revisions.
+ return old_id
def get_readme_file_names( repository_name ):
readme_files = [ 'readme', 'read_me', 'install' ]
valid_filenames = [ r for r in readme_files ]
@@ -803,27 +909,20 @@
elif all_metadata_records:
return all_metadata_records[ 0 ]
return None
-def get_named_tmpfile_from_ctx( ctx, filename, dir ):
- filename = strip_path( filename )
- for ctx_file in ctx.files():
- ctx_file_name = strip_path( ctx_file )
- if filename == ctx_file_name:
- try:
- # If the file was moved, its destination file contents will be returned here.
- fctx = ctx[ ctx_file ]
- except LookupError, e:
- # Continue looking in case the file was moved.
- fctx = None
- continue
- if fctx:
- fh = tempfile.NamedTemporaryFile( 'wb', dir=dir )
- tmp_filename = fh.name
- fh.close()
- fh = open( tmp_filename, 'wb' )
- fh.write( fctx.data() )
- fh.close()
- return tmp_filename
- return None
+def get_relative_path_to_repository_file( root, name, relative_install_dir, work_dir, shed_config_dict, resetting_all_metadata_on_repository ):
+ if resetting_all_metadata_on_repository:
+ full_path_to_file = os.path.join( root, name )
+ stripped_path_to_file = full_path_to_file.replace( work_dir, '' )
+ if stripped_path_to_file.startswith( '/' ):
+ stripped_path_to_file = stripped_path_to_file[ 1: ]
+ relative_path_to_file = os.path.join( relative_install_dir, stripped_path_to_file )
+ else:
+ relative_path_to_file = os.path.join( root, name )
+ if relative_install_dir and \
+ shed_config_dict.get( 'tool_path' ) and \
+ relative_path_to_file.startswith( os.path.join( shed_config_dict.get( 'tool_path' ), relative_install_dir ) ):
+ relative_path_to_file = relative_path_to_file[ len( shed_config_dict.get( 'tool_path' ) ) + 1: ]
+ return relative_path_to_file
def get_sample_files_from_disk( repository_files_dir, tool_path = None, relative_install_dir=None, resetting_all_metadata_on_repository=False ):
if resetting_all_metadata_on_repository:
# Keep track of the location where the repository is temporarily cloned so that we can strip it when setting metadata.
@@ -852,38 +951,6 @@
relative_path_to_sample_file = relative_path_to_sample_file[ len( tool_path ) + 1 :]
sample_file_metadata_paths.append( relative_path_to_sample_file )
return sample_file_metadata_paths, sample_file_copy_paths
-def get_parent_id( trans, id, old_id, version, guid, changeset_revisions ):
- parent_id = None
- # Compare from most recent to oldest.
- changeset_revisions.reverse()
- for changeset_revision in changeset_revisions:
- repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
- metadata = repository_metadata.metadata
- tools_dicts = metadata.get( 'tools', [] )
- for tool_dict in tools_dicts:
- if tool_dict[ 'guid' ] == guid:
- # The tool has not changed between the compared changeset revisions.
- continue
- if tool_dict[ 'id' ] == old_id and tool_dict[ 'version' ] != version:
- # The tool version is different, so we've found the parent.
- return tool_dict[ 'guid' ]
- if parent_id is None:
- # The tool did not change through all of the changeset revisions.
- return old_id
-def get_relative_path_to_repository_file( root, name, relative_install_dir, work_dir, shed_config_dict, resetting_all_metadata_on_repository ):
- if resetting_all_metadata_on_repository:
- full_path_to_file = os.path.join( root, name )
- stripped_path_to_file = full_path_to_file.replace( work_dir, '' )
- if stripped_path_to_file.startswith( '/' ):
- stripped_path_to_file = stripped_path_to_file[ 1: ]
- relative_path_to_file = os.path.join( relative_install_dir, stripped_path_to_file )
- else:
- relative_path_to_file = os.path.join( root, name )
- if relative_install_dir and \
- shed_config_dict.get( 'tool_path' ) and \
- relative_path_to_file.startswith( os.path.join( shed_config_dict.get( 'tool_path' ), relative_install_dir ) ):
- relative_path_to_file = relative_path_to_file[ len( shed_config_dict.get( 'tool_path' ) ) + 1: ]
- return relative_path_to_file
def handle_existing_tool_dependencies_that_changed_in_update( app, repository, original_dependency_dict, new_dependency_dict ):
"""
This method is called when a Galaxy admin is getting updates for an installed tool shed repository in order to cover the case where an
@@ -969,6 +1036,31 @@
valid = False
error_message = str( e )
return tool, valid, error_message
+def load_tool_from_tmp_config( trans, repo, ctx, ctx_file, work_dir ):
+ tool = None
+ message = ''
+ tmp_tool_config = get_named_tmpfile_from_ctx( ctx, ctx_file, work_dir )
+ if tmp_tool_config:
+ element_tree = util.parse_xml( tmp_tool_config )
+ element_tree_root = element_tree.getroot()
+ # Look for code files required by the tool config.
+ tmp_code_files = []
+ for code_elem in element_tree_root.findall( 'code' ):
+ code_file_name = code_elem.get( 'file' )
+ tmp_code_file_name = copy_file_from_manifest( repo, ctx, code_file_name, work_dir )
+ if tmp_code_file_name:
+ tmp_code_files.append( tmp_code_file_name )
+ tool, valid, message = load_tool_from_config( trans.app, tmp_tool_config )
+ for tmp_code_file in tmp_code_files:
+ try:
+ os.unlink( tmp_code_file )
+ except:
+ pass
+ try:
+ os.unlink( tmp_tool_config )
+ except:
+ pass
+ return tool, message
def open_repository_files_folder( trans, folder_path ):
try:
files_list = get_repository_files( trans, folder_path )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: eXpress in tool menus: (a) move to position after Cuff* tools and (b) add to main's tool conf.
by Bitbucket 21 Nov '12
by Bitbucket 21 Nov '12
21 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/5376431b78bf/
changeset: 5376431b78bf
user: jgoecks
date: 2012-11-21 15:56:01
summary: eXpress in tool menus: (a) move to position after Cuff* tools and (b) add to main's tool conf.
affected #: 2 files
diff -r 46339150e5e134fb2eb57e4945617841e03a5a3f -r 5376431b78bf67afc967eb7dbebde50a02e69518 tool_conf.xml.main
--- a/tool_conf.xml.main
+++ b/tool_conf.xml.main
@@ -330,8 +330,9 @@
<tool file="ngs_rna/tophat_wrapper.xml" /><tool file="ngs_rna/cufflinks_wrapper.xml" /><tool file="ngs_rna/cuffcompare_wrapper.xml" />
- <tool file="ngs_rna/cuffmerge_wrapper.xml" />
+ <tool file="ngs_rna/cuffmerge_wrapper.xml" /><tool file="ngs_rna/cuffdiff_wrapper.xml" />
+ <tool file="ngs_rna/express_wrapper.xml" /><label text="Filtering" id="filtering" /><tool file="ngs_rna/filter_transcripts_via_tracking.xml" /></section>
diff -r 46339150e5e134fb2eb57e4945617841e03a5a3f -r 5376431b78bf67afc967eb7dbebde50a02e69518 tool_conf.xml.sample
--- a/tool_conf.xml.sample
+++ b/tool_conf.xml.sample
@@ -331,9 +331,9 @@
<tool file="ngs_rna/tophat_color_wrapper.xml" /><tool file="ngs_rna/cufflinks_wrapper.xml" /><tool file="ngs_rna/cuffcompare_wrapper.xml" />
+ <tool file="ngs_rna/cuffmerge_wrapper.xml" />
+ <tool file="ngs_rna/cuffdiff_wrapper.xml" /><tool file="ngs_rna/express_wrapper.xml" />
- <tool file="ngs_rna/cuffmerge_wrapper.xml" />
- <tool file="ngs_rna/cuffdiff_wrapper.xml" /><!-- Trinity is very memory-intensive and should only be enabled/run
on instances with sufficient resources.
<label text="De novo Assembly" id="de_novo_assembly "/>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: scatterplot: fix column selection broken in 7002f41
by Bitbucket 20 Nov '12
by Bitbucket 20 Nov '12
20 Nov '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/46339150e5e1/
changeset: 46339150e5e1
user: carlfeberhard
date: 2012-11-20 21:42:01
summary: scatterplot: fix column selection broken in 7002f41
affected #: 1 file
diff -r 7002f41bcaa3b1a5f5023e3c2d523488812873df -r 46339150e5e134fb2eb57e4945617841e03a5a3f static/scripts/viz/scatterplot.js
--- a/static/scripts/viz/scatterplot.js
+++ b/static/scripts/viz/scatterplot.js
@@ -939,7 +939,7 @@
var selections = {};
this.$dataSettingsPanel.find( 'div.column-select select' ).each( function(){
var $this = $( this ),
- val = $this.val();
+ val = parseInt( $this.val(), 10 ) - 1;
selections[ $this.attr( 'name' ) ] = {
colIndex : val,
colName : $this.children( '[value="' + val + '"]' ).text()
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
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/0941c74d1d05/
changeset: 0941c74d1d05
user: carlfeberhard
date: 2012-11-20 21:30:22
summary: scatterplot: add ability to auto-render based on query string
affected #: 4 files
diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -786,6 +786,9 @@
@web.expose
def scatterplot( self, trans, dataset_id, **kwargs ):
+ """
+ Returns a page that controls and renders a scatteplot graph.
+ """
# Get HDA.
hda = self.get_dataset( trans, dataset_id, check_ownership=False, check_accessible=True )
hda_dict = hda.get_api_value()
@@ -793,6 +796,7 @@
if( hda_dict[ 'metadata_column_names' ] == None
and hasattr( hda.datatype, 'column_names' ) ):
hda_dict[ 'metadata_column_names' ] = hda.datatype.column_names
+
history_id = trans.security.encode_id( hda.history.id )
#TODO: add column data
@@ -845,4 +849,3 @@
name = fields[4]
rows.append( [location, name] )
return { 'data': rows }
-
diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 static/scripts/templates/visualization-templates.html
--- a/static/scripts/templates/visualization-templates.html
+++ b/static/scripts/templates/visualization-templates.html
@@ -2,11 +2,10 @@
{{! main controls }}
<ul class="nav nav-tabs">
- <li class="active">
- <a data-toggle="tab" href="#data-settings">Data Controls</a>
- </li>
+ <li class="active"><a data-toggle="tab" href="#data-settings">Data Controls</a></li><li><a data-toggle="tab" href="#chart-settings">Plot Controls</a></li><li><a data-toggle="tab" href="#chart-stats">Statistics</a></li>
+ <li><a data-toggle="tab" href="#chart">Chart</a></li></ul>
{{! data settings }}
diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 static/scripts/viz/scatterplot.js
--- a/static/scripts/viz/scatterplot.js
+++ b/static/scripts/viz/scatterplot.js
@@ -412,14 +412,14 @@
}
// titles
- newDatapoints.attr( 'title', function( d, i ){
- return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ];
- });
+ //newDatapoints.attr( 'title', function( d, i ){
+ // return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ];
+ //});
// events
newDatapoints
//TODO: remove magic numbers
- .on( 'mouseover', function(){
+ .on( 'mouseover', function( d, i ){
var datapoint = d3.select( this );
datapoint
.style( 'fill', 'red' )
@@ -438,12 +438,24 @@
.attr( 'x1', datapoint.attr( 'cx' ) ).attr( 'y1', datapoint.attr( 'cy' ) )
.attr( 'x2', datapoint.attr( 'cx' ) ).attr( 'y2', plot.config.height )
.classed( 'hoverline', true );
+
+ //var datapointWindowPos = $( this ).position();
+ var datapointWindowPos = $( this ).offset();
+ window.dot = this;
+ console.debug( 'datapointWindowPos:', datapointWindowPos );
+ console.debug( 'datapoint r:', datapoint.attr( 'r' ) );
+ //this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left + datapoint.attr( 'r' ),
+ this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left,
+ newXCol[ i ], newYCol[ i ], ( ids )?( ids[ i ] ):( undefined ) );
+ $( 'body' ).append( this.popup );
})
.on( 'mouseout', function(){
d3.select( this )
.style( 'fill', 'black' )
.style( 'fill-opacity', 0.2 );
-
+ if( this.popup ){
+ this.popup.remove();
+ }
d3.selectAll( '.hoverline' ).remove();
});
@@ -499,7 +511,7 @@
loadingIndicatorImage : 'loading_large_white_bg.gif',
initialize : function( attributes ){
- if( this.logger ){ window.form = this; }
+ console.debug( this + '.initialize, attributes:', attributes );
this.dataset = null;
this.chartConfig = null;
@@ -517,7 +529,7 @@
},
initializeFromAttributes : function( attributes ){
- // ensure certain vars we need are passed in attributes
+ // required settings: ensure certain vars we need are passed in attributes
if( !attributes || !attributes.dataset ){
throw( "ScatterplotView requires a dataset" );
} else {
@@ -586,9 +598,9 @@
loadingIndicatorImagePath : galaxy_paths.get( 'image_path' ) + '/' + this.loadingIndicatorImage
};
+ //TODO: isNumericColumn
// gather column indeces (from metadata_column_types) and names (from metadata_columnnames)
_.each( this.dataset.metadata_column_types, function( type, index ){
- //TODO: using 0-based indeces
// label with the name if available (fall back on 'column <index>')
var name = 'column ' + ( index + 1 );
if( view.dataset.metadata_column_names ){
@@ -597,23 +609,46 @@
// filter numeric columns to their own list
if( type === 'int' || type === 'float' ){
- formData.numericColumns.push({ index: index, name: name });
+ formData.numericColumns.push({ index: ( index + 1 ), name: name });
}
- formData.allColumns.push({ index: index, name: name });
+ formData.allColumns.push({ index: ( index + 1 ), name: name });
});
-
//TODO: other vals: max_vals, start_val, pagination (plot-settings)
// render template and set up panels, store refs
this.$el.append( ScatterplotControlForm.templates.form( formData ) );
+
this.$dataSettingsPanel = this.$el.find( '.tab-pane#data-settings' );
this.$chartSettingsPanel = this._render_chartSettings();
this.$statsPanel = this.$el.find( '.tab-pane#chart-stats' );
-
+
+ // preset to column selectors if they were passed in the config
+ this.$dataSettingsPanel.find( '#X-select' ).val( this.chartConfig.xColumn );
+ this.$dataSettingsPanel.find( '#Y-select' ).val( this.chartConfig.yColumn );
+ if( this.chartConfig.idColumn !== undefined ){
+ this.$dataSettingsPanel.find( '#include-id-checkbox' )
+ .attr( 'checked', true ).trigger( 'change' );
+ this.$dataSettingsPanel.find( '#ID-select' ).val( this.chartConfig.idColumn );
+ }
+
//this.$el.find( 'ul.nav' ).find( 'a[href="#chart-settings"]' ).tab( 'show' );
+
+ //TODO:?? add autoRender=1 to query maybe?
+ if( this.chartConfig.xColumn && this.chartConfig.yColumn ){
+ this.renderPlot();
+ }
return this;
},
-
+
+ //TODO: seems like a function of dataset or metadata
+ isColumnNumeric : function( index ){
+ if( ( index >= 0 ) && ( index < this.dataset.metadata_column_types.length ) ){
+ var columnType = this.dataset.metadata_column_types[ index ];
+ return ( columnType === 'int' || columnType === 'float' );
+ }
+ return false;
+ },
+
_render_chartSettings : function(){
// chart settings panel
var chartControl = this,
@@ -658,7 +693,7 @@
// ------------------------------------------------------------------------- EVENTS
events : {
- 'click #include-id-checkbox' : 'toggleThirdColumnSelector',
+ 'change #include-id-checkbox' : 'toggleThirdColumnSelector',
'click #data-settings #render-button' : 'renderPlot',
'click #chart-settings #render-button' : 'changeChartSettings'
},
@@ -948,7 +983,7 @@
},
toString : function(){
- return 'ScatterplotControlForm(' + this.dataset.id + ')';
+ return 'ScatterplotControlForm(' + (( this.dataset )?( this.dataset.id ):( '' )) + ')';
}
});
diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 templates/visualization/scatterplot.mako
--- a/templates/visualization/scatterplot.mako
+++ b/templates/visualization/scatterplot.mako
@@ -193,6 +193,15 @@
fill-opacity: 0.2;
}
+/* -------------------------------------------- info box */
+.zero-dimensions {
+ width: 0;
+ height: 0;
+ border-top: 8px solid transparent;
+ border-bottom: 8px solid transparent;
+ border-right: 8px solid grey;
+}
+
</style></%def>
@@ -207,21 +216,88 @@
require([ "viz/scatterplot" ], function( scatterplot ){
var hda = ${h.to_json_string( hda )},
- historyID = '${historyID}';
-
- settingsForm = new scatterplot.ScatterplotControlForm({
- dataset : hda,
- el : $( '#chart-settings-form' ),
- apiDatasetsURL : "${h.url_for( controller='/api/datasets' )}",
+ historyID = '${historyID}',
+ querySettings = ${h.to_json_string( kwargs )},
+ chartConfig = _.extend( querySettings, {
+ containerSelector : '#chart-holder',
+ //TODO: move to ScatterplotControlForm.initialize
+ marginTop : ( querySettings.marginTop > 20 )?( querySettings.marginTop ):( 20 ),
- chartConfig : {
- containerSelector : '#chart-holder',
- marginTop : 20,
- }
+ xColumn : querySettings.xColumn,
+ yColumn : querySettings.yColumn,
+ idColumn : querySettings.idColumn
+ });
+ console.debug( querySettings );
+
+ var settingsForm = new scatterplot.ScatterplotControlForm({
+ dataset : hda,
+ apiDatasetsURL : "${h.url_for( controller='/api/datasets' )}",
+ el : $( '#chart-settings-form' ),
+ chartConfig : chartConfig
}).render();
});
+
+function make_abs_box( top, left, x, y, id ){
+ console.debug( top, left, x, y, id );
+ var ARROW_SIZE = 8,
+ ARROW_COLOR = 'grey',
+ DIST_TO_POINT = 4,
+ halfArrowSize = ARROW_SIZE / 2;
+
+ var boxContainer = $( '<div />' )
+ .attr( 'id', 'abs-box-container' )
+ // top left arrow
+ .css({
+ 'position' : 'absolute',
+ 'top' : top - halfArrowSize,
+ 'left' : left + ARROW_SIZE + DIST_TO_POINT,
+ 'background-color': 'transparent',
+ });
+ window.boxContainer = boxContainer;
+
+ var arrowLeft = $( '<div />' )
+ .attr( 'id', 'abs-box-arrow' )
+ .addClass( 'zero-dimensions' )
+ .css({
+ 'border-top' : ARROW_SIZE + 'px solid transparent',
+ 'border-bottom' : ARROW_SIZE + 'px solid transparent',
+ 'border-right' : ARROW_SIZE + 'px solid ' + ARROW_COLOR,
+ });
+ boxContainer.append( arrowLeft );
+ window.arrow = arrowLeft;
+
+ console.debug( 'arrow height:', arrowLeft.height() );
+ var boxInfo = $( '<div />' )
+ .attr( 'id', 'abs-box' )
+ .css({
+ 'position' : 'relative',
+ //TODO: 4 here is the border-radius
+ 'top' : -( 2 * ARROW_SIZE + 6 ),
+ 'left' : ARROW_SIZE,
+ 'border' : '2px solid grey',
+ 'border-radius' : '4px',
+ 'padding' : '4px',
+ 'background-color': 'white',
+ 'box-shadow' : '4px 4px 4px black'
+ });
+
+ // remove
+ if( id ){
+ $( '<div />' ).addClass( 'abs-box-id' ).css( 'font-weight', 'bold' ).text( id ).appendTo( boxInfo );
+ }
+ $( '<div />' ).addClass( 'abs-box-x' ).text( x ).appendTo( boxInfo );
+ $( '<div />' ).addClass( 'abs-box-y' ).text( y ).appendTo( boxInfo );
+ boxContainer.append( boxInfo );
+ boxContainer.append( '<div style="clear:both"></div>' );
+ window.boxInfo = boxContainer;
+
+ //console.debug( boxContainer );
+ return boxContainer;
+}
+
+
</script></%def>
https://bitbucket.org/galaxy/galaxy-central/changeset/f25f13784d20/
changeset: f25f13784d20
user: carlfeberhard
date: 2012-11-20 21:32:14
summary: scatterplot: clean up
affected #: 2 files
diff -r 0941c74d1d058ad6183347417e45fd5fd1528501 -r f25f13784d20b7f8697ff499b73339ac7d2b4acc static/scripts/viz/scatterplot.js
--- a/static/scripts/viz/scatterplot.js
+++ b/static/scripts/viz/scatterplot.js
@@ -412,9 +412,9 @@
}
// titles
- //newDatapoints.attr( 'title', function( d, i ){
- // return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ];
- //});
+ newDatapoints.attr( 'title', function( d, i ){
+ return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ];
+ });
// events
newDatapoints
@@ -440,23 +440,21 @@
.classed( 'hoverline', true );
//var datapointWindowPos = $( this ).position();
- var datapointWindowPos = $( this ).offset();
- window.dot = this;
- console.debug( 'datapointWindowPos:', datapointWindowPos );
- console.debug( 'datapoint r:', datapoint.attr( 'r' ) );
- //this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left + datapoint.attr( 'r' ),
- this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left,
- newXCol[ i ], newYCol[ i ], ( ids )?( ids[ i ] ):( undefined ) );
- $( 'body' ).append( this.popup );
+ //var datapointWindowPos = $( this ).offset();
+ //window.dot = this;
+ ////this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left + datapoint.attr( 'r' ),
+ //this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left,
+ // newXCol[ i ], newYCol[ i ], ( ids )?( ids[ i ] ):( undefined ) );
+ //$( 'body' ).append( this.popup );
})
.on( 'mouseout', function(){
d3.select( this )
.style( 'fill', 'black' )
.style( 'fill-opacity', 0.2 );
- if( this.popup ){
- this.popup.remove();
- }
d3.selectAll( '.hoverline' ).remove();
+ //if( this.popup ){
+ // this.popup.remove();
+ //}
});
return newDatapoints;
@@ -511,7 +509,7 @@
loadingIndicatorImage : 'loading_large_white_bg.gif',
initialize : function( attributes ){
- console.debug( this + '.initialize, attributes:', attributes );
+ this.log( this + '.initialize, attributes:', attributes );
this.dataset = null;
this.chartConfig = null;
diff -r 0941c74d1d058ad6183347417e45fd5fd1528501 -r f25f13784d20b7f8697ff499b73339ac7d2b4acc templates/visualization/scatterplot.mako
--- a/templates/visualization/scatterplot.mako
+++ b/templates/visualization/scatterplot.mako
@@ -227,7 +227,7 @@
yColumn : querySettings.yColumn,
idColumn : querySettings.idColumn
});
- console.debug( querySettings );
+ //console.debug( querySettings );
var settingsForm = new scatterplot.ScatterplotControlForm({
dataset : hda,
https://bitbucket.org/galaxy/galaxy-central/changeset/7002f41bcaa3/
changeset: 7002f41bcaa3
user: carlfeberhard
date: 2012-11-20 21:32:40
summary: pack scripts
affected #: 1 file
diff -r f25f13784d20b7f8697ff499b73339ac7d2b4acc -r 7002f41bcaa3b1a5f5023e3c2d523488812873df static/scripts/packed/viz/scatterplot.js
--- a/static/scripts/packed/viz/scatterplot.js
+++ b/static/scripts/packed/viz/scatterplot.js
@@ -1,1 +1,1 @@
-define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.animDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(){var r=d3.select(this);r.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",0).attr("y2",r.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",r.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){if(this.logger){window.form=this}this.dataset=null;this.chartConfig=null;this.plot=null;this.loader=null;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null;this.initializeFromAttributes(c);this.initializeChart(c);this.initializeDataLoader(c)},initializeFromAttributes:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ")}this.log("dataset:",this.dataset);if(!c.apiDatasetsURL){throw ("ScatterplotView requires a apiDatasetsURL")}else{this.dataURL=c.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("this.dataURL:",this.dataURL)},initializeChart:function(c){this.chartConfig=c.chartConfig||{};if(this.logger){this.chartConfig.debugging=true}this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config},initializeDataLoader:function(d){var c=this;this.loader=new LazyDataLoader({logger:(this.logger)?(this.logger):(null),url:null,start:d.start||0,total:d.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})}});$(this.loader).bind("error",function(g,e,f){c.log("ERROR:",e,f);alert("ERROR fetching data:\n"+e+"\n"+f);c.hideLoadingIndicator()})},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types,function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:f,name:e})}d.allColumns.push({index:f,name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");return this},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");function f(){var l=$(this),k=l.slider("value");g.text(k)}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"click #include-id-checkbox":"toggleThirdColumnSelector","click #data-settings #render-button":"renderPlot","click #chart-settings #render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},renderPlot:function(){var c=this;c.data=null;c.meta=null;_.extend(this.chartConfig,this.getGraphSettings());this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("this.loader, url:",this.loader.url,"total:",this.loader.total);$(this.loader).bind("loaded.new",function(e,d){c.log(c+" loaded.new",d);c.postProcessDataFetchResponse(d);c.log("postprocessed data:",c.data,"meta:",c.meta);c.showLoadingIndicator("Rendering...",function(){c.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");c.plot.render(c.data,c.meta);c.renderStats(c.data,c.meta);c.hideLoadingIndicator()})});$(this.loader).bind("complete",function(d,e){c.log("complete",e);$(c.loader).unbind()});c.showLoadingIndicator("Fetching data...",function(){c.loader.load()})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var c=this;newGraphSettings=this.getGraphSettings();this.log("newGraphSettings:",newGraphSettings);_.extend(this.chartConfig,newGraphSettings);this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);if(c.data&&c.meta){c.showLoadingIndicator("Rendering...",function(){c.plot.render(c.data,c.meta);c.hideLoadingIndicator()})}else{this.renderPlot()}},postProcessDataFetchResponse:function(c){this.postProcessData(c.data);this.postProcessMeta(c.meta)},postProcessData:function(d){var c=this;if(c.data){_.each(d,function(f,e){c.data[e]=c.data[e].concat(f)})}else{c.data=d}},postProcessMeta:function(e){var c=this,d=this.dataset.metadata_column_types;if(c.meta){_.each(e,function(g,f){var k=c.meta[f],i=d[f];c.log(f+" postprocessing meta:",g);k.count+=(g.count)?(g.count):(0);c.log(f,"count:",k.count);if((i==="int")||(i==="float")){k.min=Math.min(g.min,k.min);k.max=Math.max(g.max,k.max);k.sum=g.sum+k.sum;k.mean=(k.count)?(k.sum/k.count):(null);var h=c.data[f].slice().sort(),j=Math.floor(h.length/2);if(h.length%2===0){k.median=((h[j]+h[(j+1)])/2)}else{k.median=h[j]}}})}else{c.meta=e;c.log("initial meta:",c.meta)}},getDataSettings:function(){var d=this.getColumnSelections(),c=[];this.log("columnSelections:",d);c=[d.X.colIndex,d.Y.colIndex];if(this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked")){c.push(d.ID.colIndex)}var e={data_type:"raw_data",columns:"["+c+"]"};this.log("params:",e);return e},getColumnSelections:function(){var c={};this.$dataSettingsPanel.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},getGraphSettings:function(){var e={},f=this.getColumnSelections();e.datapointSize=this.$chartSettingsPanel.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");e.width=this.$chartSettingsPanel.find("#width.numeric-slider-input").find(".slider").slider("value");e.height=this.$chartSettingsPanel.find("#height.numeric-slider-input").find(".slider").slider("value");var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();e.xLabel=(d==="X")?(f.X.colName):(d);e.yLabel=(c==="Y")?(f.Y.colName):(c);e.animDuration=10;if(this.$chartSettingsPanel.find("#animDuration.checkbox-input").is(":checked")){e.animDuration=500}this.log("graphSettings:",e);return e},toString:function(){return"ScatterplotControlForm("+this.dataset.id+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}});
\ No newline at end of file
+define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.animDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(t,r){var s=d3.select(this);s.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",0).attr("y2",s.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",s.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){this.log(this+".initialize, attributes:",c);this.dataset=null;this.chartConfig=null;this.plot=null;this.loader=null;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null;this.initializeFromAttributes(c);this.initializeChart(c);this.initializeDataLoader(c)},initializeFromAttributes:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ")}this.log("dataset:",this.dataset);if(!c.apiDatasetsURL){throw ("ScatterplotView requires a apiDatasetsURL")}else{this.dataURL=c.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("this.dataURL:",this.dataURL)},initializeChart:function(c){this.chartConfig=c.chartConfig||{};if(this.logger){this.chartConfig.debugging=true}this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config},initializeDataLoader:function(d){var c=this;this.loader=new LazyDataLoader({logger:(this.logger)?(this.logger):(null),url:null,start:d.start||0,total:d.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})}});$(this.loader).bind("error",function(g,e,f){c.log("ERROR:",e,f);alert("ERROR fetching data:\n"+e+"\n"+f);c.hideLoadingIndicator()})},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types,function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:(f+1),name:e})}d.allColumns.push({index:(f+1),name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");this.$dataSettingsPanel.find("#X-select").val(this.chartConfig.xColumn);this.$dataSettingsPanel.find("#Y-select").val(this.chartConfig.yColumn);if(this.chartConfig.idColumn!==undefined){this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked",true).trigger("change");this.$dataSettingsPanel.find("#ID-select").val(this.chartConfig.idColumn)}if(this.chartConfig.xColumn&&this.chartConfig.yColumn){this.renderPlot()}return this},isColumnNumeric:function(c){if((c>=0)&&(c<this.dataset.metadata_column_types.length)){var d=this.dataset.metadata_column_types[c];return(d==="int"||d==="float")}return false},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");function f(){var l=$(this),k=l.slider("value");g.text(k)}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-settings #render-button":"renderPlot","click #chart-settings #render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},renderPlot:function(){var c=this;c.data=null;c.meta=null;_.extend(this.chartConfig,this.getGraphSettings());this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("this.loader, url:",this.loader.url,"total:",this.loader.total);$(this.loader).bind("loaded.new",function(e,d){c.log(c+" loaded.new",d);c.postProcessDataFetchResponse(d);c.log("postprocessed data:",c.data,"meta:",c.meta);c.showLoadingIndicator("Rendering...",function(){c.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");c.plot.render(c.data,c.meta);c.renderStats(c.data,c.meta);c.hideLoadingIndicator()})});$(this.loader).bind("complete",function(d,e){c.log("complete",e);$(c.loader).unbind()});c.showLoadingIndicator("Fetching data...",function(){c.loader.load()})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var c=this;newGraphSettings=this.getGraphSettings();this.log("newGraphSettings:",newGraphSettings);_.extend(this.chartConfig,newGraphSettings);this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);if(c.data&&c.meta){c.showLoadingIndicator("Rendering...",function(){c.plot.render(c.data,c.meta);c.hideLoadingIndicator()})}else{this.renderPlot()}},postProcessDataFetchResponse:function(c){this.postProcessData(c.data);this.postProcessMeta(c.meta)},postProcessData:function(d){var c=this;if(c.data){_.each(d,function(f,e){c.data[e]=c.data[e].concat(f)})}else{c.data=d}},postProcessMeta:function(e){var c=this,d=this.dataset.metadata_column_types;if(c.meta){_.each(e,function(g,f){var k=c.meta[f],i=d[f];c.log(f+" postprocessing meta:",g);k.count+=(g.count)?(g.count):(0);c.log(f,"count:",k.count);if((i==="int")||(i==="float")){k.min=Math.min(g.min,k.min);k.max=Math.max(g.max,k.max);k.sum=g.sum+k.sum;k.mean=(k.count)?(k.sum/k.count):(null);var h=c.data[f].slice().sort(),j=Math.floor(h.length/2);if(h.length%2===0){k.median=((h[j]+h[(j+1)])/2)}else{k.median=h[j]}}})}else{c.meta=e;c.log("initial meta:",c.meta)}},getDataSettings:function(){var d=this.getColumnSelections(),c=[];this.log("columnSelections:",d);c=[d.X.colIndex,d.Y.colIndex];if(this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked")){c.push(d.ID.colIndex)}var e={data_type:"raw_data",columns:"["+c+"]"};this.log("params:",e);return e},getColumnSelections:function(){var c={};this.$dataSettingsPanel.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},getGraphSettings:function(){var e={},f=this.getColumnSelections();e.datapointSize=this.$chartSettingsPanel.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");e.width=this.$chartSettingsPanel.find("#width.numeric-slider-input").find(".slider").slider("value");e.height=this.$chartSettingsPanel.find("#height.numeric-slider-input").find(".slider").slider("value");var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();e.xLabel=(d==="X")?(f.X.colName):(d);e.yLabel=(c==="Y")?(f.Y.colName):(c);e.animDuration=10;if(this.$chartSettingsPanel.find("#animDuration.checkbox-input").is(":checked")){e.animDuration=500}this.log("graphSettings:",e);return e},toString:function(){return"ScatterplotControlForm("+((this.dataset)?(this.dataset.id):(""))+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0