galaxy-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: carlfeberhard: Revert return of status 201 in 578b918 as paste can't deal with that
by commits-noreply@bitbucket.org 10 Feb '14
by commits-noreply@bitbucket.org 10 Feb '14
10 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e18b36121df0/
Changeset: e18b36121df0
User: carlfeberhard
Date: 2014-02-10 23:45:32
Summary: Revert return of status 201 in 578b918 as paste can't deal with that
Affected #: 2 files
diff -r ed003906850cce820f74afa3b2ae227ae03f38aa -r e18b36121df0bcb9a30906716e5b0c8a747bd138 lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -191,7 +191,6 @@
archive_source = payload[ "archive_source" ]
archive_type = payload.get( "archive_type", "url" )
self.queue_history_import( trans, archive_type=archive_type, archive_source=archive_source )
- trans.response.status = 201
return {}
new_history = None
diff -r ed003906850cce820f74afa3b2ae227ae03f38aa -r e18b36121df0bcb9a30906716e5b0c8a747bd138 test/functional/api/test_histories.py
--- a/test/functional/api/test_histories.py
+++ b/test/functional/api/test_histories.py
@@ -61,7 +61,7 @@
import_data = dict( archive_source=full_download_url, archive_type="url" )
import_response = self._post( "histories", data=import_data )
- self._assert_status_code_is( import_response, 201 )
+ self._assert_status_code_is( import_response, 200 )
found = False
while not found:
time.sleep( .1 )
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
10 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ed003906850c/
Changeset: ed003906850c
User: carlfeberhard
Date: 2014-02-10 23:25:55
Summary: Fix to 578b918
Affected #: 2 files
diff -r 578b9185b556ce59c170d3fa0b422bd7773d0693 -r ed003906850cce820f74afa3b2ae227ae03f38aa lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -180,11 +180,6 @@
:rtype: dict
:returns: element view of new history
"""
- def __create_via_import( self, payload ):
- return
-
- def __import_archive( self, trans, archive_type, archive_source ):
-
hist_name = None
if payload.get( 'name', None ):
hist_name = restore_text( payload['name'] )
diff -r 578b9185b556ce59c170d3fa0b422bd7773d0693 -r ed003906850cce820f74afa3b2ae227ae03f38aa test/functional/api/test_histories.py
--- a/test/functional/api/test_histories.py
+++ b/test/functional/api/test_histories.py
@@ -61,7 +61,7 @@
import_data = dict( archive_source=full_download_url, archive_type="url" )
import_response = self._post( "histories", data=import_data )
- self._assert_status_code_is( import_response, 200 )
+ self._assert_status_code_is( import_response, 201 )
found = False
while not found:
time.sleep( .1 )
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 API: allow copying another accessible history
by commits-noreply@bitbucket.org 10 Feb '14
by commits-noreply@bitbucket.org 10 Feb '14
10 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/578b9185b556/
Changeset: 578b9185b556
User: carlfeberhard
Date: 2014-02-10 21:00:22
Summary: History API: allow copying another accessible history
Affected #: 2 files
diff -r bb0f56f7c6361cf6021da56ce70ca07e0aa6818c -r 578b9185b556ce59c170d3fa0b422bd7773d0693 lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -170,35 +170,64 @@
:type payload: dict
:param payload: (optional) dictionary structure containing:
- * name: the new history's name
- * current: if passed, set the new history to be the user's 'current'
- history
+ * name: the new history's name
+ * current: if passed, set the new history to be the user's
+ 'current' history
+ * history_id: the id of the history to copy
+ * archive_source: the url that will generate the archive to import
+ * archive_type: 'url' (default)
:rtype: dict
:returns: element view of new history
"""
- if self.__create_via_import( payload ):
- return self.__import_archive( trans, payload )
+ def __create_via_import( self, payload ):
+ return
+
+ def __import_archive( self, trans, archive_type, archive_source ):
hist_name = None
if payload.get( 'name', None ):
hist_name = restore_text( payload['name'] )
- new_history = trans.app.model.History( user=trans.user, name=hist_name )
+ #TODO: possibly default to True here - but favor explicit for now (and backwards compat)
+ set_as_current = string_as_bool( payload[ 'current' ] ) if 'current' in payload else False
+ copy_this_history_id = payload.get( 'history_id', None )
+
+ if "archive_source" in payload:
+ archive_source = payload[ "archive_source" ]
+ archive_type = payload.get( "archive_type", "url" )
+ self.queue_history_import( trans, archive_type=archive_type, archive_source=archive_source )
+ trans.response.status = 201
+ return {}
+
+ new_history = None
+ # if a history id was passed, copy that history
+ if copy_this_history_id:
+ try:
+ original_history = self.get_history( trans, copy_this_history_id,
+ check_ownership=False, check_accessible=True )
+ except HTTPBadRequest, bad_request:
+ trans.response.status = 403
+ #TODO: it's either that or parse each possible detail to it's own status code
+ return { 'error': bad_request.detail or 'Bad request' }
+
+ hist_name = hist_name or ( "Copy of '%s'" % original_history.name )
+ new_history = original_history.copy( name=hist_name, target_user=trans.user )
+
+ # otherwise, create a new empty history
+ else:
+ new_history = trans.app.model.History( user=trans.user, name=hist_name )
+
+ item = {}
trans.sa_session.add( new_history )
trans.sa_session.flush()
- #item = new_history.to_dict(view='element', value_mapper={'id':trans.security.encode_id})
+
item = self.get_history_dict( trans, new_history )
item['url'] = url_for( 'history', id=item['id'] )
- #TODO: possibly default to True here - but favor explicit for now (and backwards compat)
- current = string_as_bool( payload[ 'current' ] ) if 'current' in payload else False
- if current:
+ if set_as_current:
trans.history = new_history
- #TODO: copy own history
- #TODO: import an importable history
- #TODO: import from archive
return item
@web.expose_api
@@ -398,14 +427,6 @@
return self.serve_ready_history_export( trans, jeha )
- def __create_via_import( self, payload ):
- return "archive_source" in payload
-
- def __import_archive( self, trans, payload ):
- archive_type = payload.get( "archive_type", "url" )
- archive_source = payload[ "archive_source" ]
- self.queue_history_import( trans, archive_type=archive_type, archive_source=archive_source )
-
def _validate_and_parse_update_payload( self, payload ):
"""
Validate and parse incomming data payload for a history.
diff -r bb0f56f7c6361cf6021da56ce70ca07e0aa6818c -r 578b9185b556ce59c170d3fa0b422bd7773d0693 test/functional/api/test_histories.py
--- a/test/functional/api/test_histories.py
+++ b/test/functional/api/test_histories.py
@@ -68,3 +68,5 @@
if import_name in history_names():
found = True
assert found, "%s not in history names %s" % ( import_name, history_names() )
+
+ #TODO: (CE) test_create_from_copy
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bb744d8d3d6a/
Changeset: bb744d8d3d6a
Branch: stable
User: dan
Date: 2014-02-10 19:31:39
Summary: Fix for Dataset.set_total_size() when e.g. encountering a dead symlink.
Affected #: 1 file
diff -r dc067a95261dec2b8862162dbac3f61bffa69ec9 -r bb744d8d3d6a74872a7b42b511d087c16b1ee8b3 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1183,7 +1183,7 @@
self.total_size = self.file_size or 0
if self.object_store.exists(self, extra_dir=self._extra_files_path or "dataset_%d_files" % self.id, dir_only=True):
for root, dirs, files in os.walk( self.extra_files_path ):
- self.total_size += sum( [ os.path.getsize( os.path.join( root, file ) ) for file in files ] )
+ self.total_size += sum( [ os.path.getsize( os.path.join( root, file ) ) for file in files if os.path.exists( os.path.join( root, file ) ) ] )
def has_data( self ):
"""Detects whether there is any data"""
return self.get_size() > 0
https://bitbucket.org/galaxy/galaxy-central/commits/bb0f56f7c636/
Changeset: bb0f56f7c636
User: dan
Date: 2014-02-10 19:32:35
Summary: merge
Affected #: 1 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
commit/galaxy-central: dan: Fix for Dataset.set_total_size() when e.g. encountering a dead symlink.
by commits-noreply@bitbucket.org 10 Feb '14
by commits-noreply@bitbucket.org 10 Feb '14
10 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ec9d31a8bc04/
Changeset: ec9d31a8bc04
User: dan
Date: 2014-02-10 19:31:39
Summary: Fix for Dataset.set_total_size() when e.g. encountering a dead symlink.
Affected #: 1 file
diff -r 29ce93a13ac7c4a5d2b54e5e2c10960f30a350b3 -r ec9d31a8bc046fa2c682c0b220b7ecdbd014e38b lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1221,7 +1221,7 @@
self.total_size = self.file_size or 0
if self.object_store.exists(self, extra_dir=self._extra_files_path or "dataset_%d_files" % self.id, dir_only=True):
for root, dirs, files in os.walk( self.extra_files_path ):
- self.total_size += sum( [ os.path.getsize( os.path.join( root, file ) ) for file in files ] )
+ self.total_size += sum( [ os.path.getsize( os.path.join( root, file ) ) for file in files if os.path.exists( os.path.join( root, file ) ) ] )
def has_data( self ):
"""Detects whether there is any data"""
return self.get_size() > 0
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Close next-stable for release.
by commits-noreply@bitbucket.org 10 Feb '14
by commits-noreply@bitbucket.org 10 Feb '14
10 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3fccf7610669/
Changeset: 3fccf7610669
Branch: next-stable
User: natefoo
Date: 2014-02-10 19:19:05
Summary: Close next-stable for release.
Affected #: 0 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Add a very simple example script that uses API to run data managers.
by commits-noreply@bitbucket.org 10 Feb '14
by commits-noreply@bitbucket.org 10 Feb '14
10 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a5c0d860d190/
Changeset: a5c0d860d190
User: dan
Date: 2014-02-10 17:59:58
Summary: Add a very simple example script that uses API to run data managers.
Affected #: 1 file
diff -r 1c14b0cdba15d8ffc2474a82aa3ca535e728f941 -r a5c0d860d19010309e8a8fd02f39c015c5315fe9 scripts/api/data_manager_example_execute.py
--- /dev/null
+++ b/scripts/api/data_manager_example_execute.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+##Dan Blankenberg
+##Very simple example of using the API to run Data Managers
+##Script makes the naive assumption that dbkey==sequence id, which in many cases is not true nor desired
+##*** This script is not recommended for use as-is on a production server ***
+
+import os
+import sys
+import optparse
+import urlparse
+import time
+
+sys.path.insert( 0, os.path.dirname( __file__ ) )
+
+from common import post, get
+
+DEFAULT_SLEEP_TIME = 3
+FETCH_GENOME_TOOL_ID = 'testtoolshed.g2.bx.psu.edu/repos/blankenberg/data_manager_fetch_genome_all_…'
+BUILD_INDEX_TOOLS_ID = [ 'testtoolshed.g2.bx.psu.edu/repos/blankenberg/data_manager_bwa_index_builder…',
+ 'testtoolshed.g2.bx.psu.edu/repos/blankenberg/data_manager_bwa_index_builder…' ]
+
+def run_tool( tool_id, history_id, params, api_key, galaxy_url, wait=True, sleep_time=None, **kwargs ):
+ sleep_time = sleep_time or DEFAULT_SLEEP_TIME
+ tools_url = urlparse.urljoin( galaxy_url, 'api/tools' )
+ payload = {
+ 'tool_id' : tool_id,
+ }
+ if history_id:
+ payload['history_id'] = history_id
+ payload[ 'inputs' ] = params
+ rval = post( api_key, tools_url, payload )
+ if wait:
+ outputs = list( rval['outputs'] )
+ while outputs:
+ finished_datasets = []
+ for i, dataset_dict in enumerate( outputs ):
+ if dataset_is_terminal( dataset_dict['id'], api_key=api_key, galaxy_url=galaxy_url ):
+ finished_datasets.append( i )
+ for i in reversed( finished_datasets ):
+ outputs.pop( 0 )
+ if wait and outputs:
+ time.sleep( sleep_time )
+
+ return rval
+
+def get_dataset_state( hda_id, api_key, galaxy_url ):
+ datasets_url = urlparse.urljoin( galaxy_url, 'api/datasets/%s' % hda_id )
+ dataset_info = get( api_key, datasets_url )
+ return dataset_info['state']
+
+def dataset_is_terminal( hda_id, api_key, galaxy_url ):
+ dataset_state = get_dataset_state( hda_id, api_key, galaxy_url )
+ return dataset_state in [ 'ok', 'error' ]
+
+if __name__ == '__main__':
+ #Parse Command Line
+ parser = optparse.OptionParser()
+ parser.add_option( '-k', '--key', dest='api_key', action='store', type="string", default=None, help='API Key.' )
+ parser.add_option( '-u', '--url', dest='base_url', action='store', type="string", default='http://localhost:8080', help='Base URL of Galaxy Server' )
+ parser.add_option( '-d', '--dbkey', dest='dbkeys', action='append', type="string", default=[], help='List of dbkeys to download and Index' )
+ parser.add_option( '-s', '--sleep_time', dest='sleep_time', action='store', type="int", default=DEFAULT_SLEEP_TIME, help='How long to sleep between check loops' )
+ (options, args) = parser.parse_args()
+
+ #check options
+ assert options.api_key is not None, ValueError( 'You must specify an API key.' )
+ assert options.dbkeys, ValueError( 'You must specify at least one dbkey to use.' )
+
+ #check user is admin
+ configuration_options = get( options.api_key, urlparse.urljoin( options.base_url, 'api/configuration' ) )
+ if 'library_import_dir' not in configuration_options: #hack to check if is admin user
+ print "Warning: Data Managers are only available to admin users. The API Key provided does not appear to belong to an admin user. Will attempt to run anyway."
+
+ #Fetch Genomes
+ dbkeys = {}
+ for dbkey in options.dbkeys:
+ if dbkey not in dbkeys:
+ dbkeys[ dbkey ] = run_tool( FETCH_GENOME_TOOL_ID, None, { 'dbkey':dbkey, 'reference_source|reference_source_selector': 'ucsc', 'reference_source|requested_dbkey': dbkey }, options.api_key, options.base_url, wait=False )
+ else:
+ "dbkey (%s) was specified more than once, skipping additional specification." % ( dbkey )
+
+ print 'Genomes Queued for downloading.'
+
+ #Start indexers
+ indexing_tools = []
+ while dbkeys:
+ for dbkey, value in dbkeys.items():
+ if dataset_is_terminal( value['outputs'][0]['id'], options.api_key, options.base_url ):
+ del dbkeys[ dbkey ]
+ for tool_id in BUILD_INDEX_TOOLS_ID:
+ indexing_tools.append( run_tool( tool_id, None, { 'all_fasta_source':dbkey }, options.api_key, options.base_url, wait=False ) )
+ if dbkeys:
+ time.sleep( options.sleep_time )
+
+ print 'All genomes downloaded and indexers now queued.'
+
+ #Wait for indexers to finish
+ while indexing_tools:
+ for i, indexing_tool_value in enumerate( indexing_tools ):
+ if dataset_is_terminal( indexing_tool_value['outputs'][0]['id'], options.api_key, options.base_url ):
+ print 'Finished:', indexing_tool_value
+ del indexing_tools[i]
+ break
+ if indexing_tools:
+ time.sleep( options.sleep_time )
+
+ print 'All indexers have been run, please check results.'
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f957eec387a0/
Changeset: f957eec387a0
Branch: next-stable
User: greg
Date: 2014-02-10 17:33:51
Summary: Fixes for the tool shed's install and test framework.
Affected #: 3 files
diff -r aea2ff5acd6805ad10db0442cc159f7e4e67a541 -r f957eec387a07f5dc7acceff2124a8ef2edac6f8 test/install_and_test_tool_shed_repositories/base/util.py
--- a/test/install_and_test_tool_shed_repositories/base/util.py
+++ b/test/install_and_test_tool_shed_repositories/base/util.py
@@ -285,15 +285,17 @@
break
return version
-def get_missing_repository_dependencies( repository ):
+def get_missing_repository_dependencies( repository, all_missing_repository_dependencies=None ):
"""
Return the entire list of missing repository dependencies for the received repository. The entire
dependency tree will be inspected.
"""
+ if all_missing_repository_dependencies is None:
+ all_missing_repository_dependencies = []
print 'Checking revision %s of repository %s owned by %s for missing repository dependencies.' % \
( repository.changeset_revision, repository.name, repository.owner )
- missing_repository_dependencies = repository.missing_repository_dependencies
- for missing_required_repository in missing_repository_dependencies:
+ all_missing_repository_dependencies.extend( repository.missing_repository_dependencies )
+ for missing_required_repository in repository.missing_repository_dependencies:
print 'Revision %s of required repository %s owned by %s has status %s.' % \
( missing_required_repository.changeset_revision,
missing_required_repository.name,
@@ -301,24 +303,28 @@
missing_required_repository.status )
for repository_dependency in repository.repository_dependencies:
if repository_dependency.missing_repository_dependencies:
- missing_repository_dependencies.extend( get_missing_repository_dependencies( repository_dependency ) )
- return missing_repository_dependencies
+ all_missing_repository_dependencies.extend( get_missing_repository_dependencies( repository_dependency,
+ all_missing_repository_dependencies ) )
+ return all_missing_repository_dependencies
-def get_missing_tool_dependencies( repository ):
+def get_missing_tool_dependencies( repository, all_missing_tool_dependencies=None ):
"""
Return the entire list of missing tool dependencies for the received repository. The entire
dependency tree will be inspected.
"""
+ if all_missing_tool_dependencies is None:
+ all_missing_tool_dependencies = []
print 'Checking revision %s of repository %s owned by %s for missing tool dependencies.' % \
( repository.changeset_revision, repository.name, repository.owner )
- missing_tool_dependencies = repository.missing_tool_dependencies
- for missing_tool_dependency in missing_tool_dependencies:
+ all_missing_tool_dependencies.extend( repository.missing_tool_dependencies )
+ for missing_tool_dependency in repository.missing_tool_dependencies:
print 'Tool dependency %s version %s has status %s.' % \
( missing_tool_dependency.name, missing_tool_dependency.version, missing_tool_dependency.status )
for repository_dependency in repository.repository_dependencies:
- if repository_dependency.includes_tool_dependencies:
- missing_tool_dependencies.extend( get_missing_tool_dependencies( repository_dependency ) )
- return missing_tool_dependencies
+ if repository_dependency.missing_tool_dependencies:
+ all_missing_tool_dependencies.extend( get_missing_tool_dependencies( repository_dependency,
+ all_missing_tool_dependencies ) )
+ return all_missing_tool_dependencies
def get_repositories_to_install( tool_shed_url, test_framework ):
"""
@@ -950,29 +956,23 @@
repository_identifier_tup,
install_and_test_statistics_dict,
tool_test_results_dict )
- response_dict = save_test_results_for_changeset_revision( galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dependencies_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print'\n============================================================='
+ save_test_results_for_changeset_revision( galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dependencies_dict,
+ params,
+ can_update_tool_shed )
else:
# The required repository's installation failed.
tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = str( required_repository.error_message )
params = dict( test_install_error=True,
do_not_test=False )
- response_dict = save_test_results_for_changeset_revision( galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dependencies_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print'\n============================================================='
+ save_test_results_for_changeset_revision( galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dependencies_dict,
+ params,
+ can_update_tool_shed )
else:
print 'Cannot retrieve revision %s of required repository %s owned by %s from the database ' % \
( changeset_revision, name, owner )
@@ -1059,26 +1059,26 @@
changeset_revision = repository_dict.get( 'changeset_revision', None )
if name is None or owner is None or changeset_revision is None:
print 'Entries for name, owner or changeset_revision missing from repository_dict %s' % repository_dict
- return {}
- name = str( name )
- owner = str( owner )
- changeset_revision = str( changeset_revision )
- print '\n============================================================='
- print 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( tool_test_results_dict ) )
- print 'Updating tool_test_results for repository_metadata id %s.' % metadata_revision_id
- tool_test_results_dicts.insert( 0, tool_test_results_dict )
- params[ 'tool_test_results' ] = tool_test_results_dicts
- # Set the time_last_tested entry so that the repository_metadata.time_last_tested will be set in the tool shed.
- params[ 'time_last_tested' ] = 'This entry will result in this value being set via the Tool Shed API.'
- url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) )
- print 'url: ', url
- print 'params: ', params
- try:
- return update( tool_shed_api_key, url, params, return_formatted=False )
- except Exception, e:
- log.exception( 'Error updating tool_test_results for repository_metadata id %s:\n%s' % \
- ( str( metadata_revision_id ), str( e ) ) )
- return {}
- else:
- return {}
+ else:
+ name = str( name )
+ owner = str( owner )
+ changeset_revision = str( changeset_revision )
+ print '\n=============================================================\n'
+ print 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
+ ( changeset_revision, name, owner, str( tool_test_results_dict ) )
+ print 'Updating tool_test_results for repository_metadata id %s.' % metadata_revision_id
+ tool_test_results_dicts.insert( 0, tool_test_results_dict )
+ params[ 'tool_test_results' ] = tool_test_results_dicts
+ # Set the time_last_tested entry so that the repository_metadata.time_last_tested will be set in the tool shed.
+ params[ 'time_last_tested' ] = 'This entry will result in this value being set via the Tool Shed API.'
+ url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) )
+ print 'url: ', url
+ print 'params: ', params
+ try:
+ response_from_update = update( tool_shed_api_key, url, params, return_formatted=False )
+ print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
+ ( changeset_revision, name, owner, str( response_from_update ) )
+ print '\n=============================================================\n'
+ except Exception, e:
+ log.exception( 'Error updating tool_test_results for repository_metadata id %s:\n%s' % \
+ ( str( metadata_revision_id ), str( e ) ) )
diff -r aea2ff5acd6805ad10db0442cc159f7e4e67a541 -r f957eec387a07f5dc7acceff2124a8ef2edac6f8 test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
@@ -195,16 +195,12 @@
# If this repository is being skipped, register the reason.
tool_test_results_dict[ 'not_tested' ] = dict( reason=reason )
params = dict( do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# See if the repository was installed in a previous test.
repository = install_and_test_base_util.get_repository( name, owner, changeset_revision )
@@ -223,16 +219,12 @@
tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message
params = dict( test_install_error=True,
do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# The repository was successfully installed.
print 'Installation succeeded for revision %s of repository %s owned by %s.' % \
@@ -243,6 +235,9 @@
# missing test components.
if 'missing_test_components' not in tool_test_results_dict:
tool_test_results_dict[ 'missing_test_components' ] = []
+ # Hopefully we'll be able to run functional tests defined for tools contained in the repository - we'll
+ # assume so as the default.
+ can_run_functional_tests = True
# Populate the installation containers (success and error) for the repository's immediate dependencies
# (the entire dependency tree is not handled here).
params, install_and_test_statistics_dict, tool_test_results_dict = \
@@ -254,16 +249,18 @@
if params.get( 'test_install_error', False ):
# The repository was successfully installed, but one or more dependencies had installation errors,
# so we'll populate the test result containers since we cannot execute any tests.
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print'\n============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
+ # We cannot run functional tests for contained tools due to dependency installation errors.
+ print 'Cannot execute tests for tools in revision %s of repository %s owned by %s ' % \
+ ( changeset_revision, name, owner )
+ print 'because one or more dependencies has installation errors.'
+ can_run_functional_tests = False
+ remove_tests( app )
# Populate the installation containers (success or error) for the repository's immediate repository
# dependencies whose containers are not yet populated.
install_and_test_base_util.populate_install_containers_for_repository_dependencies( app,
@@ -271,63 +268,67 @@
encoded_repository_metadata_id,
install_and_test_statistics_dict,
can_update_tool_shed )
- # Execute the contained tool's functional tests only if the repository's entire dependency
- # tree is successfully installed.
- missing_repository_dependencies = install_and_test_base_util.get_missing_repository_dependencies( repository )
- missing_tool_dependencies = install_and_test_base_util.get_missing_tool_dependencies( repository )
- if missing_repository_dependencies or missing_tool_dependencies:
- print 'Cannot execute tests for tools in revision %s of repository %s owned by %s ' % \
- ( changeset_revision, name, owner )
- print 'because one or more dependencies has installation errors.'
- # The repository was installed successfully, but one or more dependencies had installation errors. Since
- # we cannot test the tools due to these errors, we'll remove tests and tools were created during the repository
- # installation process so nose will not discover them and attempt to execute them.
- remove_tests( app )
- else:
- print 'Revision %s of repository %s owned by %s installed successfully, so running tool tests.' % \
- ( changeset_revision, name, owner )
- # Generate the shed_tools_dict that specifies the location of test data contained within this repository.
- # and configure and run functional tests for this repository. This is equivalent to
- # sh run_functional_tests.sh -installed
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( {} ) )
- # Find the path to the test-data directory within the installed repository.
- has_test_data, shed_tools_dict = \
- parse_tool_panel_config( galaxy_shed_tool_conf_file,
- from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
- # If the repository has a test-data directory we write the generated shed_tools_dict to a temporary
- # file so the functional test framework can find it.
- # TODO: Eliminate the need for this shed_tools_dict since it grows large over the course of each test run.
- # If it cannot be eliminated altogether, reinitialize it with each new repository install so at this point
- # it contains only entries for the current repository dependency hierarchy being tested.
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
- print 'Saved generated shed_tools_dict to %s\nContents: %s' % ( galaxy_shed_tools_dict, shed_tools_dict )
- try:
- install_and_test_statistics_dict = test_repository_tools( app,
- repository,
- repository_dict,
- tool_test_results_dicts,
- tool_test_results_dict,
- install_and_test_statistics_dict )
- except Exception, e:
- exception_message = 'Error executing tests for repository %s: %s' % ( name, str( e ) )
- log.exception( exception_message )
- tool_test_results_dict[ 'failed_tests' ].append( exception_message )
- processed_at_least_one_test_failed = \
- install_and_test_statistics_dict.get( 'at_least_one_test_failed', [] )
- if repository_identifier_tup not in processed_at_least_one_test_failed:
- install_and_test_statistics_dict[ 'at_least_one_test_failed' ].append( repository_identifier_tup )
- # Record the status of this repository in the tool shed.
- params[ 'tools_functionally_correct' ] = False
- response_dict = \
+ if can_run_functional_tests:
+ # Execute the contained tool's functional tests only if the repository's entire dependency
+ # tree is successfully installed. The following checks should discover missing dependencies
+ # at any level of the dependency hierarchy.
+ missing_repository_dependencies = \
+ install_and_test_base_util.get_missing_repository_dependencies( repository,
+ all_missing_repository_dependencies=None )
+ print 'Missing repository dependencies:\n%s' % str( missing_repository_dependencies )
+ missing_tool_dependencies = \
+ install_and_test_base_util.get_missing_tool_dependencies( repository,
+ all_missing_tool_dependencies=None )
+ print 'Missing tool dependencies:\n%s' % str( missing_tool_dependencies )
+ if missing_repository_dependencies or missing_tool_dependencies:
+ print 'Cannot execute tests for tools in revision %s of repository %s owned by %s ' % \
+ ( changeset_revision, name, owner )
+ print 'because one or more dependencies has installation errors.'
+ # The repository was installed successfully, but one or more dependencies had installation errors. Since
+ # we cannot test the tools due to these errors, we'll remove tests and tools were created during the repository
+ # installation process so nose will not discover them and attempt to execute them.
+ remove_tests( app )
+ else:
+ print 'Revision %s of repository %s owned by %s installed successfully, so running tool tests.' % \
+ ( changeset_revision, name, owner )
+ # Generate the shed_tools_dict that specifies the location of test data contained within this repository.
+ # and configure and run functional tests for this repository. This is equivalent to
+ # sh run_functional_tests.sh -installed
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( {} ) )
+ # Find the path to the test-data directory within the installed repository.
+ has_test_data, shed_tools_dict = \
+ parse_tool_panel_config( galaxy_shed_tool_conf_file,
+ from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
+ # If the repository has a test-data directory we write the generated shed_tools_dict to a temporary
+ # file so the functional test framework can find it.
+ # TODO: Eliminate the need for this shed_tools_dict since it grows large over the course of each test run.
+ # If it cannot be eliminated altogether, reinitialize it with each new repository install so at this point
+ # it contains only entries for the current repository dependency hierarchy being tested.
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
+ print 'Saved generated shed_tools_dict to %s\nContents: %s' % ( galaxy_shed_tools_dict, shed_tools_dict )
+ try:
+ install_and_test_statistics_dict = test_repository_tools( app,
+ repository,
+ repository_dict,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ install_and_test_statistics_dict )
+ except Exception, e:
+ exception_message = 'Error executing tests for repository %s: %s' % ( name, str( e ) )
+ log.exception( exception_message )
+ tool_test_results_dict[ 'failed_tests' ].append( exception_message )
+ processed_at_least_one_test_failed = \
+ install_and_test_statistics_dict.get( 'at_least_one_test_failed', [] )
+ if repository_identifier_tup not in processed_at_least_one_test_failed:
+ install_and_test_statistics_dict[ 'at_least_one_test_failed' ].append( repository_identifier_tup )
+ # Record the status of this repository in the tool shed.
+ params[ 'tools_functionally_correct' ] = False
install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
tool_test_results_dicts,
tool_test_results_dict,
repository_dict,
params,
can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
else:
print 'Skipped attempt to install revision %s of repository %s owned by %s because ' % \
( changeset_revision, name, owner )
@@ -663,16 +664,12 @@
# Call the save_test_results_for_changeset_revision() method to execute a PUT request to the
# repository_revisions API controller with the status of the test. This also sets the do_not_test
# and tools_functionally correct flags and updates the time_last_tested field to today's date.
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# The get_failed_test_dicts() method returns a list.
print 'Revision %s of repository %s owned by %s installed successfully but did not pass functional tests.' % \
@@ -695,16 +692,12 @@
params = dict( tools_functionally_correct=False,
test_install_error=False,
do_not_test=set_do_not_test )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
# Remove the just-executed tests so twill will not find and re-test them along with the tools
# contained in the next repository.
remove_tests( app )
diff -r aea2ff5acd6805ad10db0442cc159f7e4e67a541 -r f957eec387a07f5dc7acceff2124a8ef2edac6f8 test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
@@ -129,16 +129,12 @@
( changeset_revision, name, owner )
tool_test_results_dict[ 'not_tested' ] = dict( reason=reason )
params = dict( do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# See if the repository was installed in a previous test.
repository = install_and_test_base_util.get_repository( name, owner, changeset_revision )
@@ -157,16 +153,12 @@
tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message
params = dict( test_install_error=True,
do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# The repository was successfully installed.
print 'Installation succeeded for revision %s of repository %s owned by %s.' % \
@@ -179,16 +171,12 @@
repository_identifier_tup,
install_and_test_statistics_dict,
tool_test_results_dict )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
# Populate the installation containers (success or error) for the repository's immediate repository
# dependencies whose containers are not yet populated.
install_and_test_base_util.populate_install_containers_for_repository_dependencies( app,
https://bitbucket.org/galaxy/galaxy-central/commits/1c14b0cdba15/
Changeset: 1c14b0cdba15
User: greg
Date: 2014-02-10 17:34:23
Summary: merged from next-stable
Affected #: 3 files
diff -r 7ca065784d58e7aa77e5092952eacd963853df65 -r 1c14b0cdba15d8ffc2474a82aa3ca535e728f941 test/install_and_test_tool_shed_repositories/base/util.py
--- a/test/install_and_test_tool_shed_repositories/base/util.py
+++ b/test/install_and_test_tool_shed_repositories/base/util.py
@@ -285,15 +285,17 @@
break
return version
-def get_missing_repository_dependencies( repository ):
+def get_missing_repository_dependencies( repository, all_missing_repository_dependencies=None ):
"""
Return the entire list of missing repository dependencies for the received repository. The entire
dependency tree will be inspected.
"""
+ if all_missing_repository_dependencies is None:
+ all_missing_repository_dependencies = []
print 'Checking revision %s of repository %s owned by %s for missing repository dependencies.' % \
( repository.changeset_revision, repository.name, repository.owner )
- missing_repository_dependencies = repository.missing_repository_dependencies
- for missing_required_repository in missing_repository_dependencies:
+ all_missing_repository_dependencies.extend( repository.missing_repository_dependencies )
+ for missing_required_repository in repository.missing_repository_dependencies:
print 'Revision %s of required repository %s owned by %s has status %s.' % \
( missing_required_repository.changeset_revision,
missing_required_repository.name,
@@ -301,24 +303,28 @@
missing_required_repository.status )
for repository_dependency in repository.repository_dependencies:
if repository_dependency.missing_repository_dependencies:
- missing_repository_dependencies.extend( get_missing_repository_dependencies( repository_dependency ) )
- return missing_repository_dependencies
+ all_missing_repository_dependencies.extend( get_missing_repository_dependencies( repository_dependency,
+ all_missing_repository_dependencies ) )
+ return all_missing_repository_dependencies
-def get_missing_tool_dependencies( repository ):
+def get_missing_tool_dependencies( repository, all_missing_tool_dependencies=None ):
"""
Return the entire list of missing tool dependencies for the received repository. The entire
dependency tree will be inspected.
"""
+ if all_missing_tool_dependencies is None:
+ all_missing_tool_dependencies = []
print 'Checking revision %s of repository %s owned by %s for missing tool dependencies.' % \
( repository.changeset_revision, repository.name, repository.owner )
- missing_tool_dependencies = repository.missing_tool_dependencies
- for missing_tool_dependency in missing_tool_dependencies:
+ all_missing_tool_dependencies.extend( repository.missing_tool_dependencies )
+ for missing_tool_dependency in repository.missing_tool_dependencies:
print 'Tool dependency %s version %s has status %s.' % \
( missing_tool_dependency.name, missing_tool_dependency.version, missing_tool_dependency.status )
for repository_dependency in repository.repository_dependencies:
- if repository_dependency.includes_tool_dependencies:
- missing_tool_dependencies.extend( get_missing_tool_dependencies( repository_dependency ) )
- return missing_tool_dependencies
+ if repository_dependency.missing_tool_dependencies:
+ all_missing_tool_dependencies.extend( get_missing_tool_dependencies( repository_dependency,
+ all_missing_tool_dependencies ) )
+ return all_missing_tool_dependencies
def get_repositories_to_install( tool_shed_url, test_framework ):
"""
@@ -950,29 +956,23 @@
repository_identifier_tup,
install_and_test_statistics_dict,
tool_test_results_dict )
- response_dict = save_test_results_for_changeset_revision( galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dependencies_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print'\n============================================================='
+ save_test_results_for_changeset_revision( galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dependencies_dict,
+ params,
+ can_update_tool_shed )
else:
# The required repository's installation failed.
tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = str( required_repository.error_message )
params = dict( test_install_error=True,
do_not_test=False )
- response_dict = save_test_results_for_changeset_revision( galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dependencies_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print'\n============================================================='
+ save_test_results_for_changeset_revision( galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dependencies_dict,
+ params,
+ can_update_tool_shed )
else:
print 'Cannot retrieve revision %s of required repository %s owned by %s from the database ' % \
( changeset_revision, name, owner )
@@ -1059,26 +1059,26 @@
changeset_revision = repository_dict.get( 'changeset_revision', None )
if name is None or owner is None or changeset_revision is None:
print 'Entries for name, owner or changeset_revision missing from repository_dict %s' % repository_dict
- return {}
- name = str( name )
- owner = str( owner )
- changeset_revision = str( changeset_revision )
- print '\n============================================================='
- print 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( tool_test_results_dict ) )
- print 'Updating tool_test_results for repository_metadata id %s.' % metadata_revision_id
- tool_test_results_dicts.insert( 0, tool_test_results_dict )
- params[ 'tool_test_results' ] = tool_test_results_dicts
- # Set the time_last_tested entry so that the repository_metadata.time_last_tested will be set in the tool shed.
- params[ 'time_last_tested' ] = 'This entry will result in this value being set via the Tool Shed API.'
- url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) )
- print 'url: ', url
- print 'params: ', params
- try:
- return update( tool_shed_api_key, url, params, return_formatted=False )
- except Exception, e:
- log.exception( 'Error updating tool_test_results for repository_metadata id %s:\n%s' % \
- ( str( metadata_revision_id ), str( e ) ) )
- return {}
- else:
- return {}
+ else:
+ name = str( name )
+ owner = str( owner )
+ changeset_revision = str( changeset_revision )
+ print '\n=============================================================\n'
+ print 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
+ ( changeset_revision, name, owner, str( tool_test_results_dict ) )
+ print 'Updating tool_test_results for repository_metadata id %s.' % metadata_revision_id
+ tool_test_results_dicts.insert( 0, tool_test_results_dict )
+ params[ 'tool_test_results' ] = tool_test_results_dicts
+ # Set the time_last_tested entry so that the repository_metadata.time_last_tested will be set in the tool shed.
+ params[ 'time_last_tested' ] = 'This entry will result in this value being set via the Tool Shed API.'
+ url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) )
+ print 'url: ', url
+ print 'params: ', params
+ try:
+ response_from_update = update( tool_shed_api_key, url, params, return_formatted=False )
+ print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
+ ( changeset_revision, name, owner, str( response_from_update ) )
+ print '\n=============================================================\n'
+ except Exception, e:
+ log.exception( 'Error updating tool_test_results for repository_metadata id %s:\n%s' % \
+ ( str( metadata_revision_id ), str( e ) ) )
diff -r 7ca065784d58e7aa77e5092952eacd963853df65 -r 1c14b0cdba15d8ffc2474a82aa3ca535e728f941 test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
@@ -195,16 +195,12 @@
# If this repository is being skipped, register the reason.
tool_test_results_dict[ 'not_tested' ] = dict( reason=reason )
params = dict( do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# See if the repository was installed in a previous test.
repository = install_and_test_base_util.get_repository( name, owner, changeset_revision )
@@ -223,16 +219,12 @@
tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message
params = dict( test_install_error=True,
do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# The repository was successfully installed.
print 'Installation succeeded for revision %s of repository %s owned by %s.' % \
@@ -243,6 +235,9 @@
# missing test components.
if 'missing_test_components' not in tool_test_results_dict:
tool_test_results_dict[ 'missing_test_components' ] = []
+ # Hopefully we'll be able to run functional tests defined for tools contained in the repository - we'll
+ # assume so as the default.
+ can_run_functional_tests = True
# Populate the installation containers (success and error) for the repository's immediate dependencies
# (the entire dependency tree is not handled here).
params, install_and_test_statistics_dict, tool_test_results_dict = \
@@ -254,16 +249,18 @@
if params.get( 'test_install_error', False ):
# The repository was successfully installed, but one or more dependencies had installation errors,
# so we'll populate the test result containers since we cannot execute any tests.
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print'\n============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
+ # We cannot run functional tests for contained tools due to dependency installation errors.
+ print 'Cannot execute tests for tools in revision %s of repository %s owned by %s ' % \
+ ( changeset_revision, name, owner )
+ print 'because one or more dependencies has installation errors.'
+ can_run_functional_tests = False
+ remove_tests( app )
# Populate the installation containers (success or error) for the repository's immediate repository
# dependencies whose containers are not yet populated.
install_and_test_base_util.populate_install_containers_for_repository_dependencies( app,
@@ -271,63 +268,67 @@
encoded_repository_metadata_id,
install_and_test_statistics_dict,
can_update_tool_shed )
- # Execute the contained tool's functional tests only if the repository's entire dependency
- # tree is successfully installed.
- missing_repository_dependencies = install_and_test_base_util.get_missing_repository_dependencies( repository )
- missing_tool_dependencies = install_and_test_base_util.get_missing_tool_dependencies( repository )
- if missing_repository_dependencies or missing_tool_dependencies:
- print 'Cannot execute tests for tools in revision %s of repository %s owned by %s ' % \
- ( changeset_revision, name, owner )
- print 'because one or more dependencies has installation errors.'
- # The repository was installed successfully, but one or more dependencies had installation errors. Since
- # we cannot test the tools due to these errors, we'll remove tests and tools were created during the repository
- # installation process so nose will not discover them and attempt to execute them.
- remove_tests( app )
- else:
- print 'Revision %s of repository %s owned by %s installed successfully, so running tool tests.' % \
- ( changeset_revision, name, owner )
- # Generate the shed_tools_dict that specifies the location of test data contained within this repository.
- # and configure and run functional tests for this repository. This is equivalent to
- # sh run_functional_tests.sh -installed
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( {} ) )
- # Find the path to the test-data directory within the installed repository.
- has_test_data, shed_tools_dict = \
- parse_tool_panel_config( galaxy_shed_tool_conf_file,
- from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
- # If the repository has a test-data directory we write the generated shed_tools_dict to a temporary
- # file so the functional test framework can find it.
- # TODO: Eliminate the need for this shed_tools_dict since it grows large over the course of each test run.
- # If it cannot be eliminated altogether, reinitialize it with each new repository install so at this point
- # it contains only entries for the current repository dependency hierarchy being tested.
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
- print 'Saved generated shed_tools_dict to %s\nContents: %s' % ( galaxy_shed_tools_dict, shed_tools_dict )
- try:
- install_and_test_statistics_dict = test_repository_tools( app,
- repository,
- repository_dict,
- tool_test_results_dicts,
- tool_test_results_dict,
- install_and_test_statistics_dict )
- except Exception, e:
- exception_message = 'Error executing tests for repository %s: %s' % ( name, str( e ) )
- log.exception( exception_message )
- tool_test_results_dict[ 'failed_tests' ].append( exception_message )
- processed_at_least_one_test_failed = \
- install_and_test_statistics_dict.get( 'at_least_one_test_failed', [] )
- if repository_identifier_tup not in processed_at_least_one_test_failed:
- install_and_test_statistics_dict[ 'at_least_one_test_failed' ].append( repository_identifier_tup )
- # Record the status of this repository in the tool shed.
- params[ 'tools_functionally_correct' ] = False
- response_dict = \
+ if can_run_functional_tests:
+ # Execute the contained tool's functional tests only if the repository's entire dependency
+ # tree is successfully installed. The following checks should discover missing dependencies
+ # at any level of the dependency hierarchy.
+ missing_repository_dependencies = \
+ install_and_test_base_util.get_missing_repository_dependencies( repository,
+ all_missing_repository_dependencies=None )
+ print 'Missing repository dependencies:\n%s' % str( missing_repository_dependencies )
+ missing_tool_dependencies = \
+ install_and_test_base_util.get_missing_tool_dependencies( repository,
+ all_missing_tool_dependencies=None )
+ print 'Missing tool dependencies:\n%s' % str( missing_tool_dependencies )
+ if missing_repository_dependencies or missing_tool_dependencies:
+ print 'Cannot execute tests for tools in revision %s of repository %s owned by %s ' % \
+ ( changeset_revision, name, owner )
+ print 'because one or more dependencies has installation errors.'
+ # The repository was installed successfully, but one or more dependencies had installation errors. Since
+ # we cannot test the tools due to these errors, we'll remove tests and tools were created during the repository
+ # installation process so nose will not discover them and attempt to execute them.
+ remove_tests( app )
+ else:
+ print 'Revision %s of repository %s owned by %s installed successfully, so running tool tests.' % \
+ ( changeset_revision, name, owner )
+ # Generate the shed_tools_dict that specifies the location of test data contained within this repository.
+ # and configure and run functional tests for this repository. This is equivalent to
+ # sh run_functional_tests.sh -installed
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( {} ) )
+ # Find the path to the test-data directory within the installed repository.
+ has_test_data, shed_tools_dict = \
+ parse_tool_panel_config( galaxy_shed_tool_conf_file,
+ from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
+ # If the repository has a test-data directory we write the generated shed_tools_dict to a temporary
+ # file so the functional test framework can find it.
+ # TODO: Eliminate the need for this shed_tools_dict since it grows large over the course of each test run.
+ # If it cannot be eliminated altogether, reinitialize it with each new repository install so at this point
+ # it contains only entries for the current repository dependency hierarchy being tested.
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
+ print 'Saved generated shed_tools_dict to %s\nContents: %s' % ( galaxy_shed_tools_dict, shed_tools_dict )
+ try:
+ install_and_test_statistics_dict = test_repository_tools( app,
+ repository,
+ repository_dict,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ install_and_test_statistics_dict )
+ except Exception, e:
+ exception_message = 'Error executing tests for repository %s: %s' % ( name, str( e ) )
+ log.exception( exception_message )
+ tool_test_results_dict[ 'failed_tests' ].append( exception_message )
+ processed_at_least_one_test_failed = \
+ install_and_test_statistics_dict.get( 'at_least_one_test_failed', [] )
+ if repository_identifier_tup not in processed_at_least_one_test_failed:
+ install_and_test_statistics_dict[ 'at_least_one_test_failed' ].append( repository_identifier_tup )
+ # Record the status of this repository in the tool shed.
+ params[ 'tools_functionally_correct' ] = False
install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
tool_test_results_dicts,
tool_test_results_dict,
repository_dict,
params,
can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
else:
print 'Skipped attempt to install revision %s of repository %s owned by %s because ' % \
( changeset_revision, name, owner )
@@ -663,16 +664,12 @@
# Call the save_test_results_for_changeset_revision() method to execute a PUT request to the
# repository_revisions API controller with the status of the test. This also sets the do_not_test
# and tools_functionally correct flags and updates the time_last_tested field to today's date.
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# The get_failed_test_dicts() method returns a list.
print 'Revision %s of repository %s owned by %s installed successfully but did not pass functional tests.' % \
@@ -695,16 +692,12 @@
params = dict( tools_functionally_correct=False,
test_install_error=False,
do_not_test=set_do_not_test )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
# Remove the just-executed tests so twill will not find and re-test them along with the tools
# contained in the next repository.
remove_tests( app )
diff -r 7ca065784d58e7aa77e5092952eacd963853df65 -r 1c14b0cdba15d8ffc2474a82aa3ca535e728f941 test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py
@@ -129,16 +129,12 @@
( changeset_revision, name, owner )
tool_test_results_dict[ 'not_tested' ] = dict( reason=reason )
params = dict( do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# See if the repository was installed in a previous test.
repository = install_and_test_base_util.get_repository( name, owner, changeset_revision )
@@ -157,16 +153,12 @@
tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message
params = dict( test_install_error=True,
do_not_test=False )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
else:
# The repository was successfully installed.
print 'Installation succeeded for revision %s of repository %s owned by %s.' % \
@@ -179,16 +171,12 @@
repository_identifier_tup,
install_and_test_statistics_dict,
tool_test_results_dict )
- response_dict = \
- install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
- tool_test_results_dicts,
- tool_test_results_dict,
- repository_dict,
- params,
- can_update_tool_shed )
- print 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \
- ( changeset_revision, name, owner, str( response_dict ) )
- print '============================================================='
+ install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url,
+ tool_test_results_dicts,
+ tool_test_results_dict,
+ repository_dict,
+ params,
+ can_update_tool_shed )
# Populate the installation containers (success or error) for the repository's immediate repository
# dependencies whose containers are not yet populated.
install_and_test_base_util.populate_install_containers_for_repository_dependencies( app,
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: enable multi-select, decrease loading indicator fade time, correct disabled icon-btn color
by commits-noreply@bitbucket.org 10 Feb '14
by commits-noreply@bitbucket.org 10 Feb '14
10 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7ca065784d58/
Changeset: 7ca065784d58
User: carlfeberhard
Date: 2014-02-10 15:52:40
Summary: History panel: enable multi-select, decrease loading indicator fade time, correct disabled icon-btn color
Affected #: 13 files
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -45,12 +45,16 @@
/** is the view currently in selection mode? */
this.selectable = attributes.selectable || false;
+ //this.log( '\t selectable:', this.selectable );
/** is the view currently selected? */
this.selected = attributes.selected || false;
+ //this.log( '\t selected:', this.selected );
/** is the body of this hda view expanded/not? */
this.expanded = attributes.expanded || false;
+ //this.log( '\t expanded:', this.expanded );
/** is the body of this hda view expanded/not? */
this.draggable = attributes.draggable || false;
+ //this.log( '\t draggable:', this.draggable );
this._setUpListeners();
},
@@ -412,12 +416,13 @@
// expand the body when the title is clicked or when in focus and space or enter is pressed
'click .dataset-title-bar' : 'toggleBodyVisibility',
'keydown .dataset-title-bar' : 'toggleBodyVisibility',
- // toggle selected state
- 'click .dataset-selector' : 'toggleSelect',
// dragging - don't work, originalEvent === null
//'dragstart .dataset-title-bar' : 'dragStartHandler',
//'dragend .dataset-title-bar' : 'dragEndHandler'
+
+ // toggle selected state
+ 'click .dataset-selector' : 'toggleSelect'
},
/** Show or hide the body/details of an HDA.
@@ -489,8 +494,6 @@
* Note: this also hides the primary actions
*/
showSelector : function( speed ){
- // if already shown, do nothing
- if( this.$el.find( '.dataset-selector' ).css( 'display' ) !== 'none' ){ return; }
speed = ( speed !== undefined )?( speed ):( this.fxSpeed );
// make sure selected state is represented properly
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -152,11 +152,14 @@
/** filters for displaying hdas */
this.filters = [];
+ /** selected hda ids */
+ this.selectedHdaIds = [];
// states/modes the panel can be in
/** is the panel currently showing the dataset selection controls? */
this.selecting = attributes.selecting || false;
this.annotationEditorShown = attributes.annotationEditorShown || false;
+ this.tagsEditorShown = attributes.tagsEditorShown || false;
this._setUpListeners();
@@ -184,11 +187,11 @@
this.on( 'loading-history', function(){
// show the loading indicator when loading a new history starts...
- this.showLoadingIndicator( 'loading history...' );
+ this.showLoadingIndicator( 'loading history...', 40 );
});
this.on( 'loading-done', function(){
// ...hiding it again when loading is done (or there's been an error)
- this.hideLoadingIndicator();
+ this.hideLoadingIndicator( 40 );
});
// throw the first render up as a diff namespace using once
@@ -408,6 +411,7 @@
this.model = new historyModel.History( newHistoryJSON, newHdaJSON, attributes );
this._setUpWebStorage( attributes.initiallyExpanded, attributes.show_deleted, attributes.show_hidden );
this._setUpModelEventHandlers();
+ this.selectedHdaIds = [];
this.trigger( 'new-model', this );
this.render();
return this;
@@ -596,8 +600,8 @@
}
}
// search and select available to both anon/logged-in users
- //$newRender.find( '.history-secondary-actions' ).prepend( this._renderSelectButton() );
- //$newRender.find( '.history-dataset-actions' ).toggle( this.selecting );
+ $newRender.find( '.history-secondary-actions' ).prepend( this._renderSelectButton() );
+ $newRender.find( '.history-dataset-actions' ).toggle( this.selecting );
$newRender.find( '.history-secondary-actions' ).prepend( this._renderSearchButton() );
this._setUpBehaviours( $newRender );
@@ -687,8 +691,15 @@
$where.find( '[title]' ).tooltip({ placement: 'bottom' });
// anon users shouldn't have access to any of the following
- if( ( !this.model )
- || ( !Galaxy.currUser || Galaxy.currUser.isAnonymous() )
+ if( !this.model ){
+ return;
+ }
+
+ // set up the pupup for actions available when multi selecting
+ this._setUpDatasetActionsPopup( $where );
+
+ // anon users shouldn't have access to any of the following
+ if( ( !Galaxy.currUser || Galaxy.currUser.isAnonymous() )
|| ( Galaxy.currUser.id !== this.model.get( 'user_id' ) ) ){
return;
}
@@ -710,7 +721,6 @@
}
}
});
- this._setUpDatasetActionsPopup( $where );
},
_setUpDatasetActionsPopup : function( $where ){
@@ -785,8 +795,10 @@
},
function createAndPrepend( next ){
panel.scrollToTop();
- var $whereTo = panel.$el.find( panel.datasetsSelector );
- panel.createHdaView( hda ).$el.hide().prependTo( $whereTo ).slideDown( panel.fxSpeed );
+ var $whereTo = panel.$el.find( panel.datasetsSelector ),
+ hdaView = panel.createHdaView( hda );
+ panel.hdaViews[ hda.id ] = hdaView;
+ hdaView.render().$el.hide().prependTo( $whereTo ).slideDown( panel.fxSpeed );
}
]);
},
@@ -796,21 +808,19 @@
*/
createHdaView : function( hda ){
var hdaId = hda.get( 'id' ),
- expanded = this.storage.get( 'expandedHdas' )[ hdaId ],
hdaView = new this.HDAViewClass({
- model : hda,
- linkTarget : this.linkTarget,
- expanded : expanded,
- //draggable : true,
- tagsEditorShown : this.preferences.get( 'tagsEditorShown' ),
- annotationEditorShown : this.preferences.get( 'annotationEditorShown' ),
- selectable : this.selecting,
- hasUser : this.model.ownedByCurrUser(),
- logger : this.logger
- });
+ model : hda,
+ linkTarget : this.linkTarget,
+ expanded : this.storage.get( 'expandedHdas' )[ hdaId ],
+ //draggable : true,
+ selectable : this.selecting,
+ hasUser : this.model.ownedByCurrUser(),
+ logger : this.logger,
+ tagsEditorShown : this.preferences.get( 'tagsEditorShown' ),
+ annotationEditorShown : this.preferences.get( 'annotationEditorShown' )
+ });
this._setUpHdaListeners( hdaView );
- this.hdaViews[ hdaId ] = hdaView;
- return hdaView.render();
+ return hdaView;
},
/** Set up HistoryPanel listeners for HDAView events. Currently binds:
@@ -826,6 +836,17 @@
hdaView.on( 'body-collapsed', function( id ){
historyView.storage.removeExpandedHda( id );
});
+ // maintain a list of hdas that are selected
+ hdaView.on( 'selected', function( hdaView ){
+ var id = hdaView.model.get( 'id' );
+ historyView.selectedHdaIds = _.union( historyView.selectedHdaIds, [ id ] );
+ //console.debug( 'selected', historyView.selectedHdaIds );
+ });
+ hdaView.on( 'de-selected', function( hdaView ){
+ var id = hdaView.model.get( 'id' );
+ historyView.selectedHdaIds = _.without( historyView.selectedHdaIds, id );
+ //console.debug( 'de-selected', historyView.selectedHdaIds );
+ });
//TODO: remove?
hdaView.on( 'error', function( model, xhr, options, msg ){
historyView.errorHandler( model, xhr, options, msg );
@@ -876,8 +897,8 @@
*/
renderHdas : function( $whereTo ){
$whereTo = $whereTo || this.$el;
- this.hdaViews = {};
var historyView = this,
+ newHdaViews = {},
$datasetsList = $whereTo.find( this.datasetsSelector ),
// only render the shown hdas
//TODO: switch to more general filtered pattern
@@ -892,7 +913,13 @@
if( visibleHdas.length ){
visibleHdas.each( function( hda ){
// render it (NOTE: reverse order, newest on top (prepend))
- $datasetsList.prepend( historyView.createHdaView( hda ).$el );
+ var hdaId = hda.get( 'id' ),
+ hdaView = historyView.createHdaView( hda );
+ newHdaViews[ hdaId ] = hdaView;
+ if( _.contains( historyView.selectedHdaIds, hdaId ) ){
+ hdaView.selected = true;
+ }
+ $datasetsList.prepend( hdaView.render().$el );
});
$whereTo.find( this.emptyMsgSelector ).hide();
@@ -900,6 +927,7 @@
//console.debug( 'emptyMsg:', $whereTo.find( this.emptyMsgSelector ) )
$whereTo.find( this.emptyMsgSelector ).show();
}
+ this.hdaViews = newHdaViews;
return this.hdaViews;
},
@@ -932,7 +960,9 @@
'click .history-search-btn' : 'toggleSearchControls',
'click .history-select-btn' : function( e ){ this.toggleSelectors( this.fxSpeed ); },
- 'click .history-select-all-datasets-btn' : 'selectAllDatasets'
+
+ 'click .history-select-all-datasets-btn' : 'selectAllDatasets',
+ 'click .history-deselect-all-datasets-btn' : 'deselectAllDatasets'
},
/** Update the history size display (curr. upper right of panel).
@@ -1070,6 +1100,7 @@
_.each( this.hdaViews, function( view ){
view.showSelector( speed );
});
+ this.selectedHdaIds = [];
},
hideSelectors : function( speed ){
@@ -1078,6 +1109,7 @@
_.each( this.hdaViews, function( view ){
view.hideSelector( speed );
});
+ this.selectedHdaIds = [];
},
toggleSelectors : function( speed ){
@@ -1089,22 +1121,15 @@
},
selectAllDatasets : function( event ){
- var $selectBtn = this.$el.find( '.history-select-all-datasets-btn' );
- currMode = $selectBtn.data( 'mode' );
- if( currMode === 'select' ){
- _.each( this.hdaViews, function( view ){
- view.select( event );
- });
- $selectBtn.data( 'mode', 'deselect' );
- $selectBtn.text( _l( 'De-select all' ) );
+ _.each( this.hdaViews, function( view ){
+ view.select( event );
+ });
+ },
- } else if( currMode === 'deselect' ){
- _.each( this.hdaViews, function( view ){
- view.deselect( event );
- });
- $selectBtn.data( 'mode', 'select' );
- $selectBtn.text( _l( 'Select all' ) );
- }
+ deselectAllDatasets : function( event ){
+ _.each( this.hdaViews, function( view ){
+ view.deselect( event );
+ });
},
getSelectedHdaViews : function(){
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 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 @@
-define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.linkTarget=c.linkTarget||"_blank";this.selectable=c.selectable||false;this.selected=c.selected||false;this.expanded=c.expanded||false;this.draggable=c.draggable||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(e){e=(e===undefined)?(true):(e);var c=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var d=this._buildNewRender();if(e){$(c).queue(function(f){this.$el.fadeOut(c.fxSpeed,f)})}$(c).queue(function(f){this.$el.empty().attr("class",c.className).addClass("state-"+c.model.get("state")).append(d.children());if(this.selectable){this.showSelector(0)}f()});if(e){$(c).queue(function(f){this.$el.fadeIn(c.fxSpeed,f)})}$(c).queue(function(f){this.trigger("rendered",c);if(this.model.inReadyState()){this.trigger("rendered:ready",c)}if(this.draggable){this.draggableOn()}f()});return this},_buildNewRender:function(){var c=$(a.templates.skeleton(this.model.toJSON()));c.find(".dataset-primary-actions").append(this._render_titleButtons());c.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(c);return c},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var d={target:this.linkTarget,classes:"dataset-display"};if(this.model.get("purged")){d.disabled=true;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.disabled=true;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.onclick=function(){if(Galaxy.frame&&Galaxy.frame.active){Galaxy.frame.add({title:"Data Viewer: "+c.model.get("name"),type:"url",content:c.urls.display})}}}}d.faIcon="fa-eye";return faIconButton(d)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var d=this.urls,e=this.model.get("meta_files");if(_.isEmpty(e)){return $(['<a href="'+d.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var f="dataset-"+this.model.get("id")+"-popup",c=['<div popupmenu="'+f+'">','<a href="'+d.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(e,function(g){return['<a class="action-button" href="',d.meta_download+g.file_type,'">',_l("Download")," ",g.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+d.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+f+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(c)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),classes:"dataset-params-btn",href:this.urls.show_params,target:this.linkTarget,faIcon:"fa-info-circle"})},_render_body:function(){var d=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),c=this["_render_body_"+this.model.get("state")];if(_.isFunction(c)){d=c.call(this)}this._setUpBehaviors(d);if(this.expanded){d.show()}return d},_render_stateBodyHelper:function(c,f){f=f||[];var d=this,e=$(a.templates.body(_.extend(this.model.toJSON(),{body:c})));e.find(".dataset-actions .left").append(_.map(f,function(g){return g.call(d)}));return e},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var c=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){c="<div>"+this.model.get("misc_blurb")+"</div>"+c}return this._render_stateBodyHelper(c,[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var c=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),d=this._render_body_ok();d.prepend(c);return d},_render_body_ok:function(){var c=this,e=$(a.templates.body(this.model.toJSON())),d=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);e.find(".dataset-actions .left").append(_.map(d,function(f){return f.call(c)}));if(this.model.isDeletedOrPurged()){return e}return e},events:{"click .dataset-title-bar":"toggleBodyVisibility","keydown .dataset-title-bar":"toggleBodyVisibility","click .dataset-selector":"toggleSelect",},toggleBodyVisibility:function(f,d){var c=32,e=13;if(f&&(f.type==="keydown")&&!(f.keyCode===c||f.keyCode===e)){return true}var g=this.$el.find(".dataset-body");d=(d===undefined)?(!g.is(":visible")):(d);if(d){this.expandBody()}else{this.collapseBody()}return false},expandBody:function(){var c=this;function d(){c.$el.children(".dataset-body").replaceWith(c._render_body());c.$el.children(".dataset-body").slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(e){d()})}else{d()}},collapseBody:function(){var c=this;this.$el.children(".dataset-body").slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},showSelector:function(e){if(this.$el.find(".dataset-selector").css("display")!=="none"){return}e=(e!==undefined)?(e):(this.fxSpeed);if(this.selected){this.select(null,true)}var d=this,c=32;if(e){this.$el.queue("fx",function(f){$(this).find(".dataset-primary-actions").fadeOut(e,f)});this.$el.queue("fx",function(f){$(this).find(".dataset-selector").show().animate({width:c},e,f);$(this).find(".dataset-title-bar").animate({"margin-left":c},e,f);d.selectable=true;d.trigger("selectable",true,d)})}else{this.$el.find(".dataset-primary-actions").hide();this.$el.find(".dataset-selector").show().css({width:c});this.$el.find(".dataset-title-bar").show().css({"margin-left":c});d.selectable=true;d.trigger("selectable",true,d)}},hideSelector:function(c){c=(c!==undefined)?(c):(this.fxSpeed);this.selectable=false;this.trigger("selectable",false,this);if(c){this.$el.queue("fx",function(d){$(this).find(".dataset-title-bar").show().css({"margin-left":"0"});$(this).find(".dataset-selector").animate({width:"0px"},c,function(){$(this).hide();d()})});this.$el.queue("fx",function(d){$(this).find(".dataset-primary-actions").fadeIn(c,d)})}else{$(this).find(".dataset-selector").css({width:"0px"}).hide();$(this).find(".dataset-primary-actions").show()}},toggleSelector:function(c){if(!this.$el.find(".dataset-selector").is(":visible")){this.showSelector(c)}else{this.hideSelector(c)}},select:function(c){this.$el.find(".dataset-selector span").removeClass("fa-square-o").addClass("fa-check-square-o");if(!this.selected){this.trigger("selected",this);this.selected=true}return false},deselect:function(c){this.$el.find(".dataset-selector span").removeClass("fa-check-square-o").addClass("fa-square-o");if(this.selected){this.trigger("de-selected",this);this.selected=false}return false},toggleSelect:function(c){if(this.selected){this.deselect(c)}else{this.select(c)}},draggableOn:function(){this.draggable=true;this.dragStartHandler=_.bind(this._dragStartHandler,this);this.dragEndHandler=_.bind(this._dragEndHandler,this);var c=this.$el.find(".dataset-title-bar").attr("draggable",true).get(0);c.addEventListener("dragstart",this.dragStartHandler,false);c.addEventListener("dragend",this.dragEndHandler,false)},draggableOff:function(){this.draggable=false;var c=this.$el.find(".dataset-title-bar").attr("draggable",false).get(0);c.removeEventListener("dragstart",this.dragStartHandler,false);c.removeEventListener("dragend",this.dragEndHandler,false)},toggleDraggable:function(){if(this.draggable){this.draggableOff()}else{this.draggableOn()}},_dragStartHandler:function(c){this.trigger("dragstart",this);c.dataTransfer.effectAllowed="move";c.dataTransfer.setData("text",JSON.stringify(this.model.toJSON()));return false},_dragEndHandler:function(c){this.trigger("dragend",this);return false},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={skeleton:Handlebars.templates["template-hda-skeleton"],body:Handlebars.templates["template-hda-body"]};return{HDABaseView:a}});
\ No newline at end of file
+define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.linkTarget=c.linkTarget||"_blank";this.selectable=c.selectable||false;this.selected=c.selected||false;this.expanded=c.expanded||false;this.draggable=c.draggable||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(e){e=(e===undefined)?(true):(e);var c=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var d=this._buildNewRender();if(e){$(c).queue(function(f){this.$el.fadeOut(c.fxSpeed,f)})}$(c).queue(function(f){this.$el.empty().attr("class",c.className).addClass("state-"+c.model.get("state")).append(d.children());if(this.selectable){this.showSelector(0)}f()});if(e){$(c).queue(function(f){this.$el.fadeIn(c.fxSpeed,f)})}$(c).queue(function(f){this.trigger("rendered",c);if(this.model.inReadyState()){this.trigger("rendered:ready",c)}if(this.draggable){this.draggableOn()}f()});return this},_buildNewRender:function(){var c=$(a.templates.skeleton(this.model.toJSON()));c.find(".dataset-primary-actions").append(this._render_titleButtons());c.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(c);return c},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var d={target:this.linkTarget,classes:"dataset-display"};if(this.model.get("purged")){d.disabled=true;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.disabled=true;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.onclick=function(){if(Galaxy.frame&&Galaxy.frame.active){Galaxy.frame.add({title:"Data Viewer: "+c.model.get("name"),type:"url",content:c.urls.display})}}}}d.faIcon="fa-eye";return faIconButton(d)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var d=this.urls,e=this.model.get("meta_files");if(_.isEmpty(e)){return $(['<a href="'+d.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var f="dataset-"+this.model.get("id")+"-popup",c=['<div popupmenu="'+f+'">','<a href="'+d.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(e,function(g){return['<a class="action-button" href="',d.meta_download+g.file_type,'">',_l("Download")," ",g.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+d.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+f+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(c)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),classes:"dataset-params-btn",href:this.urls.show_params,target:this.linkTarget,faIcon:"fa-info-circle"})},_render_body:function(){var d=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),c=this["_render_body_"+this.model.get("state")];if(_.isFunction(c)){d=c.call(this)}this._setUpBehaviors(d);if(this.expanded){d.show()}return d},_render_stateBodyHelper:function(c,f){f=f||[];var d=this,e=$(a.templates.body(_.extend(this.model.toJSON(),{body:c})));e.find(".dataset-actions .left").append(_.map(f,function(g){return g.call(d)}));return e},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var c=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){c="<div>"+this.model.get("misc_blurb")+"</div>"+c}return this._render_stateBodyHelper(c,[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var c=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),d=this._render_body_ok();d.prepend(c);return d},_render_body_ok:function(){var c=this,e=$(a.templates.body(this.model.toJSON())),d=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);e.find(".dataset-actions .left").append(_.map(d,function(f){return f.call(c)}));if(this.model.isDeletedOrPurged()){return e}return e},events:{"click .dataset-title-bar":"toggleBodyVisibility","keydown .dataset-title-bar":"toggleBodyVisibility","click .dataset-selector":"toggleSelect"},toggleBodyVisibility:function(f,d){var c=32,e=13;if(f&&(f.type==="keydown")&&!(f.keyCode===c||f.keyCode===e)){return true}var g=this.$el.find(".dataset-body");d=(d===undefined)?(!g.is(":visible")):(d);if(d){this.expandBody()}else{this.collapseBody()}return false},expandBody:function(){var c=this;function d(){c.$el.children(".dataset-body").replaceWith(c._render_body());c.$el.children(".dataset-body").slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(e){d()})}else{d()}},collapseBody:function(){var c=this;this.$el.children(".dataset-body").slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},showSelector:function(e){e=(e!==undefined)?(e):(this.fxSpeed);if(this.selected){this.select(null,true)}var d=this,c=32;if(e){this.$el.queue("fx",function(f){$(this).find(".dataset-primary-actions").fadeOut(e,f)});this.$el.queue("fx",function(f){$(this).find(".dataset-selector").show().animate({width:c},e,f);$(this).find(".dataset-title-bar").animate({"margin-left":c},e,f);d.selectable=true;d.trigger("selectable",true,d)})}else{this.$el.find(".dataset-primary-actions").hide();this.$el.find(".dataset-selector").show().css({width:c});this.$el.find(".dataset-title-bar").show().css({"margin-left":c});d.selectable=true;d.trigger("selectable",true,d)}},hideSelector:function(c){c=(c!==undefined)?(c):(this.fxSpeed);this.selectable=false;this.trigger("selectable",false,this);if(c){this.$el.queue("fx",function(d){$(this).find(".dataset-title-bar").show().css({"margin-left":"0"});$(this).find(".dataset-selector").animate({width:"0px"},c,function(){$(this).hide();d()})});this.$el.queue("fx",function(d){$(this).find(".dataset-primary-actions").fadeIn(c,d)})}else{$(this).find(".dataset-selector").css({width:"0px"}).hide();$(this).find(".dataset-primary-actions").show()}},toggleSelector:function(c){if(!this.$el.find(".dataset-selector").is(":visible")){this.showSelector(c)}else{this.hideSelector(c)}},select:function(c){this.$el.find(".dataset-selector span").removeClass("fa-square-o").addClass("fa-check-square-o");if(!this.selected){this.trigger("selected",this);this.selected=true}return false},deselect:function(c){this.$el.find(".dataset-selector span").removeClass("fa-check-square-o").addClass("fa-square-o");if(this.selected){this.trigger("de-selected",this);this.selected=false}return false},toggleSelect:function(c){if(this.selected){this.deselect(c)}else{this.select(c)}},draggableOn:function(){this.draggable=true;this.dragStartHandler=_.bind(this._dragStartHandler,this);this.dragEndHandler=_.bind(this._dragEndHandler,this);var c=this.$el.find(".dataset-title-bar").attr("draggable",true).get(0);c.addEventListener("dragstart",this.dragStartHandler,false);c.addEventListener("dragend",this.dragEndHandler,false)},draggableOff:function(){this.draggable=false;var c=this.$el.find(".dataset-title-bar").attr("draggable",false).get(0);c.removeEventListener("dragstart",this.dragStartHandler,false);c.removeEventListener("dragend",this.dragEndHandler,false)},toggleDraggable:function(){if(this.draggable){this.draggableOff()}else{this.draggableOn()}},_dragStartHandler:function(c){this.trigger("dragstart",this);c.dataTransfer.effectAllowed="move";c.dataTransfer.setData("text",JSON.stringify(this.model.toJSON()));return false},_dragEndHandler:function(c){this.trigger("dragend",this);return false},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={skeleton:Handlebars.templates["template-hda-skeleton"],body:Handlebars.templates["template-hda-body"]};return{HDABaseView:a}});
\ No newline at end of file
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 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 @@
-define(["mvc/history/history-model","mvc/dataset/hda-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(c,f,a,i){var g=SessionStorageModel.extend({defaults:{searching:false,tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});g.storageKey=function h(){return("history-panel")};var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(j){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([j],[true])))},removeExpandedHda:function(j){this.save("expandedHdas",_.omit(this.get("expandedHdas"),j))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function b(j){if(!j){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+j)}return("history:"+j)};var e=Backbone.View.extend(LoggableMixin).extend({defaultHDAViewClass:i.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",emptyMsgSelector:".empty-history-message",msgsSelector:".message-container",initialize:function(j){j=j||{};if(j.logger){this.logger=j.logger}this.log(this+".initialize:",j);this.HDAViewClass=j.HDAViewClass||this.defaultHDAViewClass;this.linkTarget=j.linkTarget||"_blank";this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.preferences=new g(_.extend({id:g.storageKey()},_.pick(j,_.keys(g.prototype.defaults))));this.filters=[];this.selecting=j.selecting||false;this.annotationEditorShown=j.annotationEditorShown||false;this._setUpListeners();if(this.model){this._setUpWebStorage(j.initiallyExpanded,j.show_deleted,j.show_hidden);this._setUpModelEventHandlers()}if(j.onready){j.onready.call(this)}},_setUpListeners:function(){this.on("error",function(k,n,j,m,l){this.errorHandler(k,n,j,m,l)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...")});this.on("loading-done",function(){this.hideLoadingIndicator()});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(j){this.log(this+"",arguments)},this)}},errorHandler:function(l,o,k,n,m){var j=this._parseErrorMessage(l,o,k,n,m);if(o&&o.status===0&&o.readyState===0){}else{if(o&&o.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",j.message,j.details)})}else{this.displayMessage("error",j.message,j.details)}}}},_parseErrorMessage:function(m,q,l,p,o){var k=Galaxy.currUser,j={message:this._bePolite(p),details:{user:(k instanceof User)?(k.toJSON()):(k+""),source:(m instanceof Backbone.Model)?(m.toJSON()):(m+""),xhr:q,options:(q)?(_.omit(l,"xhr")):(l)}};_.extend(j.details,o||{});if(q&&_.isFunction(q.getAllResponseHeaders)){var n=q.getAllResponseHeaders();n=_.compact(n.split("\n"));n=_.map(n,function(r){return r.split(": ")});j.details.xhr.responseHeaders=_.object(n)}return j},_bePolite:function(j){j=j||_l("An error occurred while getting updates from the server");return j+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadCurrentHistory:function(k){var j=this;return this.loadHistoryWithHDADetails("current",k).then(function(m,l){j.trigger("current-history",j)})},switchToHistory:function(m,l){var j=this,k=function(){return jQuery.post(galaxy_config.root+"api/histories/"+m+"/set_as_current")};return this.loadHistoryWithHDADetails(m,l,k).then(function(o,n){j.trigger("switched-history",j)})},createNewHistory:function(l){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var j=this,k=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,l,k).then(function(n,m){j.trigger("new-history",j)})},loadHistoryWithHDADetails:function(m,l,k,o){var j=this,n=function(p){return j.getExpandedHdaIds(p.id)};return this.loadHistory(m,l,k,o,n)},loadHistory:function(m,l,k,p,n){this.trigger("loading-history",this);l=l||{};var j=this;var o=c.History.getHistoryData(m,{historyFn:k,hdaFn:p,hdaDetailIds:l.initiallyExpanded||n});return this._loadHistoryFromXHR(o,l).fail(function(s,q,r){j.trigger("error",j,s,l,_l("An error was encountered while "+q),{historyId:m,history:r||{}})}).always(function(){j.trigger("loading-done",j)})},_loadHistoryFromXHR:function(l,k){var j=this;l.then(function(m,n){j.setModel(m,n,k)});l.fail(function(n,m){j.render()});return l},setModel:function(l,j,k){k=k||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){l.user=Galaxy.currUser.toJSON()}this.model=new c.History(l,j,k);this._setUpWebStorage(k.initiallyExpanded,k.show_deleted,k.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(k,j,l){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(k)){this.storage.set("exandedHdas",k)}if(_.isBoolean(j)){this.storage.set("show_deleted",j)}if(_.isBoolean(l)){this.storage.set("show_hidden",l)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var j in sessionStorage){if(j.indexOf("history:")===0){sessionStorage.removeItem(j)}}},getStoredOptions:function(k){if(!k||k==="current"){return(this.storage)?(this.storage.get()):({})}var j=sessionStorage.getItem(d.historyStorageKey(k));return(j===null)?({}):(JSON.parse(j))},getExpandedHdaIds:function(j){var k=this.getStoredOptions(j).expandedHdas;return((_.isEmpty(k))?([]):(_.keys(k)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(k,m,j,l){this.errorHandler(k,m,j,l)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(j){this.model.fetch()},this);this.model.hdas.on("state:ready",function(k,l,j){if((!k.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[k.id])}},this)},render:function(l,m){l=(l===undefined)?(this.fxSpeed):(l);var j=this,k;if(this.model){k=this.renderModel()}else{k=this.renderWithoutModel()}$(j).queue("fx",[function(n){if(l&&j.$el.is(":visible")){j.$el.fadeOut(l,n)}else{n()}},function(n){j.$el.empty();if(k){j.$el.append(k.children());j.renderBasedOnPrefs()}n()},function(n){if(l&&!j.$el.is(":visible")){j.$el.fadeIn(l,n)}else{n()}},function(n){if(m){m.call(this)}j.trigger("rendered",this);n()}]);return this},renderWithoutModel:function(){var j=$("<div/>"),k=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return j.append(k)},renderModel:function(){var j=$("<div/>");if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){j.append(e.templates.anonHistoryPanel(this.model.toJSON()))}else{j.append(e.templates.historyPanel(this.model.toJSON()));if(Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(j);this._renderAnnotation(j)}}j.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(j);this.renderHdas(j);return j},renderBasedOnPrefs:function(){if(this.preferences.get("searching")){this.showSearchControls(0)}},_renderTags:function(j){var k=this;this.tagsEditor=new TagsEditor({model:this.model,el:j.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){k.preferences.set("tagsEditorShown",true);k.toggleHDATagEditors(true,k.fxSpeed)},onhide:function(){k.preferences.set("tagsEditorShown",false);k.toggleHDATagEditors(false,k.fxSpeed)},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(j.find(".history-secondary-actions"))});if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}},_renderAnnotation:function(j){var k=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:j.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){k.preferences.set("annotationEditorShown",true);k.toggleHDAAnnotationEditors(true,k.fxSpeed)},onhide:function(){k.preferences.set("annotationEditorShown",false);k.toggleHDAAnnotationEditors(false,k.fxSpeed)},$activator:faIconButton({title:_l("Edit history Annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(j.find(".history-secondary-actions"))});if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}},_renderSearchButton:function(j){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_renderSelectButton:function(j){return faIconButton({title:_l("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(j){j=j||this.$el;j.find("[title]").tooltip({placement:"bottom"});if((!this.model)||(!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var k=this;j.find(".history-name").attr("title",_l("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(l){var m=k.model.get("name");if(l&&l!==m){k.$el.find(".history-name").text(l);k.model.save({name:l}).fail(function(){k.$el.find(".history-name").text(k.model.previous("name"))})}else{k.$el.find(".history-name").text(m)}}});this._setUpDatasetActionsPopup(j)},_setUpDatasetActionsPopup:function(j){var k=this;(new PopupMenu(j.find(".history-dataset-action-popup-btn"),[{html:_l("Hide datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype.hide;k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Unhide datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype.unhide;k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Delete datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype["delete"];k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Undelete datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype.undelete;k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Permanently delete datasets"),func:function(){if(confirm(_l("This will permanently remove the data in your datasets. Are you sure?"))){var l=f.HistoryDatasetAssociation.prototype.purge;k.getSelectedHdaCollection().ajaxQueue(l)}}}]))},refreshHdas:function(k,j){if(this.model){return this.model.refresh(k,j)}return $.when()},addHdaView:function(m){this.log("add."+this,m);var k=this;if(!m.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function l(o){var n=k.$el.find(k.emptyMsgSelector);if(n.is(":visible")){n.fadeOut(k.fxSpeed,o)}else{o()}},function j(o){k.scrollToTop();var n=k.$el.find(k.datasetsSelector);k.createHdaView(m).$el.hide().prependTo(n).slideDown(k.fxSpeed)}])},createHdaView:function(l){var k=l.get("id"),j=this.storage.get("expandedHdas")[k],m=new this.HDAViewClass({model:l,linkTarget:this.linkTarget,expanded:j,tagsEditorShown:this.preferences.get("tagsEditorShown"),annotationEditorShown:this.preferences.get("annotationEditorShown"),selectable:this.selecting,hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(m);this.hdaViews[k]=m;return m.render()},_setUpHdaListeners:function(k){var j=this;k.on("body-expanded",function(l){j.storage.addExpandedHda(l)});k.on("body-collapsed",function(l){j.storage.removeExpandedHda(l)});k.on("error",function(m,o,l,n){j.errorHandler(m,o,l,n)})},handleHdaDeletionChange:function(j){if(j.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[j.id])}},handleHdaVisibleChange:function(j){if(j.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[j.id])}},removeHdaView:function(k){if(!k){return}var j=this;k.$el.fadeOut(j.fxSpeed,function(){k.off();k.remove();delete j.hdaViews[k.model.id];if(_.isEmpty(j.hdaViews)){j.$el.find(j.emptyMsgSelector).fadeIn(j.fxSpeed,function(){j.trigger("empty-history",j)})}})},renderHdas:function(l){l=l||this.$el;this.hdaViews={};var k=this,j=l.find(this.datasetsSelector),m=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);j.empty();if(m.length){m.each(function(n){j.prepend(k.createHdaView(n).$el)});l.find(this.emptyMsgSelector).hide()}else{l.find(this.emptyMsgSelector).show()}return this.hdaViews},toggleHDATagEditors:function(j){var k=arguments;_.each(this.hdaViews,function(l){if(l.tagsEditor){l.tagsEditor.toggle.apply(l.tagsEditor,k)}})},toggleHDAAnnotationEditors:function(j){var k=arguments;_.each(this.hdaViews,function(l){if(l.annotationEditor){l.annotationEditor.toggle.apply(l.annotationEditor,k)}})},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls","click .history-select-btn":function(j){this.toggleSelectors(this.fxSpeed)},"click .history-select-all-datasets-btn":"selectAllDatasets"},updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(j){j.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(k){var l=this,o=".history-search-input";function n(p){l.searchFor=p;l.filters=[function(q){return q.matchesAll(l.searchFor)}];l.trigger("search:searching",p,l);l.renderHdas()}function j(p){if(l.model.hdas.haveDetails()){n(p);return}l.$el.find(o).searchInput("toggle-loading");l.model.hdas.fetchAllDetails({silent:true}).always(function(){l.$el.find(o).searchInput("toggle-loading")}).done(function(){n(p)})}function m(){l.searchFor="";l.filters=[];l.trigger("search:clear",l);l.renderHdas()}k.searchInput({initialVal:l.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:j,onsearch:n,onclear:m});return k},showSearchControls:function(l){l=(l===undefined)?(this.fxSpeed):(l);var j=this,k=this.$el.find(".history-search-controls"),m=k.find(".history-search-input");if(!m.children().size()){this.setUpSearchInput(m)}k.slideDown(l,function(){$(this).find("input").focus();j.preferences.set("searching",true)})},hideSearchControls:function(){speed=(speed===undefined)?(this.fxSpeed):(speed);var j=this;this.$el.find(".history-search-controls").slideUp(speed,function(){j.preferences.set("searching",false)})},toggleSearchControls:function(j){speed=(jQuery.type(j)==="number")?(j):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},showSelectors:function(j){this.selecting=true;this.$el.find(".history-dataset-actions").slideDown(j);_.each(this.hdaViews,function(k){k.showSelector(j)})},hideSelectors:function(j){this.selecting=false;this.$el.find(".history-dataset-actions").slideUp(j);_.each(this.hdaViews,function(k){k.hideSelector(j)})},toggleSelectors:function(j){if(!this.selecting){this.showSelectors(j)}else{this.hideSelectors(j)}},selectAllDatasets:function(k){var j=this.$el.find(".history-select-all-datasets-btn");currMode=j.data("mode");if(currMode==="select"){_.each(this.hdaViews,function(l){l.select(k)});j.data("mode","deselect");j.text(_l("De-select all"))}else{if(currMode==="deselect"){_.each(this.hdaViews,function(l){l.deselect(k)});j.data("mode","select");j.text(_l("Select all"))}}},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(j){return j.selected})},getSelectedHdaCollection:function(){return new f.HDACollection(_.map(this.getSelectedHdaViews(),function(j){return j.model}),{historyId:this.model.id})},showLoadingIndicator:function(k,j,l){j=(j!==undefined)?(j):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,l)}else{this.$el.fadeOut(j);this.indicator.show(k,j,l)}},hideLoadingIndicator:function(j,k){j=(j!==undefined)?(j):(this.fxSpeed);if(this.indicator){this.indicator.hide(j,k)}},displayMessage:function(o,p,n){var l=this;this.scrollToTop();var m=this.$el.find(this.msgsSelector),j=$("<div/>").addClass(o+"message").html(p);if(!_.isEmpty(n)){var k=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(l.messageToModalOptions(o,p,n));return false});j.append(" ",k)}return m.html(j)},messageToModalOptions:function(n,p,m){var j=this,o=$("<div/>"),l={title:"Details"};function k(q){q=_.omit(q,_.functions(q));return["<table>",_.map(q,function(s,r){s=(_.isObject(s))?(k(s)):(s);return'<tr><td style="vertical-align: top; color: grey">'+r+'</td><td style="padding-left: 8px">'+s+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(m)){l.body=o.append(k(m))}else{l.body=o.html(m)}l.buttons={Ok:function(){Galaxy.modal.hide();j.clearMessages()}};return l},clearMessages:function(){var j=this.$el.find(this.msgsSelector);j.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(j){this.$el.parent().scrollTop(j)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(k,l){if(!l){this.$el.parent().parent().scrollTop(k);return this}var j=window,m=this.$el.parent().parent(),o=$(j).innerHeight(),n=(o/2)-(l/2);$(m).scrollTop(k-n);return this},scrollToId:function(k){if((!k)||(!this.hdaViews[k])){return this}var j=this.hdaViews[k].$el;this.scrollIntoView(j.offset().top,j.outerHeight());return this},scrollToHid:function(j){var k=this.model.hdas.getByHid(j);if(!k){return this}return this.scrollToId(k.id)},connectToQuotaMeter:function(j){if(!j){return this}this.listenTo(j,"quota:over",this.showQuotaMessage);this.listenTo(j,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(j&&j.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var j=this.$el.find(".quota-message");if(j.is(":hidden")){j.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var j=this.$el.find(".quota-message");if(!j.is(":hidden")){j.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(j){if(!j){return this}this.on("new-storage",function(l,k){if(j&&l){j.findItemByHtml(_l("Include Deleted Datasets")).checked=l.get("show_deleted");j.findItemByHtml(_l("Include Hidden Datasets")).checked=l.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});e.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:e}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/dataset/hda-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(c,f,a,i){var g=SessionStorageModel.extend({defaults:{searching:false,tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});g.storageKey=function h(){return("history-panel")};var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(j){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([j],[true])))},removeExpandedHda:function(j){this.save("expandedHdas",_.omit(this.get("expandedHdas"),j))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function b(j){if(!j){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+j)}return("history:"+j)};var e=Backbone.View.extend(LoggableMixin).extend({defaultHDAViewClass:i.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",emptyMsgSelector:".empty-history-message",msgsSelector:".message-container",initialize:function(j){j=j||{};if(j.logger){this.logger=j.logger}this.log(this+".initialize:",j);this.HDAViewClass=j.HDAViewClass||this.defaultHDAViewClass;this.linkTarget=j.linkTarget||"_blank";this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.preferences=new g(_.extend({id:g.storageKey()},_.pick(j,_.keys(g.prototype.defaults))));this.filters=[];this.selectedHdaIds=[];this.selecting=j.selecting||false;this.annotationEditorShown=j.annotationEditorShown||false;this.tagsEditorShown=j.tagsEditorShown||false;this._setUpListeners();if(this.model){this._setUpWebStorage(j.initiallyExpanded,j.show_deleted,j.show_hidden);this._setUpModelEventHandlers()}if(j.onready){j.onready.call(this)}},_setUpListeners:function(){this.on("error",function(k,n,j,m,l){this.errorHandler(k,n,j,m,l)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this.hideLoadingIndicator(40)});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(j){this.log(this+"",arguments)},this)}},errorHandler:function(l,o,k,n,m){var j=this._parseErrorMessage(l,o,k,n,m);if(o&&o.status===0&&o.readyState===0){}else{if(o&&o.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",j.message,j.details)})}else{this.displayMessage("error",j.message,j.details)}}}},_parseErrorMessage:function(m,q,l,p,o){var k=Galaxy.currUser,j={message:this._bePolite(p),details:{user:(k instanceof User)?(k.toJSON()):(k+""),source:(m instanceof Backbone.Model)?(m.toJSON()):(m+""),xhr:q,options:(q)?(_.omit(l,"xhr")):(l)}};_.extend(j.details,o||{});if(q&&_.isFunction(q.getAllResponseHeaders)){var n=q.getAllResponseHeaders();n=_.compact(n.split("\n"));n=_.map(n,function(r){return r.split(": ")});j.details.xhr.responseHeaders=_.object(n)}return j},_bePolite:function(j){j=j||_l("An error occurred while getting updates from the server");return j+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadCurrentHistory:function(k){var j=this;return this.loadHistoryWithHDADetails("current",k).then(function(m,l){j.trigger("current-history",j)})},switchToHistory:function(m,l){var j=this,k=function(){return jQuery.post(galaxy_config.root+"api/histories/"+m+"/set_as_current")};return this.loadHistoryWithHDADetails(m,l,k).then(function(o,n){j.trigger("switched-history",j)})},createNewHistory:function(l){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var j=this,k=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,l,k).then(function(n,m){j.trigger("new-history",j)})},loadHistoryWithHDADetails:function(m,l,k,o){var j=this,n=function(p){return j.getExpandedHdaIds(p.id)};return this.loadHistory(m,l,k,o,n)},loadHistory:function(m,l,k,p,n){this.trigger("loading-history",this);l=l||{};var j=this;var o=c.History.getHistoryData(m,{historyFn:k,hdaFn:p,hdaDetailIds:l.initiallyExpanded||n});return this._loadHistoryFromXHR(o,l).fail(function(s,q,r){j.trigger("error",j,s,l,_l("An error was encountered while "+q),{historyId:m,history:r||{}})}).always(function(){j.trigger("loading-done",j)})},_loadHistoryFromXHR:function(l,k){var j=this;l.then(function(m,n){j.setModel(m,n,k)});l.fail(function(n,m){j.render()});return l},setModel:function(l,j,k){k=k||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){l.user=Galaxy.currUser.toJSON()}this.model=new c.History(l,j,k);this._setUpWebStorage(k.initiallyExpanded,k.show_deleted,k.show_hidden);this._setUpModelEventHandlers();this.selectedHdaIds=[];this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(k,j,l){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(k)){this.storage.set("exandedHdas",k)}if(_.isBoolean(j)){this.storage.set("show_deleted",j)}if(_.isBoolean(l)){this.storage.set("show_hidden",l)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var j in sessionStorage){if(j.indexOf("history:")===0){sessionStorage.removeItem(j)}}},getStoredOptions:function(k){if(!k||k==="current"){return(this.storage)?(this.storage.get()):({})}var j=sessionStorage.getItem(d.historyStorageKey(k));return(j===null)?({}):(JSON.parse(j))},getExpandedHdaIds:function(j){var k=this.getStoredOptions(j).expandedHdas;return((_.isEmpty(k))?([]):(_.keys(k)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(k,m,j,l){this.errorHandler(k,m,j,l)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(j){this.model.fetch()},this);this.model.hdas.on("state:ready",function(k,l,j){if((!k.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[k.id])}},this)},render:function(l,m){l=(l===undefined)?(this.fxSpeed):(l);var j=this,k;if(this.model){k=this.renderModel()}else{k=this.renderWithoutModel()}$(j).queue("fx",[function(n){if(l&&j.$el.is(":visible")){j.$el.fadeOut(l,n)}else{n()}},function(n){j.$el.empty();if(k){j.$el.append(k.children());j.renderBasedOnPrefs()}n()},function(n){if(l&&!j.$el.is(":visible")){j.$el.fadeIn(l,n)}else{n()}},function(n){if(m){m.call(this)}j.trigger("rendered",this);n()}]);return this},renderWithoutModel:function(){var j=$("<div/>"),k=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return j.append(k)},renderModel:function(){var j=$("<div/>");if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){j.append(e.templates.anonHistoryPanel(this.model.toJSON()))}else{j.append(e.templates.historyPanel(this.model.toJSON()));if(Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(j);this._renderAnnotation(j)}}j.find(".history-secondary-actions").prepend(this._renderSelectButton());j.find(".history-dataset-actions").toggle(this.selecting);j.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(j);this.renderHdas(j);return j},renderBasedOnPrefs:function(){if(this.preferences.get("searching")){this.showSearchControls(0)}},_renderTags:function(j){var k=this;this.tagsEditor=new TagsEditor({model:this.model,el:j.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){k.preferences.set("tagsEditorShown",true);k.toggleHDATagEditors(true,k.fxSpeed)},onhide:function(){k.preferences.set("tagsEditorShown",false);k.toggleHDATagEditors(false,k.fxSpeed)},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(j.find(".history-secondary-actions"))});if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}},_renderAnnotation:function(j){var k=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:j.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){k.preferences.set("annotationEditorShown",true);k.toggleHDAAnnotationEditors(true,k.fxSpeed)},onhide:function(){k.preferences.set("annotationEditorShown",false);k.toggleHDAAnnotationEditors(false,k.fxSpeed)},$activator:faIconButton({title:_l("Edit history Annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(j.find(".history-secondary-actions"))});if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}},_renderSearchButton:function(j){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_renderSelectButton:function(j){return faIconButton({title:_l("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(j){j=j||this.$el;j.find("[title]").tooltip({placement:"bottom"});if(!this.model){return}this._setUpDatasetActionsPopup(j);if((!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var k=this;j.find(".history-name").attr("title",_l("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(l){var m=k.model.get("name");if(l&&l!==m){k.$el.find(".history-name").text(l);k.model.save({name:l}).fail(function(){k.$el.find(".history-name").text(k.model.previous("name"))})}else{k.$el.find(".history-name").text(m)}}})},_setUpDatasetActionsPopup:function(j){var k=this;(new PopupMenu(j.find(".history-dataset-action-popup-btn"),[{html:_l("Hide datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype.hide;k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Unhide datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype.unhide;k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Delete datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype["delete"];k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Undelete datasets"),func:function(){var l=f.HistoryDatasetAssociation.prototype.undelete;k.getSelectedHdaCollection().ajaxQueue(l)}},{html:_l("Permanently delete datasets"),func:function(){if(confirm(_l("This will permanently remove the data in your datasets. Are you sure?"))){var l=f.HistoryDatasetAssociation.prototype.purge;k.getSelectedHdaCollection().ajaxQueue(l)}}}]))},refreshHdas:function(k,j){if(this.model){return this.model.refresh(k,j)}return $.when()},addHdaView:function(m){this.log("add."+this,m);var k=this;if(!m.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function l(o){var n=k.$el.find(k.emptyMsgSelector);if(n.is(":visible")){n.fadeOut(k.fxSpeed,o)}else{o()}},function j(o){k.scrollToTop();var n=k.$el.find(k.datasetsSelector),p=k.createHdaView(m);k.hdaViews[m.id]=p;p.render().$el.hide().prependTo(n).slideDown(k.fxSpeed)}])},createHdaView:function(k){var j=k.get("id"),l=new this.HDAViewClass({model:k,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[j],selectable:this.selecting,hasUser:this.model.ownedByCurrUser(),logger:this.logger,tagsEditorShown:this.preferences.get("tagsEditorShown"),annotationEditorShown:this.preferences.get("annotationEditorShown")});this._setUpHdaListeners(l);return l},_setUpHdaListeners:function(k){var j=this;k.on("body-expanded",function(l){j.storage.addExpandedHda(l)});k.on("body-collapsed",function(l){j.storage.removeExpandedHda(l)});k.on("selected",function(l){var m=l.model.get("id");j.selectedHdaIds=_.union(j.selectedHdaIds,[m])});k.on("de-selected",function(l){var m=l.model.get("id");j.selectedHdaIds=_.without(j.selectedHdaIds,m)});k.on("error",function(m,o,l,n){j.errorHandler(m,o,l,n)})},handleHdaDeletionChange:function(j){if(j.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[j.id])}},handleHdaVisibleChange:function(j){if(j.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[j.id])}},removeHdaView:function(k){if(!k){return}var j=this;k.$el.fadeOut(j.fxSpeed,function(){k.off();k.remove();delete j.hdaViews[k.model.id];if(_.isEmpty(j.hdaViews)){j.$el.find(j.emptyMsgSelector).fadeIn(j.fxSpeed,function(){j.trigger("empty-history",j)})}})},renderHdas:function(l){l=l||this.$el;var k=this,n={},j=l.find(this.datasetsSelector),m=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);j.empty();if(m.length){m.each(function(p){var o=p.get("id"),q=k.createHdaView(p);n[o]=q;if(_.contains(k.selectedHdaIds,o)){q.selected=true}j.prepend(q.render().$el)});l.find(this.emptyMsgSelector).hide()}else{l.find(this.emptyMsgSelector).show()}this.hdaViews=n;return this.hdaViews},toggleHDATagEditors:function(j){var k=arguments;_.each(this.hdaViews,function(l){if(l.tagsEditor){l.tagsEditor.toggle.apply(l.tagsEditor,k)}})},toggleHDAAnnotationEditors:function(j){var k=arguments;_.each(this.hdaViews,function(l){if(l.annotationEditor){l.annotationEditor.toggle.apply(l.annotationEditor,k)}})},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls","click .history-select-btn":function(j){this.toggleSelectors(this.fxSpeed)},"click .history-select-all-datasets-btn":"selectAllDatasets","click .history-deselect-all-datasets-btn":"deselectAllDatasets"},updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(j){j.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(k){var l=this,o=".history-search-input";function n(p){l.searchFor=p;l.filters=[function(q){return q.matchesAll(l.searchFor)}];l.trigger("search:searching",p,l);l.renderHdas()}function j(p){if(l.model.hdas.haveDetails()){n(p);return}l.$el.find(o).searchInput("toggle-loading");l.model.hdas.fetchAllDetails({silent:true}).always(function(){l.$el.find(o).searchInput("toggle-loading")}).done(function(){n(p)})}function m(){l.searchFor="";l.filters=[];l.trigger("search:clear",l);l.renderHdas()}k.searchInput({initialVal:l.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:j,onsearch:n,onclear:m});return k},showSearchControls:function(l){l=(l===undefined)?(this.fxSpeed):(l);var j=this,k=this.$el.find(".history-search-controls"),m=k.find(".history-search-input");if(!m.children().size()){this.setUpSearchInput(m)}k.slideDown(l,function(){$(this).find("input").focus();j.preferences.set("searching",true)})},hideSearchControls:function(){speed=(speed===undefined)?(this.fxSpeed):(speed);var j=this;this.$el.find(".history-search-controls").slideUp(speed,function(){j.preferences.set("searching",false)})},toggleSearchControls:function(j){speed=(jQuery.type(j)==="number")?(j):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},showSelectors:function(j){this.selecting=true;this.$el.find(".history-dataset-actions").slideDown(j);_.each(this.hdaViews,function(k){k.showSelector(j)});this.selectedHdaIds=[]},hideSelectors:function(j){this.selecting=false;this.$el.find(".history-dataset-actions").slideUp(j);_.each(this.hdaViews,function(k){k.hideSelector(j)});this.selectedHdaIds=[]},toggleSelectors:function(j){if(!this.selecting){this.showSelectors(j)}else{this.hideSelectors(j)}},selectAllDatasets:function(j){_.each(this.hdaViews,function(k){k.select(j)})},deselectAllDatasets:function(j){_.each(this.hdaViews,function(k){k.deselect(j)})},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(j){return j.selected})},getSelectedHdaCollection:function(){return new f.HDACollection(_.map(this.getSelectedHdaViews(),function(j){return j.model}),{historyId:this.model.id})},showLoadingIndicator:function(k,j,l){j=(j!==undefined)?(j):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,l)}else{this.$el.fadeOut(j);this.indicator.show(k,j,l)}},hideLoadingIndicator:function(j,k){j=(j!==undefined)?(j):(this.fxSpeed);if(this.indicator){this.indicator.hide(j,k)}},displayMessage:function(o,p,n){var l=this;this.scrollToTop();var m=this.$el.find(this.msgsSelector),j=$("<div/>").addClass(o+"message").html(p);if(!_.isEmpty(n)){var k=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(l.messageToModalOptions(o,p,n));return false});j.append(" ",k)}return m.html(j)},messageToModalOptions:function(n,p,m){var j=this,o=$("<div/>"),l={title:"Details"};function k(q){q=_.omit(q,_.functions(q));return["<table>",_.map(q,function(s,r){s=(_.isObject(s))?(k(s)):(s);return'<tr><td style="vertical-align: top; color: grey">'+r+'</td><td style="padding-left: 8px">'+s+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(m)){l.body=o.append(k(m))}else{l.body=o.html(m)}l.buttons={Ok:function(){Galaxy.modal.hide();j.clearMessages()}};return l},clearMessages:function(){var j=this.$el.find(this.msgsSelector);j.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(j){this.$el.parent().scrollTop(j)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(k,l){if(!l){this.$el.parent().parent().scrollTop(k);return this}var j=window,m=this.$el.parent().parent(),o=$(j).innerHeight(),n=(o/2)-(l/2);$(m).scrollTop(k-n);return this},scrollToId:function(k){if((!k)||(!this.hdaViews[k])){return this}var j=this.hdaViews[k].$el;this.scrollIntoView(j.offset().top,j.outerHeight());return this},scrollToHid:function(j){var k=this.model.hdas.getByHid(j);if(!k){return this}return this.scrollToId(k.id)},connectToQuotaMeter:function(j){if(!j){return this}this.listenTo(j,"quota:over",this.showQuotaMessage);this.listenTo(j,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(j&&j.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var j=this.$el.find(".quota-message");if(j.is(":hidden")){j.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var j=this.$el.find(".quota-message");if(!j.is(":hidden")){j.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(j){if(!j){return this}this.on("new-storage",function(l,k){if(j&&l){j.findItemByHtml(_l("Include Deleted Datasets")).checked=l.get("show_deleted");j.findItemByHtml(_l("Include Hidden Datasets")).checked=l.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});e.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:e}});
\ No newline at end of file
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/scripts/packed/templates/compiled/history-templates.js
--- a/static/scripts/packed/templates/compiled/history-templates.js
+++ b/static/scripts/packed/templates/compiled/history-templates.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-body"]=b(function(g,r,p,k,z){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);z=z||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';if(B=p.body){B=B.call(D,{hash:{},data:C})}else{B=D.body;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+='\n </div>\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';return A}function m(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';B=p["if"].call(D,D.misc_blurb,{hash:{},inverse:o.noop,fn:o.program(4,l,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.data_type,{hash:{},inverse:o.noop,fn:o.program(6,j,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.metadata_dbkey,{hash:{},inverse:o.noop,fn:o.program(9,f,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.misc_info,{hash:{},inverse:o.noop,fn:o.program(12,x,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';B=p.unless.call(D,D.deleted,{hash:{},inverse:o.noop,fn:o.program(14,w,C),data:C});if(B||B===0){A+=B}A+="\n\n ";return A}function l(D,C){var A="",B;A+='\n <div class="dataset-blurb">\n <span class="value">';if(B=p.misc_blurb){B=B.call(D,{hash:{},data:C})}else{B=D.misc_blurb;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function j(E,D){var A="",C,B;A+='\n <div class="dataset-datatype">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(7,i,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">';if(C=p.data_type){C=C.call(E,{hash:{},data:D})}else{C=E.data_type;C=typeof C===e?C.apply(E):C}A+=d(C)+"</span>\n </div>\n ";return A}function i(B,A){return"format"}function f(E,D){var A="",C,B;A+='\n <div class="dataset-dbkey">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(10,y,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">\n ';if(C=p.metadata_dbkey){C=C.call(E,{hash:{},data:D})}else{C=E.metadata_dbkey;C=typeof C===e?C.apply(E):C}A+=d(C)+"\n </span>\n </div>\n ";return A}function y(B,A){return"database"}function x(D,C){var A="",B;A+='\n <div class="dataset-info">\n <span class="value">';if(B=p.misc_info){B=B.call(D,{hash:{},data:C})}else{B=D.misc_info;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function w(D,C){var A="",B;A+='\n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="dataset-display-applications">\n ';B=p.each.call(D,D.display_apps,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p.each.call(D,D.display_types,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-peek">\n ';B=p["if"].call(D,D.peek,{hash:{},inverse:o.noop,fn:o.program(19,s,C),data:C});if(B||B===0){A+=B}A+="\n </div>\n\n ";return A}function v(D,C){var A="",B;A+='\n <div class="display-application">\n <span class="display-application-location">';if(B=p.label){B=B.call(D,{hash:{},data:C})}else{B=D.label;B=typeof B===e?B.apply(D):B}A+=d(B)+'</span>\n <span class="display-application-links">\n ';B=p.each.call(D,D.links,{hash:{},inverse:o.noop,fn:o.program(16,u,C),data:C});if(B||B===0){A+=B}A+="\n </span>\n </div>\n ";return A}function u(E,D){var A="",C,B;A+='\n <a target="';if(C=p.target){C=C.call(E,{hash:{},data:D})}else{C=E.target;C=typeof C===e?C.apply(E):C}A+=d(C)+'" href="';if(C=p.href){C=C.call(E,{hash:{},data:D})}else{C=E.href;C=typeof C===e?C.apply(E):C}A+=d(C)+'">';B={hash:{},inverse:o.noop,fn:o.program(17,t,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+="</a>\n ";return A}function t(C,B){var A;if(A=p.text){A=A.call(C,{hash:{},data:B})}else{A=C.text;A=typeof A===e?A.apply(C):A}return d(A)}function s(D,C){var A="",B;A+='\n <pre class="peek">';if(B=p.peek){B=B.call(D,{hash:{},data:C})}else{B=D.peek;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+="</pre>\n ";return A}q+='<div class="dataset-body">\n ';h=p["if"].call(r,r.body,{hash:{},inverse:o.program(3,m,z),fn:o.program(1,n,z),data:z});if(h||h===0){q+=h}q+="\n</div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-skeleton"]=b(function(f,r,p,k,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,f.helpers);w=w||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var x="",z,y;x+='\n <div class="errormessagesmall">\n ';y={hash:{},inverse:o.noop,fn:o.program(2,m,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+=":\n ";y={hash:{},inverse:o.noop,fn:o.program(4,l,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </div>\n ";return x}function m(y,x){return"There was an error getting the data for this dataset"}function l(z,y){var x;if(x=p.error){x=x.call(z,{hash:{},data:y})}else{x=z.error;x=typeof x===e?x.apply(z):x}return d(x)}function j(A,z){var x="",y;x+="\n ";y=p["if"].call(A,A.purged,{hash:{},inverse:o.program(10,v,z),fn:o.program(7,i,z),data:z});if(y||y===0){x+=y}x+="\n ";return x}function i(B,A){var x="",z,y;x+='\n <div class="dataset-purged-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(8,g,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n\n ";return x}function g(y,x){return"This dataset has been deleted and removed from disk."}function v(B,A){var x="",z,y;x+='\n <div class="dataset-deleted-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(11,u,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n ";return x}function u(y,x){return"This dataset has been deleted."}function t(B,A){var x="",z,y;x+='\n <div class="dataset-hidden-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(14,s,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n ";return x}function s(y,x){return"This dataset has been hidden."}q+='<div class="dataset hda">\n <div class="dataset-warnings">\n ';h=p["if"].call(r,r.error,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(6,j,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p.unless.call(r,r.visible,{hash:{},inverse:o.noop,fn:o.program(13,t,w),data:w});if(h||h===0){q+=h}q+='\n </div>\n\n <div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>\n <div class="dataset-primary-actions"></div>\n \n <div class="dataset-title-bar clear" tabindex="0">\n <span class="dataset-state-icon state-icon"></span>\n <div class="dataset-title">\n <span class="hda-hid">';if(h=p.hid){h=h.call(r,{hash:{},data:w})}else{h=r.hid;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n <span class="dataset-name">';if(h=p.name){h=h.call(r,{hash:{},data:w})}else{h=r.name;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n </div>\n </div>\n\n <div class="dataset-body"></div>\n</div>';return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(h,r,p,l,t){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,h.helpers);t=t||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(x,w){var u="",v;u+='\n <div class="history-name">\n ';if(v=p.name){v=v.call(x,{hash:{},data:w})}else{v=x.name;v=typeof v===e?v.apply(x):v}u+=d(v)+"\n </div>\n ";return u}function m(x,w){var u="",v;u+='\n <div class="history-size">';if(v=p.nice_size){v=v.call(x,{hash:{},data:w})}else{v=x.nice_size;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function k(x,w){var u="",v;u+='\n \n <div class="';if(v=p.status){v=v.call(x,{hash:{},data:w})}else{v=x.status;v=typeof v===e?v.apply(x):v}u+=d(v)+'message">';if(v=p.message){v=v.call(x,{hash:{},data:w})}else{v=x.message;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function j(v,u){return"You are over your disk quota"}function g(v,u){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function s(v,u){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,t),data:t});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(5,k,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(7,j,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(9,g,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(11,s,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(h,r,p,l,t){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,h.helpers);t=t||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(x,w){var u="",v;u+='\n <div class="history-name">\n ';if(v=p.name){v=v.call(x,{hash:{},data:w})}else{v=x.name;v=typeof v===e?v.apply(x):v}u+=d(v)+"\n </div>\n ";return u}function m(x,w){var u="",v;u+='\n <div class="history-size">';if(v=p.nice_size){v=v.call(x,{hash:{},data:w})}else{v=x.nice_size;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function k(x,w){var u="",v;u+='\n \n <div class="';if(v=p.status){v=v.call(x,{hash:{},data:w})}else{v=x.status;v=typeof v===e?v.apply(x):v}u+=d(v)+'message">';if(v=p.message){v=v.call(x,{hash:{},data:w})}else{v=x.message;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function j(v,u){return"You are over your disk quota"}function g(v,u){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function s(v,u){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,t),data:t});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(5,k,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(7,j,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(9,g,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(11,s,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(g,r,p,l,x){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);x=x||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var y="",z;y+='\n <div class="history-name">\n ';if(z=p.name){z=z.call(B,{hash:{},data:A})}else{z=B.name;z=typeof z===e?z.apply(B):z}y+=d(z)+"\n </div>\n ";return y}function m(B,A){var y="",z;y+='\n <div class="history-size">';if(z=p.nice_size){z=z.call(B,{hash:{},data:A})}else{z=B.nice_size;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function k(C,B){var y="",A,z;y+='\n <div class="warningmessagesmall"><strong>\n ';z={hash:{},inverse:o.noop,fn:o.program(6,j,B),data:B};if(A=p.local){A=A.call(C,z)}else{A=C.local;A=typeof A===e?A.apply(C):A}if(!p.local){A=c.call(C,A,z)}if(A||A===0){y+=A}y+="\n </strong></div>\n ";return y}function j(z,y){return"You are currently viewing a deleted history!"}function h(B,A){var y="",z;y+='\n \n <div class="';if(z=p.status){z=z.call(B,{hash:{},data:A})}else{z=B.status;z=typeof z===e?z.apply(B):z}y+=d(z)+'message">';if(z=p.message){z=z.call(B,{hash:{},data:A})}else{z=B.message;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function w(z,y){return"You are over your disk quota"}function v(z,y){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function u(z,y){return"Select all"}function t(z,y){return"For all selected"}function s(z,y){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n ';i=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(5,k,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(8,h,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(10,w,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(12,v,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(14,u,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:o.noop,fn:o.program(16,t,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(18,s,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(g,r,p,l,x){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);x=x||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var y="",z;y+='\n <div class="history-name">\n ';if(z=p.name){z=z.call(B,{hash:{},data:A})}else{z=B.name;z=typeof z===e?z.apply(B):z}y+=d(z)+"\n </div>\n ";return y}function m(B,A){var y="",z;y+='\n <div class="history-size">';if(z=p.nice_size){z=z.call(B,{hash:{},data:A})}else{z=B.nice_size;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function k(C,B){var y="",A,z;y+='\n <div class="warningmessagesmall"><strong>\n ';z={hash:{},inverse:o.noop,fn:o.program(6,j,B),data:B};if(A=p.local){A=A.call(C,z)}else{A=C.local;A=typeof A===e?A.apply(C):A}if(!p.local){A=c.call(C,A,z)}if(A||A===0){y+=A}y+="\n </strong></div>\n ";return y}function j(z,y){return"You are currently viewing a deleted history!"}function h(B,A){var y="",z;y+='\n \n <div class="';if(z=p.status){z=z.call(B,{hash:{},data:A})}else{z=B.status;z=typeof z===e?z.apply(B):z}y+=d(z)+'message">';if(z=p.message){z=z.call(B,{hash:{},data:A})}else{z=B.message;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function w(z,y){return"You are over your disk quota"}function v(z,y){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function u(z,y){return"Select all"}function t(z,y){return"For all selected"}function s(z,y){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n ';i=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(5,k,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(8,h,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(10,w,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(12,v,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(14,u,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:o.noop,fn:o.program(16,t,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(18,s,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-body"]=b(function(g,r,p,k,z){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);z=z||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';if(B=p.body){B=B.call(D,{hash:{},data:C})}else{B=D.body;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+='\n </div>\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';return A}function m(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';B=p["if"].call(D,D.misc_blurb,{hash:{},inverse:o.noop,fn:o.program(4,l,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.data_type,{hash:{},inverse:o.noop,fn:o.program(6,j,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.metadata_dbkey,{hash:{},inverse:o.noop,fn:o.program(9,f,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.misc_info,{hash:{},inverse:o.noop,fn:o.program(12,x,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';B=p.unless.call(D,D.deleted,{hash:{},inverse:o.noop,fn:o.program(14,w,C),data:C});if(B||B===0){A+=B}A+="\n\n ";return A}function l(D,C){var A="",B;A+='\n <div class="dataset-blurb">\n <span class="value">';if(B=p.misc_blurb){B=B.call(D,{hash:{},data:C})}else{B=D.misc_blurb;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function j(E,D){var A="",C,B;A+='\n <div class="dataset-datatype">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(7,i,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">';if(C=p.data_type){C=C.call(E,{hash:{},data:D})}else{C=E.data_type;C=typeof C===e?C.apply(E):C}A+=d(C)+"</span>\n </div>\n ";return A}function i(B,A){return"format"}function f(E,D){var A="",C,B;A+='\n <div class="dataset-dbkey">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(10,y,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">\n ';if(C=p.metadata_dbkey){C=C.call(E,{hash:{},data:D})}else{C=E.metadata_dbkey;C=typeof C===e?C.apply(E):C}A+=d(C)+"\n </span>\n </div>\n ";return A}function y(B,A){return"database"}function x(D,C){var A="",B;A+='\n <div class="dataset-info">\n <span class="value">';if(B=p.misc_info){B=B.call(D,{hash:{},data:C})}else{B=D.misc_info;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function w(D,C){var A="",B;A+='\n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="dataset-display-applications">\n ';B=p.each.call(D,D.display_apps,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p.each.call(D,D.display_types,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-peek">\n ';B=p["if"].call(D,D.peek,{hash:{},inverse:o.noop,fn:o.program(19,s,C),data:C});if(B||B===0){A+=B}A+="\n </div>\n\n ";return A}function v(D,C){var A="",B;A+='\n <div class="display-application">\n <span class="display-application-location">';if(B=p.label){B=B.call(D,{hash:{},data:C})}else{B=D.label;B=typeof B===e?B.apply(D):B}A+=d(B)+'</span>\n <span class="display-application-links">\n ';B=p.each.call(D,D.links,{hash:{},inverse:o.noop,fn:o.program(16,u,C),data:C});if(B||B===0){A+=B}A+="\n </span>\n </div>\n ";return A}function u(E,D){var A="",C,B;A+='\n <a target="';if(C=p.target){C=C.call(E,{hash:{},data:D})}else{C=E.target;C=typeof C===e?C.apply(E):C}A+=d(C)+'" href="';if(C=p.href){C=C.call(E,{hash:{},data:D})}else{C=E.href;C=typeof C===e?C.apply(E):C}A+=d(C)+'">';B={hash:{},inverse:o.noop,fn:o.program(17,t,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+="</a>\n ";return A}function t(C,B){var A;if(A=p.text){A=A.call(C,{hash:{},data:B})}else{A=C.text;A=typeof A===e?A.apply(C):A}return d(A)}function s(D,C){var A="",B;A+='\n <pre class="peek">';if(B=p.peek){B=B.call(D,{hash:{},data:C})}else{B=D.peek;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+="</pre>\n ";return A}q+='<div class="dataset-body">\n ';h=p["if"].call(r,r.body,{hash:{},inverse:o.program(3,m,z),fn:o.program(1,n,z),data:z});if(h||h===0){q+=h}q+="\n</div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-skeleton"]=b(function(f,r,p,k,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,f.helpers);w=w||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var x="",z,y;x+='\n <div class="errormessagesmall">\n ';y={hash:{},inverse:o.noop,fn:o.program(2,m,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+=":\n ";y={hash:{},inverse:o.noop,fn:o.program(4,l,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </div>\n ";return x}function m(y,x){return"There was an error getting the data for this dataset"}function l(z,y){var x;if(x=p.error){x=x.call(z,{hash:{},data:y})}else{x=z.error;x=typeof x===e?x.apply(z):x}return d(x)}function j(A,z){var x="",y;x+="\n ";y=p["if"].call(A,A.purged,{hash:{},inverse:o.program(10,v,z),fn:o.program(7,i,z),data:z});if(y||y===0){x+=y}x+="\n ";return x}function i(B,A){var x="",z,y;x+='\n <div class="dataset-purged-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(8,g,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n\n ";return x}function g(y,x){return"This dataset has been deleted and removed from disk."}function v(B,A){var x="",z,y;x+='\n <div class="dataset-deleted-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(11,u,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n ";return x}function u(y,x){return"This dataset has been deleted."}function t(B,A){var x="",z,y;x+='\n <div class="dataset-hidden-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(14,s,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n ";return x}function s(y,x){return"This dataset has been hidden."}q+='<div class="dataset hda">\n <div class="dataset-warnings">\n ';h=p["if"].call(r,r.error,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(6,j,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p.unless.call(r,r.visible,{hash:{},inverse:o.noop,fn:o.program(13,t,w),data:w});if(h||h===0){q+=h}q+='\n </div>\n\n <div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>\n <div class="dataset-primary-actions"></div>\n \n <div class="dataset-title-bar clear" tabindex="0">\n <span class="dataset-state-icon state-icon"></span>\n <div class="dataset-title">\n <span class="hda-hid">';if(h=p.hid){h=h.call(r,{hash:{},data:w})}else{h=r.hid;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n <span class="dataset-name">';if(h=p.name){h=h.call(r,{hash:{},data:w})}else{h=r.name;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n </div>\n </div>\n\n <div class="dataset-body"></div>\n</div>';return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-skeleton"]=b(function(f,r,p,k,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,f.helpers);w=w||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var x="",z,y;x+='\n <div class="errormessagesmall">\n ';y={hash:{},inverse:o.noop,fn:o.program(2,m,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+=":\n ";y={hash:{},inverse:o.noop,fn:o.program(4,l,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </div>\n ";return x}function m(y,x){return"There was an error getting the data for this dataset"}function l(z,y){var x;if(x=p.error){x=x.call(z,{hash:{},data:y})}else{x=z.error;x=typeof x===e?x.apply(z):x}return d(x)}function j(A,z){var x="",y;x+="\n ";y=p["if"].call(A,A.purged,{hash:{},inverse:o.program(10,v,z),fn:o.program(7,i,z),data:z});if(y||y===0){x+=y}x+="\n ";return x}function i(B,A){var x="",z,y;x+='\n <div class="dataset-purged-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(8,g,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n\n ";return x}function g(y,x){return"This dataset has been deleted and removed from disk."}function v(B,A){var x="",z,y;x+='\n <div class="dataset-deleted-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(11,u,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n ";return x}function u(y,x){return"This dataset has been deleted."}function t(B,A){var x="",z,y;x+='\n <div class="dataset-hidden-msg warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(14,s,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n ";return x}function s(y,x){return"This dataset has been hidden."}q+='<div class="dataset hda">\n <div class="dataset-warnings">\n ';h=p["if"].call(r,r.error,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(6,j,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p.unless.call(r,r.visible,{hash:{},inverse:o.noop,fn:o.program(13,t,w),data:w});if(h||h===0){q+=h}q+='\n </div>\n\n <div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>\n <div class="dataset-primary-actions"></div>\n \n <div class="dataset-title-bar clear" tabindex="0">\n <span class="dataset-state-icon state-icon"></span>\n <div class="dataset-title">\n <span class="hda-hid">';if(h=p.hid){h=h.call(r,{hash:{},data:w})}else{h=r.hid;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n <span class="dataset-name">';if(h=p.name){h=h.call(r,{hash:{},data:w})}else{h=r.name;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n </div>\n </div>\n\n <div class="dataset-body"></div>\n</div>';return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(h,r,p,l,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,h.helpers);w=w||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(A,z){var x="",y;x+='\n <div class="history-name">\n ';if(y=p.name){y=y.call(A,{hash:{},data:z})}else{y=A.name;y=typeof y===e?y.apply(A):y}x+=d(y)+"\n </div>\n ";return x}function m(A,z){var x="",y;x+='\n <div class="history-size">';if(y=p.nice_size){y=y.call(A,{hash:{},data:z})}else{y=A.nice_size;y=typeof y===e?y.apply(A):y}x+=d(y)+"</div>\n ";return x}function k(A,z){var x="",y;x+='\n \n <div class="';if(y=p.status){y=y.call(A,{hash:{},data:z})}else{y=A.status;y=typeof y===e?y.apply(A):y}x+=d(y)+'message">';if(y=p.message){y=y.call(A,{hash:{},data:z})}else{y=A.message;y=typeof y===e?y.apply(A):y}x+=d(y)+"</div>\n ";return x}function j(y,x){return"You are over your disk quota"}function g(y,x){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function v(y,x){return"All"}function u(y,x){return"None"}function t(y,x){return"For all selected"}function s(y,x){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,w),data:w});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions btn-group"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(5,k,w),data:w});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(7,j,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(9,g,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n <div class="history-dataset-actions">\n <div class="btn-group">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(11,v,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n <button class="history-deselect-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(13,u,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n </div>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:o.noop,fn:o.program(15,t,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(17,s,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(g,s,q,m,y){this.compilerInfo=[4,">= 1.0.0"];q=this.merge(q,g.helpers);y=y||{};var r="",i,f,e="function",d=this.escapeExpression,p=this,c=q.blockHelperMissing;function o(C,B){var z="",A;z+='\n <div class="history-name">\n ';if(A=q.name){A=A.call(C,{hash:{},data:B})}else{A=C.name;A=typeof A===e?A.apply(C):A}z+=d(A)+"\n </div>\n ";return z}function n(C,B){var z="",A;z+='\n <div class="history-size">';if(A=q.nice_size){A=A.call(C,{hash:{},data:B})}else{A=C.nice_size;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function l(D,C){var z="",B,A;z+='\n <div class="warningmessagesmall"><strong>\n ';A={hash:{},inverse:p.noop,fn:p.program(6,k,C),data:C};if(B=q.local){B=B.call(D,A)}else{B=D.local;B=typeof B===e?B.apply(D):B}if(!q.local){B=c.call(D,B,A)}if(B||B===0){z+=B}z+="\n </strong></div>\n ";return z}function k(A,z){return"You are currently viewing a deleted history!"}function h(C,B){var z="",A;z+='\n \n <div class="';if(A=q.status){A=A.call(C,{hash:{},data:B})}else{A=C.status;A=typeof A===e?A.apply(C):A}z+=d(A)+'message">';if(A=q.message){A=A.call(C,{hash:{},data:B})}else{A=C.message;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function x(A,z){return"You are over your disk quota"}function w(A,z){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function v(A,z){return"All"}function u(A,z){return"None"}function t(A,z){return"For all selected"}function j(A,z){return"Your history is empty. Click 'Get Data' on the left pane to start"}r+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n ';i=q["if"].call(s,s.name,{hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=q["if"].call(s,s.nice_size,{hash:{},inverse:p.noop,fn:p.program(3,n,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="history-secondary-actions btn-group"></div>\n </div>\n\n ';i=q["if"].call(s,s.deleted,{hash:{},inverse:p.noop,fn:p.program(5,l,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="message-container">\n ';i=q["if"].call(s,s.message,{hash:{},inverse:p.noop,fn:p.program(8,h,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:p.noop,fn:p.program(10,x,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+=".\n ";f={hash:{},inverse:p.noop,fn:p.program(12,w,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <div class="btn-group">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:p.noop,fn:p.program(14,v,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='</button>\n <button class="history-deselect-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:p.noop,fn:p.program(16,u,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='</button>\n </div>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:p.noop,fn:p.program(18,t,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:p.noop,fn:p.program(20,j,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+="\n </div>";return r})})();
\ No newline at end of file
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/scripts/packed/templates/compiled/template-history-historyPanel-anon.js
--- a/static/scripts/packed/templates/compiled/template-history-historyPanel-anon.js
+++ b/static/scripts/packed/templates/compiled/template-history-historyPanel-anon.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(h,r,p,l,t){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,h.helpers);t=t||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(x,w){var u="",v;u+='\n <div class="history-name">\n ';if(v=p.name){v=v.call(x,{hash:{},data:w})}else{v=x.name;v=typeof v===e?v.apply(x):v}u+=d(v)+"\n </div>\n ";return u}function m(x,w){var u="",v;u+='\n <div class="history-size">';if(v=p.nice_size){v=v.call(x,{hash:{},data:w})}else{v=x.nice_size;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function k(x,w){var u="",v;u+='\n \n <div class="';if(v=p.status){v=v.call(x,{hash:{},data:w})}else{v=x.status;v=typeof v===e?v.apply(x):v}u+=d(v)+'message">';if(v=p.message){v=v.call(x,{hash:{},data:w})}else{v=x.message;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function j(v,u){return"You are over your disk quota"}function g(v,u){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function s(v,u){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,t),data:t});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(5,k,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(7,j,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(9,g,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(11,s,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(h,r,p,l,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,h.helpers);w=w||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(A,z){var x="",y;x+='\n <div class="history-name">\n ';if(y=p.name){y=y.call(A,{hash:{},data:z})}else{y=A.name;y=typeof y===e?y.apply(A):y}x+=d(y)+"\n </div>\n ";return x}function m(A,z){var x="",y;x+='\n <div class="history-size">';if(y=p.nice_size){y=y.call(A,{hash:{},data:z})}else{y=A.nice_size;y=typeof y===e?y.apply(A):y}x+=d(y)+"</div>\n ";return x}function k(A,z){var x="",y;x+='\n \n <div class="';if(y=p.status){y=y.call(A,{hash:{},data:z})}else{y=A.status;y=typeof y===e?y.apply(A):y}x+=d(y)+'message">';if(y=p.message){y=y.call(A,{hash:{},data:z})}else{y=A.message;y=typeof y===e?y.apply(A):y}x+=d(y)+"</div>\n ";return x}function j(y,x){return"You are over your disk quota"}function g(y,x){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function v(y,x){return"All"}function u(y,x){return"None"}function t(y,x){return"For all selected"}function s(y,x){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,w),data:w});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions btn-group"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(5,k,w),data:w});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(7,j,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(9,g,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n <div class="history-dataset-actions">\n <div class="btn-group">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(11,v,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n <button class="history-deselect-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(13,u,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n </div>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:o.noop,fn:o.program(15,t,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(17,s,w),data:w};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 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(g,r,p,l,x){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);x=x||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var y="",z;y+='\n <div class="history-name">\n ';if(z=p.name){z=z.call(B,{hash:{},data:A})}else{z=B.name;z=typeof z===e?z.apply(B):z}y+=d(z)+"\n </div>\n ";return y}function m(B,A){var y="",z;y+='\n <div class="history-size">';if(z=p.nice_size){z=z.call(B,{hash:{},data:A})}else{z=B.nice_size;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function k(C,B){var y="",A,z;y+='\n <div class="warningmessagesmall"><strong>\n ';z={hash:{},inverse:o.noop,fn:o.program(6,j,B),data:B};if(A=p.local){A=A.call(C,z)}else{A=C.local;A=typeof A===e?A.apply(C):A}if(!p.local){A=c.call(C,A,z)}if(A||A===0){y+=A}y+="\n </strong></div>\n ";return y}function j(z,y){return"You are currently viewing a deleted history!"}function h(B,A){var y="",z;y+='\n \n <div class="';if(z=p.status){z=z.call(B,{hash:{},data:A})}else{z=B.status;z=typeof z===e?z.apply(B):z}y+=d(z)+'message">';if(z=p.message){z=z.call(B,{hash:{},data:A})}else{z=B.message;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function w(z,y){return"You are over your disk quota"}function v(z,y){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function u(z,y){return"Select all"}function t(z,y){return"For all selected"}function s(z,y){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n ';i=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(5,k,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(8,h,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(10,w,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(12,v,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(14,u,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:o.noop,fn:o.program(16,t,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(18,s,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(g,s,q,m,y){this.compilerInfo=[4,">= 1.0.0"];q=this.merge(q,g.helpers);y=y||{};var r="",i,f,e="function",d=this.escapeExpression,p=this,c=q.blockHelperMissing;function o(C,B){var z="",A;z+='\n <div class="history-name">\n ';if(A=q.name){A=A.call(C,{hash:{},data:B})}else{A=C.name;A=typeof A===e?A.apply(C):A}z+=d(A)+"\n </div>\n ";return z}function n(C,B){var z="",A;z+='\n <div class="history-size">';if(A=q.nice_size){A=A.call(C,{hash:{},data:B})}else{A=C.nice_size;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function l(D,C){var z="",B,A;z+='\n <div class="warningmessagesmall"><strong>\n ';A={hash:{},inverse:p.noop,fn:p.program(6,k,C),data:C};if(B=q.local){B=B.call(D,A)}else{B=D.local;B=typeof B===e?B.apply(D):B}if(!q.local){B=c.call(D,B,A)}if(B||B===0){z+=B}z+="\n </strong></div>\n ";return z}function k(A,z){return"You are currently viewing a deleted history!"}function h(C,B){var z="",A;z+='\n \n <div class="';if(A=q.status){A=A.call(C,{hash:{},data:B})}else{A=C.status;A=typeof A===e?A.apply(C):A}z+=d(A)+'message">';if(A=q.message){A=A.call(C,{hash:{},data:B})}else{A=C.message;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function x(A,z){return"You are over your disk quota"}function w(A,z){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function v(A,z){return"All"}function u(A,z){return"None"}function t(A,z){return"For all selected"}function j(A,z){return"Your history is empty. Click 'Get Data' on the left pane to start"}r+='<div class="history-controls">\n <div class="history-search-controls">\n <div class="history-search-input"></div>\n </div>\n\n <div class="history-title">\n ';i=q["if"].call(s,s.name,{hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=q["if"].call(s,s.nice_size,{hash:{},inverse:p.noop,fn:p.program(3,n,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="history-secondary-actions btn-group"></div>\n </div>\n\n ';i=q["if"].call(s,s.deleted,{hash:{},inverse:p.noop,fn:p.program(5,l,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="message-container">\n ';i=q["if"].call(s,s.message,{hash:{},inverse:p.noop,fn:p.program(8,h,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:p.noop,fn:p.program(10,x,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+=".\n ";f={hash:{},inverse:p.noop,fn:p.program(12,w,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <div class="btn-group">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:p.noop,fn:p.program(14,v,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='</button>\n <button class="history-deselect-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:p.noop,fn:p.program(16,u,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='</button>\n </div>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:p.noop,fn:p.program(18,t,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:p.noop,fn:p.program(20,j,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+="\n </div>";return r})})();
\ No newline at end of file
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/scripts/templates/compiled/history-templates.js
--- a/static/scripts/templates/compiled/history-templates.js
+++ b/static/scripts/templates/compiled/history-templates.js
@@ -302,98 +302,125 @@
});
})();(function() {
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
-templates['template-history-historyPanel-anon'] = template(function (Handlebars,depth0,helpers,partials,data) {
+templates['template-hda-skeleton'] = template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
- var buffer = "", stack1, options, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
+ var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
function program1(depth0,data) {
- var buffer = "", stack1;
- buffer += "\n <div class=\"history-name\">\n ";
- if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "\n </div>\n ";
- return buffer;
- }
-
-function program3(depth0,data) {
-
- var buffer = "", stack1;
- buffer += "\n <div class=\"history-size\">";
- if (stack1 = helpers.nice_size) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.nice_size; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "</div>\n ";
- return buffer;
- }
-
-function program5(depth0,data) {
-
- var buffer = "", stack1;
- buffer += "\n "
- + "\n <div class=\"";
- if (stack1 = helpers.status) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.status; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "message\">";
- if (stack1 = helpers.message) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.message; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "</div>\n ";
- return buffer;
- }
-
-function program7(depth0,data) {
-
-
- return "You are over your disk quota";
- }
-
-function program9(depth0,data) {
-
-
- return "Tool execution is on hold until your disk usage drops below your allocated quota";
- }
-
-function program11(depth0,data) {
-
-
- return "Your history is empty. Click 'Get Data' on the left pane to start";
- }
-
- buffer += "<div class=\"history-controls\">\n <div class=\"history-search-controls\">\n <div class=\"history-search-input\"></div>\n </div>\n\n <div class=\"history-title\">\n "
- + "\n ";
- stack1 = helpers['if'].call(depth0, depth0.name, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n <div class=\"message-container\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data};
+ var buffer = "", stack1, options;
+ buffer += "\n <div class=\"errormessagesmall\">\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(9, program9, data),data:data};
+ buffer += ":\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n </div>\n\n </div>"
- + "\n\n "
- + "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
+ buffer += "\n </div>\n ";
+ return buffer;
+ }
+function program2(depth0,data) {
+
+
+ return "There was an error getting the data for this dataset";
+ }
+
+function program4(depth0,data) {
+
+ var stack1;
+ if (stack1 = helpers.error) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
+ else { stack1 = depth0.error; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ return escapeExpression(stack1);
+ }
+
+function program6(depth0,data) {
+
+ var buffer = "", stack1;
+ buffer += "\n ";
+ stack1 = helpers['if'].call(depth0, depth0.purged, {hash:{},inverse:self.program(10, program10, data),fn:self.program(7, program7, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ return buffer;
+ }
+function program7(depth0,data) {
+
+ var buffer = "", stack1, options;
+ buffer += "\n <div class=\"dataset-purged-msg warningmessagesmall\"><strong>\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </strong></div>\n\n ";
+ return buffer;
+ }
+function program8(depth0,data) {
+
+
+ return "This dataset has been deleted and removed from disk.";
+ }
+
+function program10(depth0,data) {
+
+ var buffer = "", stack1, options;
+ buffer += "\n <div class=\"dataset-deleted-msg warningmessagesmall\"><strong>\n ";
options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </div>";
+ buffer += "\n </strong></div>\n ";
+ return buffer;
+ }
+function program11(depth0,data) {
+
+
+ return "This dataset has been deleted.";
+ }
+
+function program13(depth0,data) {
+
+ var buffer = "", stack1, options;
+ buffer += "\n <div class=\"dataset-hidden-msg warningmessagesmall\"><strong>\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </strong></div>\n ";
+ return buffer;
+ }
+function program14(depth0,data) {
+
+
+ return "This dataset has been hidden.";
+ }
+
+ buffer += "<div class=\"dataset hda\">\n <div class=\"dataset-warnings\">\n ";
+ stack1 = helpers['if'].call(depth0, depth0.error, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n ";
+ stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n ";
+ stack1 = helpers.unless.call(depth0, depth0.visible, {hash:{},inverse:self.noop,fn:self.program(13, program13, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </div>\n\n <div class=\"dataset-selector\"><span class=\"fa fa-2x fa-square-o\"></span></div>\n <div class=\"dataset-primary-actions\"></div>\n "
+ + "\n <div class=\"dataset-title-bar clear\" tabindex=\"0\">\n <span class=\"dataset-state-icon state-icon\"></span>\n <div class=\"dataset-title\">\n <span class=\"hda-hid\">";
+ if (stack1 = helpers.hid) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
+ else { stack1 = depth0.hid; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ buffer += escapeExpression(stack1)
+ + "</span>\n <span class=\"dataset-name\">";
+ if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
+ else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ buffer += escapeExpression(stack1)
+ + "</span>\n </div>\n </div>\n\n <div class=\"dataset-body\"></div>\n</div>";
return buffer;
});
})();(function() {
@@ -456,6 +483,24 @@
function program11(depth0,data) {
+ return "All";
+ }
+
+function program13(depth0,data) {
+
+
+ return "None";
+ }
+
+function program15(depth0,data) {
+
+
+ return "For all selected";
+ }
+
+function program17(depth0,data) {
+
+
return "Your history is empty. Click 'Get Data' on the left pane to start";
}
@@ -466,7 +511,7 @@
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n <div class=\"message-container\">\n ";
+ buffer += "\n\n <div class=\"history-secondary-actions btn-group\"></div>\n </div>\n\n <div class=\"message-container\">\n ";
stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
@@ -481,10 +526,28 @@
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n </div>\n\n </div>"
+ buffer += ".\n </div>\n\n <div class=\"history-dataset-actions\">\n <div class=\"btn-group\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
+ options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</button>\n <button class=\"history-deselect-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
+ options = {hash:{},inverse:self.noop,fn:self.program(13, program13, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</button>\n </div>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
+ options = {hash:{},inverse:self.noop,fn:self.program(15, program15, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "...</button>\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(17, program17, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -570,16 +633,22 @@
function program14(depth0,data) {
- return "Select all";
+ return "All";
}
function program16(depth0,data) {
+ return "None";
+ }
+
+function program18(depth0,data) {
+
+
return "For all selected";
}
-function program18(depth0,data) {
+function program20(depth0,data) {
return "Your history is empty. Click 'Get Data' on the left pane to start";
@@ -591,7 +660,7 @@
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n ";
+ buffer += "\n\n <div class=\"history-secondary-actions btn-group\"></div>\n </div>\n\n ";
stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"message-container\">\n ";
@@ -609,162 +678,28 @@
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n </div>\n \n <div class=\"tags-display\"></div>\n <div class=\"annotation-display\"></div>\n\n <div class=\"history-dataset-actions\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
+ buffer += ".\n </div>\n \n <div class=\"tags-display\"></div>\n <div class=\"annotation-display\"></div>\n\n <div class=\"history-dataset-actions\">\n <div class=\"btn-group\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
options = {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "</button>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
+ buffer += "</button>\n <button class=\"history-deselect-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
options = {hash:{},inverse:self.noop,fn:self.program(16, program16, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</button>\n </div>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
+ options = {hash:{},inverse:self.noop,fn:self.program(18, program18, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "...</button>\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(18, program18, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </div>";
- return buffer;
- });
-})();(function() {
- var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
-templates['template-history-historyPanel'] = template(function (Handlebars,depth0,helpers,partials,data) {
- this.compilerInfo = [4,'>= 1.0.0'];
-helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
- var buffer = "", stack1, options, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
-
-function program1(depth0,data) {
-
- var buffer = "", stack1;
- buffer += "\n <div class=\"history-name\">\n ";
- if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "\n </div>\n ";
- return buffer;
- }
-
-function program3(depth0,data) {
-
- var buffer = "", stack1;
- buffer += "\n <div class=\"history-size\">";
- if (stack1 = helpers.nice_size) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.nice_size; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "</div>\n ";
- return buffer;
- }
-
-function program5(depth0,data) {
-
- var buffer = "", stack1, options;
- buffer += "\n <div class=\"warningmessagesmall\"><strong>\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </strong></div>\n ";
- return buffer;
- }
-function program6(depth0,data) {
-
-
- return "You are currently viewing a deleted history!";
- }
-
-function program8(depth0,data) {
-
- var buffer = "", stack1;
- buffer += "\n "
- + "\n <div class=\"";
- if (stack1 = helpers.status) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.status; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "message\">";
- if (stack1 = helpers.message) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
- else { stack1 = depth0.message; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- buffer += escapeExpression(stack1)
- + "</div>\n ";
- return buffer;
- }
-
-function program10(depth0,data) {
-
-
- return "You are over your disk quota";
- }
-
-function program12(depth0,data) {
-
-
- return "Tool execution is on hold until your disk usage drops below your allocated quota";
- }
-
-function program14(depth0,data) {
-
-
- return "Select all";
- }
-
-function program16(depth0,data) {
-
-
- return "For all selected";
- }
-
-function program18(depth0,data) {
-
-
- return "Your history is empty. Click 'Get Data' on the left pane to start";
- }
-
- buffer += "<div class=\"history-controls\">\n <div class=\"history-search-controls\">\n <div class=\"history-search-input\"></div>\n </div>\n\n <div class=\"history-title\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.name, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n ";
- stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n <div class=\"message-container\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data});
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(10, program10, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(12, program12, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n </div>\n \n <div class=\"tags-display\"></div>\n <div class=\"annotation-display\"></div>\n\n <div class=\"history-dataset-actions\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
- options = {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "</button>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
- options = {hash:{},inverse:self.noop,fn:self.program(16, program16, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "...</button>\n </div>\n\n </div>"
- + "\n\n "
- + "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(18, program18, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(20, program20, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/scripts/templates/compiled/template-history-historyPanel-anon.js
--- a/static/scripts/templates/compiled/template-history-historyPanel-anon.js
+++ b/static/scripts/templates/compiled/template-history-historyPanel-anon.js
@@ -58,6 +58,24 @@
function program11(depth0,data) {
+ return "All";
+ }
+
+function program13(depth0,data) {
+
+
+ return "None";
+ }
+
+function program15(depth0,data) {
+
+
+ return "For all selected";
+ }
+
+function program17(depth0,data) {
+
+
return "Your history is empty. Click 'Get Data' on the left pane to start";
}
@@ -68,7 +86,7 @@
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n <div class=\"message-container\">\n ";
+ buffer += "\n\n <div class=\"history-secondary-actions btn-group\"></div>\n </div>\n\n <div class=\"message-container\">\n ";
stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
@@ -83,10 +101,28 @@
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n </div>\n\n </div>"
+ buffer += ".\n </div>\n\n <div class=\"history-dataset-actions\">\n <div class=\"btn-group\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
+ options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</button>\n <button class=\"history-deselect-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
+ options = {hash:{},inverse:self.noop,fn:self.program(13, program13, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</button>\n </div>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
+ options = {hash:{},inverse:self.noop,fn:self.program(15, program15, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "...</button>\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(17, program17, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 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
@@ -76,16 +76,22 @@
function program14(depth0,data) {
- return "Select all";
+ return "All";
}
function program16(depth0,data) {
+ return "None";
+ }
+
+function program18(depth0,data) {
+
+
return "For all selected";
}
-function program18(depth0,data) {
+function program20(depth0,data) {
return "Your history is empty. Click 'Get Data' on the left pane to start";
@@ -97,7 +103,7 @@
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n ";
+ buffer += "\n\n <div class=\"history-secondary-actions btn-group\"></div>\n </div>\n\n ";
stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"message-container\">\n ";
@@ -115,22 +121,28 @@
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += ".\n </div>\n \n <div class=\"tags-display\"></div>\n <div class=\"annotation-display\"></div>\n\n <div class=\"history-dataset-actions\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
+ buffer += ".\n </div>\n \n <div class=\"tags-display\"></div>\n <div class=\"annotation-display\"></div>\n\n <div class=\"history-dataset-actions\">\n <div class=\"btn-group\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
options = {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "</button>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
+ buffer += "</button>\n <button class=\"history-deselect-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
options = {hash:{},inverse:self.noop,fn:self.program(16, program16, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</button>\n </div>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
+ options = {hash:{},inverse:self.noop,fn:self.program(18, program18, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "...</button>\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(18, program18, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(20, program20, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/scripts/templates/history-templates.html
--- a/static/scripts/templates/history-templates.html
+++ b/static/scripts/templates/history-templates.html
@@ -44,8 +44,12 @@
<div class="annotation-display"></div><div class="history-dataset-actions">
- <button class="history-select-all-datasets-btn btn btn-default"
- data-mode="select">{{#local}}Select all{{/local}}</button>
+ <div class="btn-group">
+ <button class="history-select-all-datasets-btn btn btn-default"
+ data-mode="select">{{#local}}All{{/local}}</button>
+ <button class="history-deselect-all-datasets-btn btn btn-default"
+ data-mode="select">{{#local}}None{{/local}}</button>
+ </div><button class="history-dataset-action-popup-btn btn btn-default"
>{{#local}}For all selected{{/local}}...</button></div>
@@ -98,6 +102,17 @@
{{#local}}Tool execution is on hold until your disk usage drops below your allocated quota{{/local}}.
</div>
+ <div class="history-dataset-actions">
+ <div class="btn-group">
+ <button class="history-select-all-datasets-btn btn btn-default"
+ data-mode="select">{{#local}}All{{/local}}</button>
+ <button class="history-deselect-all-datasets-btn btn btn-default"
+ data-mode="select">{{#local}}None{{/local}}</button>
+ </div>
+ <button class="history-dataset-action-popup-btn btn btn-default"
+ >{{#local}}For all selected{{/local}}...</button>
+ </div>
+
</div>{{! end history-controls }}
{{! where the datasets/hdas are added }}
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1577,7 +1577,7 @@
.workflow-invocation-complete{border:solid 1px #6A6;border-left-width:5px;margin:10px 0;padding-left:5px}
.icon-btn{display:inline-block;height:22px;width:22px;text-align:center;line-height:19px;font-size:1.2em;border-radius:3px;border:1px solid #bfbfbf;background-color:#f2f2f2;color:#333;cursor:pointer}
.icon-btn:hover{background-color:white;color:maroon}
-.icon-btn.disabled{background-color:transparent;color:#f2f2f2}
+.icon-btn.disabled{background-color:transparent;color:#bfbfbf}
.search-input .search-query{width:100%;padding-right:24px}
.search-input .search-clear,.search-input .search-loading{position:relative;display:inline-block;float:right;margin-top:-23px;margin-right:4px;font-size:1.4em;line-height:23px;color:grey}
.search-input .search-clear:hover{color:#303030}
@@ -1594,7 +1594,7 @@
.history-panel .dataset .dataset-primary-actions .icon-btn:first-child{margin-right:0px;border-top-left-radius:3px;border-bottom-left-radius:3px}
.history-panel .dataset .dataset-primary-actions .icon-btn:last-child{margin-left:0px;border-radius:0px 3px 3px 0px}
.history-panel .dataset .dataset-primary-actions .icon-btn{margin-left:2px}
-.history-panel .dataset .dataset-body{display:none;padding:6px 10px 6px 8px}.history-panel .dataset .dataset-body [class$=messagesmall]{margin:0px 0px 8px 0px}
+.history-panel .dataset .dataset-body{display:none;padding:0 10px 6px 8px}.history-panel .dataset .dataset-body [class$=messagesmall]{margin:0px 0px 8px 0px}
.history-panel .dataset .dataset-body label{margin:0px;padding:0px;font-weight:normal}
.history-panel .dataset .dataset-body .prompt{font-weight:normal;color:#555}
.history-panel .dataset .dataset-body .prompt:after{content:':'}
diff -r 1dc6776635ee359f32e8c661f549d2db8c06f16d -r 7ca065784d58e7aa77e5092952eacd963853df65 static/style/src/less/history.less
--- a/static/style/src/less/history.less
+++ b/static/style/src/less/history.less
@@ -57,9 +57,10 @@
}
.icon-btn.disabled {
background-color: transparent;
- color: @icon-btn-bg;
+ color: @icon-btn-border;
}
+// ---------------------------------------------------------------------------- search bar
.search-input {
.search-query {
width : 100%;
@@ -84,6 +85,7 @@
color : @link-color;
}
}
+
// ---------------------------------------------------------------------------- panel header buttons
#history-refresh-button,
#history-options-button {
@@ -177,7 +179,8 @@
.dataset-body {
display: none;
// background-color: fadeout( white, 70% );
- .dataset-padding;
+ //.dataset-padding;
+ padding: 0px @spacing-right @spacing-bottom @spacing-left;
[class$=messagesmall] {
margin: 0px 0px 8px 0px;
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
08 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1dc6776635ee/
Changeset: 1dc6776635ee
User: guerler
Date: 2014-02-08 07:02:50
Summary: Upload: Fixes for FF
Affected #: 4 files
diff -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 -r 1dc6776635ee359f32e8c661f549d2db8c06f16d static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -296,27 +296,34 @@
// configure uploadbox
this.uploadbox.configure({url : this.options.nginx_upload_path});
- // configure file mode
- if (file_mode == 'ftp') {
- this.uploadbox.configure({paramname : ''});
+ // configure tool
+ tool_input = {};
+
+ // local files
+ if (file_mode == 'local') {
+ this.uploadbox.configure({paramname : 'files_0|file_data'});
} else {
- this.uploadbox.configure({paramname : 'files_0|file_data'});
+ this.uploadbox.configure({paramname : null});
}
- // configure tool
- tool_input = {};
+ // new files
+ if (file_mode == 'new') {
+ tool_input['files_0|url_paste'] = url_paste;
+ }
+
+ // files from ftp
+ if (file_mode == 'ftp') {
+ // add to tool configuration
+ tool_input['files_0|ftp_files'] = file_path;
+ }
+
+ // add common configuration
tool_input['dbkey'] = genome;
tool_input['file_type'] = extension;
tool_input['files_0|type'] = 'upload_dataset';
- tool_input['files_0|url_paste'] = url_paste;
tool_input['space_to_tabs'] = space_to_tabs;
tool_input['to_posix_lines'] = to_posix_lines;
- // add ftp file path
- if (file_mode == 'ftp') {
- tool_input['files_0|ftp_files'] = file_path;
- }
-
// setup data
data = {};
data['history_id'] = this.current_history;
@@ -341,8 +348,8 @@
_eventSuccess : function(index, file, message) {
// update status
var it = this.collection.get(index);
+ it.set('percentage', 100);
it.set('status', 'success');
- it.set('percentage', 100);
// file size
var file_size = it.get('file_size');
@@ -370,9 +377,9 @@
var it = this.collection.get(index);
// update status
+ it.set('percentage', 100);
it.set('status', 'error');
it.set('info', message);
- it.set('percentage', 100);
// update ui button
this.ui_button.set('percentage', this._upload_percentage(100, file.size));
diff -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 -r 1dc6776635ee359f32e8c661f549d2db8c06f16d static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes?upload_only=True",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;if(h=="ftp"){tool_input["files_0|ftp_files"]=n}data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");k.set("percentage",100);var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);j.set("percentage",100);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes?upload_only=True",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});tool_input={};if(h=="local"){this.uploadbox.configure({paramname:"files_0|file_data"})}else{this.uploadbox.configure({paramname:null})}if(h=="new"){tool_input["files_0|url_paste"]=q}if(h=="ftp"){tool_input["files_0|ftp_files"]=n}tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("percentage",100);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("percentage",100);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
diff -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 -r 1dc6776635ee359f32e8c661f549d2db8c06f16d static/scripts/packed/utils/uploadbox.js
--- a/static/scripts/packed/utils/uploadbox.js
+++ b/static/scripts/packed/utils/uploadbox.js
@@ -1,1 +1,1 @@
-(function(c){jQuery.event.props.push("dataTransfer");var h={url:"",paramname:"content",maxfilesize:2048,maxfilenumber:50,dragover:function(){},dragleave:function(){},announce:function(){},initialize:function(){},progress:function(){},success:function(){},error:function(k,l,m){alert(m)},complete:function(){},error_filesize:"File exceeds 2GB. Please use an FTP client.",error_default:"Please make sure the file is available.",error_server:"Upload request failed.",error_login:"Uploads require you to log in.",error_missing:"No upload content available."};var a={};var e={};var f=0;var j=0;var d=false;var g=false;var b=null;var i=null;c.fn.uploadbox=function(A){a=c.extend({},h,A);b=this;b.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');b.on("drop",o);b.on("dragover",p);b.on("dragleave",x);c("#uploadbox_input").change(function(B){z(B.target.files);c(this).val("")});function o(B){if(!B.dataTransfer){return}z(B.dataTransfer.files);B.preventDefault();return false}function p(B){B.preventDefault();a.dragover.call(B)}function x(B){B.stopPropagation();a.dragleave.call(B)}function k(B){if(B.lengthComputable){a.progress(this.index,this.file,Math.round((B.loaded*100)/B.total))}}function z(D){if(d){return}var E=f;for(var C=0;C<D.length;C++){if(j>=a.maxfilenumber){break}var B=String(f++);e[B]=D[C];a.announce(B,e[B],"");j++}return E}function r(B){if(e[B]){delete e[B];j--}}function m(){if(j==0||g){g=false;d=false;a.complete();return}else{d=true}var D=-1;for(var F in e){D=F;break}var E=e[D];r(D);var C=E.size;var H=E.mode;var B=1048576*a.maxfilesize;if(C<B||E.mode=="ftp"){var G=a.initialize(D,E);if(G){q(D,E,G)}else{u(D,E,a.error_missing)}}else{u(D,E,a.error_filesize)}}function q(B,D,E){var F=new FormData();for(var C in E){F.append(C,E[C])}if(D.size>0){F.append(a.paramname,D,D.name)}i=new XMLHttpRequest();i.open("POST",a.url,true);i.setRequestHeader("Accept","application/json");i.setRequestHeader("Cache-Control","no-cache");i.setRequestHeader("X-Requested-With","XMLHttpRequest");i.onreadystatechange=function(){if(i.readyState!=i.DONE){return}var G=null;if(i.responseText){try{G=jQuery.parseJSON(i.responseText)}catch(H){G=i.responseText}}if(i.status<200||i.status>299){var I=i.statusText;if(i.status==403){I=a.error_login}else{if(i.status==0){I=a.error_server}else{if(!I){I=a.error_default}}}u(B,D,I+" ("+i.status+")")}else{y(B,D,G)}};i.upload.index=B;i.upload.file=D;i.upload.addEventListener("progress",k,false);i.send(F)}function y(B,C,D){a.success(B,C,D);m()}function u(B,C,D){a.error(B,C,D);m()}function w(){c("#uploadbox_input").trigger("click")}function t(B){for(B in e){r(B)}}function l(){if(!d){d=true;m()}}function v(){g=true}function n(B){a=c.extend({},a,B);return a}function s(){return window.File&&window.FormData&&window.XMLHttpRequest&&window.FileList}return{select:w,add:z,remove:r,start:l,stop:v,reset:t,configure:n,compatible:s}}})(jQuery);
\ No newline at end of file
+(function(c){jQuery.event.props.push("dataTransfer");var h={url:"",paramname:"content",maxfilesize:2048,maxfilenumber:50,dragover:function(){},dragleave:function(){},announce:function(){},initialize:function(){},progress:function(){},success:function(){},error:function(k,l,m){alert(m)},complete:function(){},error_filesize:"File exceeds 2GB. Please use an FTP client.",error_default:"Please make sure the file is available.",error_server:"Upload request failed.",error_login:"Uploads require you to log in.",error_missing:"No upload content available."};var a={};var e={};var f=0;var j=0;var d=false;var g=false;var b=null;var i=null;c.fn.uploadbox=function(A){a=c.extend({},h,A);b=this;b.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');b.on("drop",o);b.on("dragover",p);b.on("dragleave",x);c("#uploadbox_input").change(function(B){z(B.target.files);c(this).val("")});function o(B){if(!B.dataTransfer){return}z(B.dataTransfer.files);B.preventDefault();return false}function p(B){B.preventDefault();a.dragover.call(B)}function x(B){B.stopPropagation();a.dragleave.call(B)}function k(B){if(B.lengthComputable){a.progress(this.index,this.file,Math.round((B.loaded*100)/B.total))}}function z(D){if(d){return}var E=f;for(var C=0;C<D.length;C++){if(j>=a.maxfilenumber){break}var B=String(f++);e[B]=D[C];a.announce(B,e[B],"");j++}return E}function r(B){if(e[B]){delete e[B];j--}}function m(){if(j==0||g){g=false;d=false;a.complete();return}else{d=true}var D=-1;for(var F in e){D=F;break}var E=e[D];r(D);var C=E.size;var H=E.mode;var B=1048576*a.maxfilesize;if(C<B||E.mode=="ftp"){var G=a.initialize(D,E);if(G){q(D,E,G)}else{u(D,E,a.error_missing)}}else{u(D,E,a.error_filesize)}}function q(B,D,E){var F=new FormData();for(var C in E){F.append(C,E[C])}if(D.size>0&&a.paramname){F.append(a.paramname,D,D.name)}i=new XMLHttpRequest();i.open("POST",a.url,true);i.setRequestHeader("Accept","application/json");i.setRequestHeader("Cache-Control","no-cache");i.setRequestHeader("X-Requested-With","XMLHttpRequest");i.onreadystatechange=function(){if(i.readyState!=i.DONE){return}var G=null;if(i.responseText){try{G=jQuery.parseJSON(i.responseText)}catch(H){G=i.responseText}}if(i.status<200||i.status>299){var I=i.statusText;if(i.status==403){I=a.error_login}else{if(i.status==0){I=a.error_server}else{if(!I){I=a.error_default}}}u(B,D,I+" ("+i.status+")")}else{y(B,D,G)}};i.upload.index=B;i.upload.file=D;i.upload.addEventListener("progress",k,false);i.send(F)}function y(B,C,D){a.success(B,C,D);m()}function u(B,C,D){a.error(B,C,D);m()}function w(){c("#uploadbox_input").trigger("click")}function t(B){for(B in e){r(B)}}function l(){if(!d){d=true;m()}}function v(){g=true}function n(B){a=c.extend({},a,B);return a}function s(){return window.File&&window.FormData&&window.XMLHttpRequest&&window.FileList}return{select:w,add:z,remove:r,start:l,stop:v,reset:t,configure:n,compatible:s}}})(jQuery);
\ No newline at end of file
diff -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 -r 1dc6776635ee359f32e8c661f549d2db8c06f16d static/scripts/utils/uploadbox.js
--- a/static/scripts/utils/uploadbox.js
+++ b/static/scripts/utils/uploadbox.js
@@ -219,12 +219,14 @@
{
// construct form data
var formData = new FormData();
- for (var key in data)
+ for (var key in data) {
formData.append(key, data[key]);
+ }
// check file size
- if (file.size > 0)
+ if (file.size > 0 && opts.paramname) {
formData.append(opts.paramname, file, file.name);
+ }
// prepare request
xhr = new XMLHttpRequest();
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: guerler: Upload: Fix progress bar in FF
by commits-noreply@bitbucket.org 08 Feb '14
by commits-noreply@bitbucket.org 08 Feb '14
08 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0c2b806274c5/
Changeset: 0c2b806274c5
User: guerler
Date: 2014-02-08 06:31:29
Summary: Upload: Fix progress bar in FF
Affected #: 4 files
diff -r 303f709d14276511f121c216f030400fddec2bd5 -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 static/scripts/mvc/upload/upload-model.js
--- a/static/scripts/mvc/upload/upload-model.js
+++ b/static/scripts/mvc/upload/upload-model.js
@@ -13,6 +13,7 @@
file_size : 0,
file_type : null,
file_path : '',
+ percentage : 0,
// settings
space_to_tabs : false,
diff -r 303f709d14276511f121c216f030400fddec2bd5 -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -342,6 +342,7 @@
// update status
var it = this.collection.get(index);
it.set('status', 'success');
+ it.set('percentage', 100);
// file size
var file_size = it.get('file_size');
@@ -371,6 +372,7 @@
// update status
it.set('status', 'error');
it.set('info', message);
+ it.set('percentage', 100);
// update ui button
this.ui_button.set('percentage', this._upload_percentage(100, file.size));
diff -r 303f709d14276511f121c216f030400fddec2bd5 -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 static/scripts/packed/mvc/upload/upload-model.js
--- a/static/scripts/packed/mvc/upload/upload-model.js
+++ b/static/scripts/packed/mvc/upload/upload-model.js
@@ -1,1 +1,1 @@
-define([],function(){var b=Backbone.Model.extend({defaults:{extension:"auto",genome:"?",url_paste:"",status:"init",info:null,file_mode:"local",file_size:0,file_type:null,file_path:"",space_to_tabs:false,to_posix_lines:true}});var a=Backbone.Collection.extend({model:b});return{Model:b,Collection:a}});
\ No newline at end of file
+define([],function(){var b=Backbone.Model.extend({defaults:{extension:"auto",genome:"?",url_paste:"",status:"init",info:null,file_mode:"local",file_size:0,file_type:null,file_path:"",percentage:0,space_to_tabs:false,to_posix_lines:true}});var a=Backbone.Collection.extend({model:b});return{Model:b,Collection:a}});
\ No newline at end of file
diff -r 303f709d14276511f121c216f030400fddec2bd5 -r 0c2b806274c53d16d9c9ba15501431a2103c8a54 static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes?upload_only=True",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;if(h=="ftp"){tool_input["files_0|ftp_files"]=n}data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes?upload_only=True",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;if(h=="ftp"){tool_input["files_0|ftp_files"]=n}data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");k.set("percentage",100);var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);j.set("percentage",100);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ 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
commit/galaxy-central: guerler: Charts: Adjust to viz framework change
by commits-noreply@bitbucket.org 08 Feb '14
by commits-noreply@bitbucket.org 08 Feb '14
08 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/303f709d1427/
Changeset: 303f709d1427
User: guerler
Date: 2014-02-08 06:06:46
Summary: Charts: Adjust to viz framework change
Affected #: 1 file
diff -r 375c04b4a7085c91c48201fc5d7376ab613874c8 -r 303f709d14276511f121c216f030400fddec2bd5 config/plugins/visualizations/charts/templates/charts.mako
--- a/config/plugins/visualizations/charts/templates/charts.mako
+++ b/config/plugins/visualizations/charts/templates/charts.mako
@@ -61,7 +61,7 @@
require(['app'], function(App) {
// load options
var options = {
- config : ${h.to_json_string( query_args )},
+ config : ${h.to_json_string( config )},
dataset : ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ) )}
}
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: guerler: Upload: Add error handler to ftp file api controller, remove timeout for extension info popup
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/375c04b4a708/
Changeset: 375c04b4a708
User: guerler
Date: 2014-02-08 05:15:43
Summary: Upload: Add error handler to ftp file api controller, remove timeout for extension info popup
Affected #: 5 files
diff -r 4228b5439785c10aaf638db4e18be65dfd6b9275 -r 375c04b4a7085c91c48201fc5d7376ab613874c8 lib/galaxy/webapps/galaxy/api/ftp_files.py
--- a/lib/galaxy/webapps/galaxy/api/ftp_files.py
+++ b/lib/galaxy/webapps/galaxy/api/ftp_files.py
@@ -18,35 +18,43 @@
GET /api/ftp_files/
Displays local files.
"""
- # initialize response
- response = []
- # identify ftp directory
- user_ftp_base_dir = trans.app.config.ftp_upload_dir
- if user_ftp_base_dir is None:
- return []
-
- # identify user sub directory
- user_ftp_dir = None
- if user_ftp_base_dir is not None and trans is not None and trans.user is not None:
- identifier = trans.app.config.ftp_upload_dir_identifier
- user_ftp_dir = os.path.join( user_ftp_base_dir, getattr(trans.user, identifier) )
- if user_ftp_dir is None:
- return []
+ # look for ftp files
+ try:
+ # initialize response
+ response = []
+
+ # identify ftp directory
+ user_ftp_base_dir = trans.app.config.ftp_upload_dir
+ if user_ftp_base_dir is None:
+ return []
+
+ # identify user sub directory
+ user_ftp_dir = None
+ if user_ftp_base_dir is not None and trans is not None and trans.user is not None:
+ identifier = trans.app.config.ftp_upload_dir_identifier
+ user_ftp_dir = os.path.join( user_ftp_base_dir, getattr(trans.user, identifier) )
+ if user_ftp_dir is None:
+ return []
- # read directory
- if os.path.exists( user_ftp_dir ):
- for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
- for filename in filenames:
- path = os.path.relpath( os.path.join( dirpath, filename ), user_ftp_dir )
- statinfo = os.lstat( os.path.join( dirpath, filename ) )
- response.append( dict( path = path,
- size = statinfo.st_size,
- ctime = time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
+ # read directory
+ if os.path.exists( user_ftp_dir ):
+ for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
+ for filename in filenames:
+ path = os.path.relpath( os.path.join( dirpath, filename ), user_ftp_dir )
+ statinfo = os.lstat( os.path.join( dirpath, filename ) )
+ response.append( dict( path = path,
+ size = statinfo.st_size,
+ ctime = time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
+
+ # sort by path
+ response = sorted(response, key=itemgetter("path"))
+
+ # return
+ return response
- # sort by path
- response = sorted(response, key=itemgetter("path"))
-
- # return
- return response
+ except Exception, exception:
+ log.error( 'could not get ftp files: %s', str( exception ), exc_info=True )
+ trans.response.status = 500
+ return { 'error': str( exception ) }
diff -r 4228b5439785c10aaf638db4e18be65dfd6b9275 -r 375c04b4a7085c91c48201fc5d7376ab613874c8 static/scripts/mvc/upload/upload-row.js
--- a/static/scripts/mvc/upload/upload-row.js
+++ b/static/scripts/mvc/upload/upload-row.js
@@ -16,8 +16,7 @@
return Backbone.View.extend({
// options
options: {
- padding : 8,
- timeout : 2000
+ padding : 8
},
// states
@@ -325,16 +324,6 @@
},
// attach file info popup
- _hideExtensionInfo : function()
- {
- // remove popup
- var self = this
- this.popover_timeout = setTimeout(function() {
- self._destroyExtensionInfo();
- }, this.options.timeout);
- },
-
- // attach file info popup
_destroyExtensionInfo : function()
{
this.$el.find('#extension-info').popover('destroy');
diff -r 4228b5439785c10aaf638db4e18be65dfd6b9275 -r 375c04b4a7085c91c48201fc5d7376ab613874c8 static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -105,7 +105,7 @@
// load extension
var self = this;
- Utils.jsonFromUrl(galaxy_config.root + "api/datatypes",
+ Utils.jsonFromUrl(galaxy_config.root + "api/datatypes?upload_only=True",
function(datatypes) {
for (key in datatypes)
self.select_extension.push([datatypes[key], datatypes[key]]);
diff -r 4228b5439785c10aaf638db4e18be65dfd6b9275 -r 375c04b4a7085c91c48201fc5d7376ab613874c8 static/scripts/packed/mvc/upload/upload-row.js
--- a/static/scripts/packed/mvc/upload/upload-row.js
+++ b/static/scripts/packed/mvc/upload/upload-row.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/upload/upload-model","mvc/upload/upload-extensions","mvc/upload/upload-settings","mvc/ui.popover"],function(d,b,e,a,c){return Backbone.View.extend({options:{padding:8,timeout:2000},status_classes:{init:"upload-icon-button fa fa-trash-o",queued:"upload-icon fa fa-spinner fa-spin",running:"upload-icon fa fa-spinner fa-spin",success:"upload-icon-button fa fa-check",error:"upload-icon-button fa fa-exclamation-triangle"},settings:null,initialize:function(i,g){this.app=i;var f=this;this.model=new b.Model(g);this.setElement(this._template(g));var h=this.$el;this.settings=new c.View({title:"Upload configuration",container:h.find("#settings"),placement:"bottom"});h.find("#symbol").on("click",function(){f._removeRow()});h.find("#extension-info").on("click",function(j){f._showExtensionInfo()}).on("mousedown",function(j){j.preventDefault()});h.find("#settings").on("click",function(j){f._showSettings()}).on("mousedown",function(j){j.preventDefault()});h.find("#text-content").on("keyup",function(j){f.model.set("url_paste",$(j.target).val());f.model.set("file_size",$(j.target).val().length)});h.find("#genome").on("change",function(j){f.model.set("genome",$(j.target).val())});h.find("#extension").on("change",function(j){f.model.set("extension",$(j.target).val())});h.find("#space_to_tabs").on("change",function(j){f.model.set("space_to_tabs",$(j.target).prop("checked"))});this.model.on("change:percentage",function(){f._refreshPercentage()});this.model.on("change:status",function(){f._refreshStatus()});this.model.on("change:extension",function(){f._destroyExtensionInfo()});this.model.on("change:info",function(){f._refreshInfo()});this.model.on("change:genome",function(){f._refreshGenome()});this.model.on("change:file_size",function(){f._refreshFileSize()});this.model.on("remove",function(){f._destroyExtensionInfo();f.remove()});this.app.collection.on("reset",function(){f._destroyExtensionInfo();f.remove()})},render:function(){var m=this.model.get("file_name");var g=this.model.get("file_size");var j=this.model.get("file_mode");var i=this.$el;i.find("#title").html(m);i.find("#size").html(d.bytesToString(g));i.find("#mode").removeClass().addClass("mode");if(j=="new"){var l=i.find("#text");var k=this.options.padding;var h=i.width()-2*k;var f=i.height()-k;l.css("width",h+"px");l.css("top",f+"px");i.height(f+l.height()+2*k);l.show();i.find("#mode").addClass("fa fa-pencil")}if(j=="local"){i.find("#mode").addClass("fa fa-laptop")}if(j=="ftp"){i.find("#mode").addClass("fa fa-code-fork")}},_refreshGenome:function(){var f=this.model.get("genome");this.$el.find("#genome").val(f)},_refreshInfo:function(){var f=this.model.get("info");if(f){this.$el.find("#info").html("<strong>Failed: </strong>"+f).show()}else{this.$el.find("#info").hide()}},_refreshPercentage:function(){var f=parseInt(this.model.get("percentage"));this.$el.find(".progress-bar").css({width:f+"%"});if(f!=100){this.$el.find("#percentage").html(f+"%")}else{this.$el.find("#percentage").html("Adding to history...")}},_refreshStatus:function(){var g=this.$el;var f=this.model.get("status");var i=this.status_classes[f];var h=this.$el.find("#symbol");h.removeClass();h.addClass(i);if(f=="init"){g.find("#text-content").attr("disabled",false);g.find("#genome").attr("disabled",false);g.find("#extension").attr("disabled",false);g.find("#space_to_tabs").attr("disabled",false)}else{g.find("#text-content").attr("disabled",true);g.find("#genome").attr("disabled",true);g.find("#extension").attr("disabled",true);g.find("#space_to_tabs").attr("disabled",true)}if(f=="success"){g.addClass("success");g.find("#percentage").html("100%")}if(f=="error"){g.addClass("danger");g.find(".progress").remove()}},_refreshFileSize:function(){var f=this.model.get("file_size");this.$el.find("#size").html(d.bytesToString(f))},_removeRow:function(){var f=this.model.get("status");if(f=="init"||f=="success"||f=="error"){this.app.collection.remove(this.model)}},_showExtensionInfo:function(){var f=$(this.el).find("#extension-info");var h=this.model.get("extension");var g=$(this.el).find("#extension").find("option:selected").text();if(!this.extension_popup){this.extension_popup=new c.View({content:e(h),placement:"bottom",container:f})}if(!this.extension_popup.visible){this.extension_popup.title(g);this.extension_popup.empty();this.extension_popup.append(e(h));this.extension_popup.show()}else{this.extension_popup.hide()}},_showSettings:function(){if(!this.settings.visible){this.settings.empty();this.settings.append((new a(this)).$el);this.settings.show()}else{this.settings.hide()}},_hideExtensionInfo:function(){var f=this;this.popover_timeout=setTimeout(function(){f._destroyExtensionInfo()},this.options.timeout)},_destroyExtensionInfo:function(){this.$el.find("#extension-info").popover("destroy")},_template:function(h){var g=this;var f='<tr id="upload-item-'+h.id+'" class="upload-item"><td><div style="position: relative;"><div id="mode"></div><div id="title" class="title"></div><div id="text" class="text"><div class="text-info">You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.</div><textarea id="text-content" class="text-content form-control"></textarea></div></div></td><td><div id="size" class="size"></div></td>';f+='<td><select id="extension" class="extension">';for(key in g.app.select_extension){f+='<option value="'+g.app.select_extension[key][1]+'">'+g.app.select_extension[key][0]+"</option>"}f+='</select> <i id="extension-info" class="upload-icon-button fa fa-search"/></td>';f+='<td><select id="genome" class="genome">';for(key in g.app.select_genome){f+='<option value="'+g.app.select_genome[key][1]+'">'+g.app.select_genome[key][0]+"</option>"}f+="</select></td>";f+='<td><div id="settings" class="upload-icon-button fa fa-gear"></div><td><div id="info" class="info"><div class="progress"><div class="progress-bar progress-bar-success"></div><div id="percentage" class="percentage">0%</div></div></div></td><td><div id="symbol" class="'+this.status_classes.init+'"></div></td></tr>';return f}})});
\ No newline at end of file
+define(["utils/utils","mvc/upload/upload-model","mvc/upload/upload-extensions","mvc/upload/upload-settings","mvc/ui.popover"],function(d,b,e,a,c){return Backbone.View.extend({options:{padding:8},status_classes:{init:"upload-icon-button fa fa-trash-o",queued:"upload-icon fa fa-spinner fa-spin",running:"upload-icon fa fa-spinner fa-spin",success:"upload-icon-button fa fa-check",error:"upload-icon-button fa fa-exclamation-triangle"},settings:null,initialize:function(i,g){this.app=i;var f=this;this.model=new b.Model(g);this.setElement(this._template(g));var h=this.$el;this.settings=new c.View({title:"Upload configuration",container:h.find("#settings"),placement:"bottom"});h.find("#symbol").on("click",function(){f._removeRow()});h.find("#extension-info").on("click",function(j){f._showExtensionInfo()}).on("mousedown",function(j){j.preventDefault()});h.find("#settings").on("click",function(j){f._showSettings()}).on("mousedown",function(j){j.preventDefault()});h.find("#text-content").on("keyup",function(j){f.model.set("url_paste",$(j.target).val());f.model.set("file_size",$(j.target).val().length)});h.find("#genome").on("change",function(j){f.model.set("genome",$(j.target).val())});h.find("#extension").on("change",function(j){f.model.set("extension",$(j.target).val())});h.find("#space_to_tabs").on("change",function(j){f.model.set("space_to_tabs",$(j.target).prop("checked"))});this.model.on("change:percentage",function(){f._refreshPercentage()});this.model.on("change:status",function(){f._refreshStatus()});this.model.on("change:extension",function(){f._destroyExtensionInfo()});this.model.on("change:info",function(){f._refreshInfo()});this.model.on("change:genome",function(){f._refreshGenome()});this.model.on("change:file_size",function(){f._refreshFileSize()});this.model.on("remove",function(){f._destroyExtensionInfo();f.remove()});this.app.collection.on("reset",function(){f._destroyExtensionInfo();f.remove()})},render:function(){var m=this.model.get("file_name");var g=this.model.get("file_size");var j=this.model.get("file_mode");var i=this.$el;i.find("#title").html(m);i.find("#size").html(d.bytesToString(g));i.find("#mode").removeClass().addClass("mode");if(j=="new"){var l=i.find("#text");var k=this.options.padding;var h=i.width()-2*k;var f=i.height()-k;l.css("width",h+"px");l.css("top",f+"px");i.height(f+l.height()+2*k);l.show();i.find("#mode").addClass("fa fa-pencil")}if(j=="local"){i.find("#mode").addClass("fa fa-laptop")}if(j=="ftp"){i.find("#mode").addClass("fa fa-code-fork")}},_refreshGenome:function(){var f=this.model.get("genome");this.$el.find("#genome").val(f)},_refreshInfo:function(){var f=this.model.get("info");if(f){this.$el.find("#info").html("<strong>Failed: </strong>"+f).show()}else{this.$el.find("#info").hide()}},_refreshPercentage:function(){var f=parseInt(this.model.get("percentage"));this.$el.find(".progress-bar").css({width:f+"%"});if(f!=100){this.$el.find("#percentage").html(f+"%")}else{this.$el.find("#percentage").html("Adding to history...")}},_refreshStatus:function(){var g=this.$el;var f=this.model.get("status");var i=this.status_classes[f];var h=this.$el.find("#symbol");h.removeClass();h.addClass(i);if(f=="init"){g.find("#text-content").attr("disabled",false);g.find("#genome").attr("disabled",false);g.find("#extension").attr("disabled",false);g.find("#space_to_tabs").attr("disabled",false)}else{g.find("#text-content").attr("disabled",true);g.find("#genome").attr("disabled",true);g.find("#extension").attr("disabled",true);g.find("#space_to_tabs").attr("disabled",true)}if(f=="success"){g.addClass("success");g.find("#percentage").html("100%")}if(f=="error"){g.addClass("danger");g.find(".progress").remove()}},_refreshFileSize:function(){var f=this.model.get("file_size");this.$el.find("#size").html(d.bytesToString(f))},_removeRow:function(){var f=this.model.get("status");if(f=="init"||f=="success"||f=="error"){this.app.collection.remove(this.model)}},_showExtensionInfo:function(){var f=$(this.el).find("#extension-info");var h=this.model.get("extension");var g=$(this.el).find("#extension").find("option:selected").text();if(!this.extension_popup){this.extension_popup=new c.View({content:e(h),placement:"bottom",container:f})}if(!this.extension_popup.visible){this.extension_popup.title(g);this.extension_popup.empty();this.extension_popup.append(e(h));this.extension_popup.show()}else{this.extension_popup.hide()}},_showSettings:function(){if(!this.settings.visible){this.settings.empty();this.settings.append((new a(this)).$el);this.settings.show()}else{this.settings.hide()}},_destroyExtensionInfo:function(){this.$el.find("#extension-info").popover("destroy")},_template:function(h){var g=this;var f='<tr id="upload-item-'+h.id+'" class="upload-item"><td><div style="position: relative;"><div id="mode"></div><div id="title" class="title"></div><div id="text" class="text"><div class="text-info">You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.</div><textarea id="text-content" class="text-content form-control"></textarea></div></div></td><td><div id="size" class="size"></div></td>';f+='<td><select id="extension" class="extension">';for(key in g.app.select_extension){f+='<option value="'+g.app.select_extension[key][1]+'">'+g.app.select_extension[key][0]+"</option>"}f+='</select> <i id="extension-info" class="upload-icon-button fa fa-search"/></td>';f+='<td><select id="genome" class="genome">';for(key in g.app.select_genome){f+='<option value="'+g.app.select_genome[key][1]+'">'+g.app.select_genome[key][0]+"</option>"}f+="</select></td>";f+='<td><div id="settings" class="upload-icon-button fa fa-gear"></div><td><div id="info" class="info"><div class="progress"><div class="progress-bar progress-bar-success"></div><div id="percentage" class="percentage">0%</div></div></div></td><td><div id="symbol" class="'+this.status_classes.init+'"></div></td></tr>';return f}})});
\ No newline at end of file
diff -r 4228b5439785c10aaf638db4e18be65dfd6b9275 -r 375c04b4a7085c91c48201fc5d7376ab613874c8 static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;if(h=="ftp"){tool_input["files_0|ftp_files"]=n}data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes?upload_only=True",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;if(h=="ftp"){tool_input["files_0|ftp_files"]=n}data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ 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
commit/galaxy-central: guerler: Upload: Fix style for FF
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4228b5439785/
Changeset: 4228b5439785
User: guerler
Date: 2014-02-08 04:39:51
Summary: Upload: Fix style for FF
Affected #: 2 files
diff -r 2a62cf94bb5bb3a094f179652aaf17e4cdc2d8ce -r 4228b5439785c10aaf638db4e18be65dfd6b9275 static/scripts/mvc/upload/upload-ftp.js
--- a/static/scripts/mvc/upload/upload-ftp.js
+++ b/static/scripts/mvc/upload/upload-ftp.js
@@ -137,7 +137,7 @@
'<span class="upload-icon fa fa-hdd-o"/>' +
'<span id="upload-ftp-disk"/>' +
'</span>' +
- '<table class="grid">' +
+ '<table class="grid" style="float: left;">' +
'<thead>' +
'<tr>' +
'<th></th>' +
diff -r 2a62cf94bb5bb3a094f179652aaf17e4cdc2d8ce -r 4228b5439785c10aaf638db4e18be65dfd6b9275 static/scripts/packed/mvc/upload/upload-ftp.js
--- a/static/scripts/packed/mvc/upload/upload-ftp.js
+++ b/static/scripts/packed/mvc/upload/upload-ftp.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.View.extend({options:{class_add:"upload-icon-button fa fa-square-o",class_remove:"upload-icon-button fa fa-check-square-o"},initialize:function(c){this.app=c;var b=this;this.setElement(this._template());a.jsonFromUrl(galaxy_config.root+"api/ftp_files",function(d){b._fill(d)})},events:{mousedown:function(b){b.preventDefault()}},_fill:function(c){if(c.length>0){this.$el.find("#upload-ftp-content").html($(this._template_table()));var b=0;for(key in c){this.add(c[key]);b+=c[key].size}this.$el.find("#upload-ftp-number").html(c.length+" files");this.$el.find("#upload-ftp-disk").html(a.bytesToString(b,true))}else{this.$el.find("#upload-ftp-content").html($(this._template_info()))}this.$el.find("#upload-ftp-wait").hide()},add:function(e){var d=$(this._template_row(e));$(this.el).find("tbody").append(d);var c="";if(this._find(e)){c=this.options.class_remove}else{c=this.options.class_add}d.find("#upload-ftp-add").addClass(c);var b=this;d.find("#upload-ftp-add").on("click",function(){var f=b._find(e);$(this).removeClass();if(!f){b.app.uploadbox.add([{mode:"ftp",name:e.path,size:e.size,path:e.path}]);$(this).addClass(b.options.class_remove)}else{b.app.collection.remove(f);$(this).addClass(b.options.class_add)}})},_find:function(f){var c=this.app.collection.where({file_path:f.path});var b=null;for(var d in c){var e=c[d];if(e.get("status")=="init"&&e.get("file_mode")=="ftp"){b=e.get("id")}}return b},_template_row:function(b){return'<tr><td><div id="upload-ftp-add"/></td><td>'+b.path+'</td><td style="white-space: nowrap;">'+a.bytesToString(b.size)+'</td><td style="white-space: nowrap;">'+b.ctime+"</td></tr>"},_template_table:function(){return'<span style="whitespace: nowrap; float: left;">Available files: </span><span style="whitespace: nowrap; float: right;"><span class="upload-icon fa fa-file-text-o"/><span id="upload-ftp-number"/> <span class="upload-icon fa fa-hdd-o"/><span id="upload-ftp-disk"/></span><table class="grid"><thead><tr><th></th><th>Name</th><th>Size</th><th>Created</th></tr></thead><tbody></tbody></table>'},_template_info:function(){return'<div class="upload-ftp-warning warningmessage">Your FTP directory does not contain any files.</div>'},_template:function(){return'<div class="upload-ftp"><div id="upload-ftp-wait" class="upload-ftp-wait fa fa-spinner fa-spin"/><div class="upload-ftp-help">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>'+this.app.options.ftp_upload_site+'</strong> using your Galaxy credentials (email address and password).</div><div id="upload-ftp-content"></div><div>'}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.View.extend({options:{class_add:"upload-icon-button fa fa-square-o",class_remove:"upload-icon-button fa fa-check-square-o"},initialize:function(c){this.app=c;var b=this;this.setElement(this._template());a.jsonFromUrl(galaxy_config.root+"api/ftp_files",function(d){b._fill(d)})},events:{mousedown:function(b){b.preventDefault()}},_fill:function(c){if(c.length>0){this.$el.find("#upload-ftp-content").html($(this._template_table()));var b=0;for(key in c){this.add(c[key]);b+=c[key].size}this.$el.find("#upload-ftp-number").html(c.length+" files");this.$el.find("#upload-ftp-disk").html(a.bytesToString(b,true))}else{this.$el.find("#upload-ftp-content").html($(this._template_info()))}this.$el.find("#upload-ftp-wait").hide()},add:function(e){var d=$(this._template_row(e));$(this.el).find("tbody").append(d);var c="";if(this._find(e)){c=this.options.class_remove}else{c=this.options.class_add}d.find("#upload-ftp-add").addClass(c);var b=this;d.find("#upload-ftp-add").on("click",function(){var f=b._find(e);$(this).removeClass();if(!f){b.app.uploadbox.add([{mode:"ftp",name:e.path,size:e.size,path:e.path}]);$(this).addClass(b.options.class_remove)}else{b.app.collection.remove(f);$(this).addClass(b.options.class_add)}})},_find:function(f){var c=this.app.collection.where({file_path:f.path});var b=null;for(var d in c){var e=c[d];if(e.get("status")=="init"&&e.get("file_mode")=="ftp"){b=e.get("id")}}return b},_template_row:function(b){return'<tr><td><div id="upload-ftp-add"/></td><td>'+b.path+'</td><td style="white-space: nowrap;">'+a.bytesToString(b.size)+'</td><td style="white-space: nowrap;">'+b.ctime+"</td></tr>"},_template_table:function(){return'<span style="whitespace: nowrap; float: left;">Available files: </span><span style="whitespace: nowrap; float: right;"><span class="upload-icon fa fa-file-text-o"/><span id="upload-ftp-number"/> <span class="upload-icon fa fa-hdd-o"/><span id="upload-ftp-disk"/></span><table class="grid" style="float: left;"><thead><tr><th></th><th>Name</th><th>Size</th><th>Created</th></tr></thead><tbody></tbody></table>'},_template_info:function(){return'<div class="upload-ftp-warning warningmessage">Your FTP directory does not contain any files.</div>'},_template:function(){return'<div class="upload-ftp"><div id="upload-ftp-wait" class="upload-ftp-wait fa fa-spinner fa-spin"/><div class="upload-ftp-help">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>'+this.app.options.ftp_upload_site+'</strong> using your Galaxy credentials (email address and password).</div><div id="upload-ftp-content"></div><div>'}})});
\ 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
commit/galaxy-central: guerler: Upload: Remove console output
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2a62cf94bb5b/
Changeset: 2a62cf94bb5b
User: guerler
Date: 2014-02-08 01:41:28
Summary: Upload: Remove console output
Affected #: 2 files
diff -r c3671911ad886fda9cd85c1bf398ac6f10325022 -r 2a62cf94bb5bb3a094f179652aaf17e4cdc2d8ce static/scripts/mvc/upload/upload-button.js
--- a/static/scripts/mvc/upload/upload-button.js
+++ b/static/scripts/mvc/upload/upload-button.js
@@ -67,7 +67,6 @@
$el.addClass('progress-bar-notransition');
if (value != '') {
$el.addClass('progress-bar-' + value);
- console.log($el);
}
},
diff -r c3671911ad886fda9cd85c1bf398ac6f10325022 -r 2a62cf94bb5bb3a094f179652aaf17e4cdc2d8ce static/scripts/packed/mvc/upload/upload-button.js
--- a/static/scripts/packed/mvc/upload/upload-button.js
+++ b/static/scripts/packed/mvc/upload/upload-button.js
@@ -1,1 +1,1 @@
-define([],function(){var b=Backbone.Model.extend({defaults:{percentage:0,icon:"fa-circle",label:"",status:""}});var a=Backbone.View.extend({model:null,initialize:function(d){var c=this;this.model=d;this.options=this.model.attributes;this.setElement(this._template(this.options));$(this.el).on("click",this.options.onclick);if(this.options.tooltip){$(this.el).tooltip({title:this.options.tooltip,placement:"bottom"})}this.model.on("change:percentage",function(){c._percentage(c.model.get("percentage"))});this.model.on("change:status",function(){c._status(c.model.get("status"))});var c=this;$(window).on("beforeunload",function(){var e="";if(c.options.onunload){e=c.options.onunload()}if(e!=""){return e}})},_status:function(d){var c=this.$el.find(".progress-bar");c.removeClass();c.addClass("progress-bar");c.addClass("progress-bar-notransition");if(d!=""){c.addClass("progress-bar-"+d);console.log(c)}},_percentage:function(d){var c=this.$el.find(".progress-bar");c.css({width:d+"%"})},_template:function(c){return'<div style="float: right"><div class="upload-button"><div class="progress"><div class="progress-bar"></div></div><div id="label" class="label"><a class="panel-header-button" href="javascript:void(0)"><span class="fa fa-upload"></span></a></div></div></div>'}});return{Model:b,View:a}});
\ No newline at end of file
+define([],function(){var b=Backbone.Model.extend({defaults:{percentage:0,icon:"fa-circle",label:"",status:""}});var a=Backbone.View.extend({model:null,initialize:function(d){var c=this;this.model=d;this.options=this.model.attributes;this.setElement(this._template(this.options));$(this.el).on("click",this.options.onclick);if(this.options.tooltip){$(this.el).tooltip({title:this.options.tooltip,placement:"bottom"})}this.model.on("change:percentage",function(){c._percentage(c.model.get("percentage"))});this.model.on("change:status",function(){c._status(c.model.get("status"))});var c=this;$(window).on("beforeunload",function(){var e="";if(c.options.onunload){e=c.options.onunload()}if(e!=""){return e}})},_status:function(d){var c=this.$el.find(".progress-bar");c.removeClass();c.addClass("progress-bar");c.addClass("progress-bar-notransition");if(d!=""){c.addClass("progress-bar-"+d)}},_percentage:function(d){var c=this.$el.find(".progress-bar");c.css({width:d+"%"})},_template:function(c){return'<div style="float: right"><div class="upload-button"><div class="progress"><div class="progress-bar"></div></div><div id="label" class="label"><a class="panel-header-button" href="javascript:void(0)"><span class="fa fa-upload"></span></a></div></div></div>'}});return{Model:b,View:a}});
\ 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
commit/galaxy-central: guerler: Upload: Only add ftp file path if available
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c3671911ad88/
Changeset: c3671911ad88
User: guerler
Date: 2014-02-08 01:05:36
Summary: Upload: Only add ftp file path if available
Affected #: 2 files
diff -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 -r c3671911ad886fda9cd85c1bf398ac6f10325022 static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -309,10 +309,14 @@
tool_input['file_type'] = extension;
tool_input['files_0|type'] = 'upload_dataset';
tool_input['files_0|url_paste'] = url_paste;
- tool_input['files_0|ftp_files'] = file_path;
tool_input['space_to_tabs'] = space_to_tabs;
tool_input['to_posix_lines'] = to_posix_lines;
+ // add ftp file path
+ if (file_mode == 'ftp') {
+ tool_input['files_0|ftp_files'] = file_path;
+ }
+
// setup data
data = {};
data['history_id'] = this.current_history;
diff -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 -r c3671911ad886fda9cd85c1bf398ac6f10325022 static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input["files_0|ftp_files"]=n;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;if(h=="ftp"){tool_input["files_0|ftp_files"]=n}data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ 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
commit/galaxy-central: guerler: Upload: Add ftp support, separate modules, Ui: Add popovers, Grids: Fix search icon
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d8fcf33cbe4a/
Changeset: d8fcf33cbe4a
User: guerler
Date: 2014-02-08 00:47:25
Summary: Upload: Add ftp support, separate modules, Ui: Add popovers, Grids: Fix search icon
Affected #: 31 files
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 lib/galaxy/webapps/galaxy/api/ftp_files.py
--- /dev/null
+++ b/lib/galaxy/webapps/galaxy/api/ftp_files.py
@@ -0,0 +1,52 @@
+"""
+API operations on ftp files.
+"""
+import logging
+from galaxy.web.base.controller import BaseAPIController, url_for
+from galaxy import web
+import os.path
+import os
+import time
+from operator import itemgetter
+
+log = logging.getLogger( __name__ )
+
+class FTPFilesAPIController( BaseAPIController ):
+ @web.expose_api
+ def index( self, trans, **kwd ):
+ """
+ GET /api/ftp_files/
+ Displays local files.
+ """
+ # initialize response
+ response = []
+
+ # identify ftp directory
+ user_ftp_base_dir = trans.app.config.ftp_upload_dir
+ if user_ftp_base_dir is None:
+ return []
+
+ # identify user sub directory
+ user_ftp_dir = None
+ if user_ftp_base_dir is not None and trans is not None and trans.user is not None:
+ identifier = trans.app.config.ftp_upload_dir_identifier
+ user_ftp_dir = os.path.join( user_ftp_base_dir, getattr(trans.user, identifier) )
+ if user_ftp_dir is None:
+ return []
+
+ # read directory
+ if os.path.exists( user_ftp_dir ):
+ for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
+ for filename in filenames:
+ path = os.path.relpath( os.path.join( dirpath, filename ), user_ftp_dir )
+ statinfo = os.lstat( os.path.join( dirpath, filename ) )
+ response.append( dict( path = path,
+ size = statinfo.st_size,
+ ctime = time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
+
+ # sort by path
+ response = sorted(response, key=itemgetter("path"))
+
+ # return
+ return response
+
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -127,6 +127,7 @@
webapp.mapper.resource( 'form', 'forms', path_prefix='/api' )
webapp.mapper.resource( 'request_type', 'request_types', path_prefix='/api' )
webapp.mapper.resource( 'role', 'roles', path_prefix='/api' )
+ webapp.mapper.resource( 'ftp_file', 'ftp_files', path_prefix='/api' )
webapp.mapper.resource( 'group', 'groups', path_prefix='/api' )
webapp.mapper.resource_with_deleted( 'quota', 'quotas', path_prefix='/api' )
webapp.mapper.connect( '/api/tools/{id:.+?}', action='show', controller="tools" )
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/galaxy.modal.js
--- a/static/scripts/galaxy.modal.js
+++ b/static/scripts/galaxy.modal.js
@@ -86,6 +86,12 @@
this.$buttons.find('#' + button_id).hide();
},
+ // get button
+ getButton: function(name) {
+ var button_id = this.buttonList[name];
+ return this.$buttons.find('#' + button_id);
+ },
+
// returns scroll top for body element
scrollTop: function() {
return this.$body.scrollTop();
@@ -175,7 +181,7 @@
'<button type="button" class="close" style="display: none;">×</button>' +
'<h4 class="title">' + title + '</h4>' +
'</div>' +
- '<div class="modal-body"></div>' +
+ '<div class="modal-body" style="position: static;"></div>' +
'<div class="modal-footer">' +
'<div class="buttons" style="float: right;"></div>' +
'</div>' +
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/grid/grid-template.js
--- a/static/scripts/mvc/grid/grid-template.js
+++ b/static/scripts/mvc/grid/grid-template.js
@@ -556,7 +556,7 @@
tmpl += '<span class="search-box">' +
'<input class="search-box-input" id="input-' + column_key + '-filter" name="f-' + column_key + '" type="text" placeholder="' + value + '" size="' + size + '"/>' +
'<button type="submit" style="background: transparent; border: none; padding: 4px; margin: 0px;">' +
- '<i class="fa fa-plus-circle"></i>' +
+ '<i class="fa fa-search"></i>' +
'</button>' +
'</span>' +
'</form>';
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/ui.popover.js
--- /dev/null
+++ b/static/scripts/mvc/ui.popover.js
@@ -0,0 +1,169 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+var View = Backbone.View.extend({
+
+ // default options
+ optionsDefault: {
+ with_close : true,
+ container : 'body',
+ title : null,
+ placement : 'top'
+ },
+
+ // visibility flag
+ visible: false,
+
+ // initialize
+ initialize: function (options) {
+
+ // link this
+ var self = this;
+
+ // update options
+ this.options = _.defaults(options, this.optionsDefault);
+
+ // set element
+ this.setElement(this._template(this.options));
+
+ // attach popover to parent
+ this.options.container.parent().append(this.$el);
+
+ // attach close
+ if (this.options.with_close) {
+ this.$el.find('#close').on('click', function() { self.hide(); });
+ }
+
+ // generate unique id
+ this.uuid = Utils.uuid();
+
+ // add event to hide if click is outside of popup
+ var self = this;
+ $('body').on('mousedown.' + this.uuid, function(e) { self._hide(e) });
+ },
+
+ // title
+ title: function(val) {
+ if (val !== undefined) {
+ this.$el.find('.popover-title-label').html(val);
+ }
+ },
+
+ // show
+ show: function () {
+ // show popover
+ this.$el.show();
+ this.visible = true;
+
+ // calculate position
+ var position = this._get_placement(this.options.placement);
+
+ // set position
+ this.$el.css(position);
+ },
+
+ // calculate position and error
+ _get_placement: function(placement) {
+ // get popover dimensions
+ var width = this._get_width(this.$el);
+ var height = this.$el.height();
+
+ // get container details
+ var $container = this.options.container;
+ var container_width = this._get_width($container);
+ var container_height = this._get_height($container);
+ var container_position = $container.position();
+
+ // initialize position
+ var top = 0;
+ var left = 0;
+
+ // calculate position
+ if (placement == 'top' || placement == 'bottom') {
+ left = container_position.left - width + (container_width + width) / 2;
+ if (placement == 'top') {
+ top = container_position.top - height - 5;
+ } else {
+ top = container_position.top + container_height + 5;
+ }
+ }
+
+ // return
+ return {top: top, left: left};
+ },
+
+ // width
+ _get_width: function($el) {
+ return $el.width() + parseInt($el.css('padding-left')) + parseInt($el.css('padding-right'))
+ },
+
+ // heigth
+ _get_height: function($el) {
+ return $el.height() + parseInt($el.css('padding-top')) + parseInt($el.css('padding-bottom'))
+ },
+
+ // hide
+ hide: function () {
+ this.$el.hide();
+ this.visible = false;
+ },
+
+ // append
+ append: function($el) {
+ this.$el.find('.popover-content').append($el);
+ },
+
+ // empty
+ empty: function($el) {
+ this.$el.find('.popover-content').empty();
+ },
+
+ // remove
+ remove: function() {
+ // remove event handler
+ $('body').off('mousedown.' + this.uuid);
+
+ // remove element from dom
+ this.$el.remove();
+ },
+
+ // remove
+ _hide : function(e) {
+ //the 'is' for buttons that trigger popups
+ //the 'has' for icons within a button that triggers a popup
+ if (!$(this.options.container).is(e.target) &&
+ !$(this.el).is(e.target) &&
+ $(this.el).has(e.target).length === 0) {
+ this.hide();
+ }
+ },
+
+ // template
+ _template: function(options) {
+ var tmpl = '<div class="popover-view popover fade ' + options.placement + ' in">' +
+ '<div class="arrow"></div>' +
+ '<div class="popover-title">' +
+ '<div class="popover-title-label">' +
+ options.title +
+ '</div>';
+
+ // add close icon
+ if (options.with_close) {
+ tmpl += '<div id="close" class="popover-close fa fa-times-circle"></div>';
+ }
+
+ // finalize
+ tmpl += '</div>' +
+ '<div class="popover-content"></div>' +
+ '</div>';
+
+ // return
+ return tmpl;
+ }
+});
+
+return {
+ View: View
+}
+
+});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/upload/upload-button.js
--- /dev/null
+++ b/static/scripts/mvc/upload/upload-button.js
@@ -0,0 +1,102 @@
+// dependencies
+define([], function() {
+
+// create model
+var Model = Backbone.Model.extend({
+ defaults: {
+ percentage : 0,
+ icon : 'fa-circle',
+ label : '',
+ status : ''
+ }
+});
+
+// progress bar button on ui
+var View = Backbone.View.extend({
+ // model
+ model : null,
+
+ // initialize
+ initialize : function(model) {
+ // link this
+ var self = this;
+
+ // create model
+ this.model = model;
+
+ // get options
+ this.options = this.model.attributes;
+
+ // create new element
+ this.setElement(this._template(this.options));
+
+ // add event
+ $(this.el).on('click', this.options.onclick);
+
+ // add tooltip
+ if (this.options.tooltip) {
+ $(this.el).tooltip({title: this.options.tooltip, placement: 'bottom'});
+ }
+
+ // events
+ this.model.on('change:percentage', function() {
+ self._percentage(self.model.get('percentage'));
+ });
+ this.model.on('change:status', function() {
+ self._status(self.model.get('status'));
+ });
+
+ // unload event
+ var self = this;
+ $(window).on('beforeunload', function() {
+ var text = "";
+ if (self.options.onunload) {
+ text = self.options.onunload();
+ }
+ if (text != "") {
+ return text;
+ }
+ });
+ },
+
+ // set status
+ _status: function(value) {
+ var $el = this.$el.find('.progress-bar');
+ $el.removeClass();
+ $el.addClass('progress-bar');
+ $el.addClass('progress-bar-notransition');
+ if (value != '') {
+ $el.addClass('progress-bar-' + value);
+ console.log($el);
+ }
+ },
+
+ // set percentage
+ _percentage: function(value) {
+ var $el = this.$el.find('.progress-bar');
+ $el.css({ width : value + '%' });
+ },
+
+ // template
+ _template: function(options) {
+ return '<div style="float: right">' +
+ '<div class="upload-button">' +
+ '<div class="progress">' +
+ '<div class="progress-bar"></div>' +
+ '</div>' +
+ '<div id="label" class="label">' +
+ '<a class="panel-header-button" href="javascript:void(0)">' +
+ '<span class="fa fa-upload"></span>' +
+ '</a>' +
+ '</div>' +
+ '</div>' +
+ '</div>';
+ }
+});
+
+return {
+ Model: Model,
+ View: View
+};
+
+});
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/upload/upload-ftp.js
--- /dev/null
+++ b/static/scripts/mvc/upload/upload-ftp.js
@@ -0,0 +1,173 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// item view
+return Backbone.View.extend({
+ // options
+ options: {
+ class_add : 'upload-icon-button fa fa-square-o',
+ class_remove : 'upload-icon-button fa fa-check-square-o'
+ },
+
+ // render
+ initialize: function(app) {
+ // link app
+ this.app = app;
+
+ // link this
+ var self = this;
+
+ // set template
+ this.setElement(this._template());
+
+ // load extension
+ Utils.jsonFromUrl(galaxy_config.root + 'api/ftp_files', function(ftp_files) { self._fill(ftp_files); });
+ },
+
+ // events
+ events: {
+ 'mousedown' : function(e) { e.preventDefault(); }
+ },
+
+ // fill table
+ _fill: function(ftp_files) {
+
+ if (ftp_files.length > 0) {
+ // add table
+ this.$el.find('#upload-ftp-content').html($(this._template_table()));
+
+ // add files to table
+ var size = 0;
+ for (key in ftp_files) {
+ this.add(ftp_files[key]);
+ size += ftp_files[key].size;
+ }
+
+ // update stats
+ this.$el.find('#upload-ftp-number').html(ftp_files.length + ' files');
+ this.$el.find('#upload-ftp-disk').html(Utils.bytesToString (size, true));
+ } else {
+ // add info
+ this.$el.find('#upload-ftp-content').html($(this._template_info()));
+ }
+
+ // hide spinner
+ this.$el.find('#upload-ftp-wait').hide();
+ },
+
+ // add
+ add: function(ftp_file) {
+ // create new item
+ var $it = $(this._template_row(ftp_file));
+
+ // append to table
+ $(this.el).find('tbody').append($it);
+
+ // find model and set initial 'add' icon class
+ var icon_class = '';
+ if (this._find(ftp_file)) {
+ icon_class = this.options.class_remove;
+ } else {
+ icon_class = this.options.class_add;
+ }
+ $it.find('#upload-ftp-add').addClass(icon_class);
+
+ // click to add ftp files
+ var self = this;
+ $it.find('#upload-ftp-add').on('click', function() {
+ // find model
+ var model_index = self._find(ftp_file);
+
+ // update icon
+ $(this).removeClass();
+
+ // add model
+ if (!model_index) {
+ // add to uploadbox
+ self.app.uploadbox.add([{
+ mode : 'ftp',
+ name : ftp_file.path,
+ size : ftp_file.size,
+ path : ftp_file.path
+ }]);
+
+ // add new icon class
+ $(this).addClass(self.options.class_remove);
+ } else {
+ // remove
+ self.app.collection.remove(model_index);
+
+ // add new icon class
+ $(this).addClass(self.options.class_add);
+ }
+ });
+ },
+
+ // get model index
+ _find: function(ftp_file) {
+ // check if exists already
+ var filtered = this.app.collection.where({file_path : ftp_file.path});
+ var model_index = null;
+ for (var key in filtered) {
+ var item = filtered[key];
+ if (item.get('status') == 'init' && item.get('file_mode') == 'ftp') {
+ model_index = item.get('id');
+ }
+ }
+ return model_index;
+ },
+
+ // template row
+ _template_row: function(options) {
+ return '<tr>' +
+ '<td><div id="upload-ftp-add"/></td>' +
+ '<td>' + options.path + '</td>' +
+ '<td style="white-space: nowrap;">' + Utils.bytesToString(options.size) + '</td>' +
+ '<td style="white-space: nowrap;">' + options.ctime + '</td>' +
+ '</tr>';
+ },
+
+ // load table template
+ _template_table: function()
+ {
+ return '<span style="whitespace: nowrap; float: left;">Available files: </span>' +
+ '<span style="whitespace: nowrap; float: right;">' +
+ '<span class="upload-icon fa fa-file-text-o"/>' +
+ '<span id="upload-ftp-number"/> ' +
+ '<span class="upload-icon fa fa-hdd-o"/>' +
+ '<span id="upload-ftp-disk"/>' +
+ '</span>' +
+ '<table class="grid">' +
+ '<thead>' +
+ '<tr>' +
+ '<th></th>' +
+ '<th>Name</th>' +
+ '<th>Size</th>' +
+ '<th>Created</th>' +
+ '</tr>' +
+ '</thead>' +
+ '<tbody></tbody>' +
+ '</table>';
+ },
+
+ // load table template
+ _template_info: function()
+ {
+ return '<div class="upload-ftp-warning warningmessage">' +
+ 'Your FTP directory does not contain any files.' +
+ '</div>';
+ },
+
+ // load html template
+ _template: function()
+ {
+ return '<div class="upload-ftp">' +
+ '<div id="upload-ftp-wait" class="upload-ftp-wait fa fa-spinner fa-spin"/>' +
+ '<div class="upload-ftp-help">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>' + this.app.options.ftp_upload_site + '</strong> using your Galaxy credentials (email address and password).</div>' +
+ '<div id="upload-ftp-content"></div>' +
+ '<div>';
+ }
+
+});
+
+});
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/upload/upload-model.js
--- a/static/scripts/mvc/upload/upload-model.js
+++ b/static/scripts/mvc/upload/upload-model.js
@@ -7,9 +7,16 @@
extension : 'auto',
genome : '?',
url_paste : '',
+ status : 'init',
+ info : null,
+ file_mode : 'local',
+ file_size : 0,
+ file_type : null,
+ file_path : '',
+
+ // settings
space_to_tabs : false,
- status : 'init',
- info : null
+ to_posix_lines : true
}
});
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/upload/upload-row.js
--- a/static/scripts/mvc/upload/upload-row.js
+++ b/static/scripts/mvc/upload/upload-row.js
@@ -1,5 +1,16 @@
// dependencies
-define(['mvc/upload/upload-model', 'mvc/upload/upload-extensions'], function(UploadModel, UploadExtensions) {
+define(['utils/utils',
+ 'mvc/upload/upload-model',
+ 'mvc/upload/upload-extensions',
+ 'mvc/upload/upload-settings',
+ 'mvc/ui.popover'],
+
+ function( Utils,
+ UploadModel,
+ UploadExtensions,
+ UploadSettings,
+ Popover
+ ) {
// item view
return Backbone.View.extend({
@@ -11,13 +22,16 @@
// states
status_classes : {
- init : 'symbol fa fa-trash-o',
- queued : 'symbol fa fa-spinner fa-spin',
- running : 'symbol fa fa-spinner fa-spin',
- success : 'symbol fa fa-check',
- error : 'symbol fa fa-exclamation-triangle'
+ init : 'upload-icon-button fa fa-trash-o',
+ queued : 'upload-icon fa fa-spinner fa-spin',
+ running : 'upload-icon fa fa-spinner fa-spin',
+ success : 'upload-icon-button fa fa-check',
+ error : 'upload-icon-button fa fa-exclamation-triangle'
},
+ // handle for settings popover
+ settings: null,
+
// render
initialize: function(app, options) {
// link app
@@ -35,36 +49,32 @@
// link item
var it = this.$el;
+ // append popup to settings icon
+ this.settings = new Popover.View({
+ title : 'Upload configuration',
+ container : it.find('#settings'),
+ placement : 'bottom'
+ });
+
+ //
+ // ui events
+ //
+
// handle click event
- it.find('#symbol').on('click', function() {
- // get current status
- var status = self.model.get('status');
-
- // only remove from queue if not in processing line
- if (status == 'init' || status == 'success' || status == 'error')
- {
- // remove from collection
- self.app.collection.remove(self.model);
- }
- });
+ it.find('#symbol').on('click', function() { self._removeRow(); });
- // handle mouse over
- it.find('#extension_info').on('mouseover' , function() { self._showExtensionInfo(); })
- .on('mouseleave', function() { self._hideExtensionInfo(); });
+ // handle extension info popover
+ it.find('#extension-info').on('click' , function(e) { self._showExtensionInfo(); })
+ .on('mousedown', function(e) { e.preventDefault(); });
+
+ // handle settings popover
+ it.find('#settings').on('click' , function(e) { self._showSettings(); })
+ .on('mousedown', function(e) { e.preventDefault(); });
// handle text editing event
- it.find('#text-content').on('keyup', function() {
- // get properties
- var $el = it.find('#text-content');
- var value = $el.val();
- var count = value.length;
-
- // update size string
- it.find('#size').html(self._formatSize (count));
-
- // update url paste content
- self.model.set('url_paste', value);
- self.model.set('file_size', count);
+ it.find('#text-content').on('keyup', function(e) {
+ self.model.set('url_paste', $(e.target).val());
+ self.model.set('file_size', $(e.target).val().length);
});
// handle genome selection
@@ -75,7 +85,6 @@
// handle extension selection
it.find('#extension').on('change', function(e) {
self.model.set('extension', $(e.target).val());
- self.$el.find('#extension_info').popover('destroy');
});
// handle space to tabs button
@@ -83,19 +92,27 @@
self.model.set('space_to_tabs', $(e.target).prop('checked'));
});
- // events
+ //
+ // model events
+ //
this.model.on('change:percentage', function() {
self._refreshPercentage();
});
this.model.on('change:status', function() {
self._refreshStatus();
});
+ this.model.on('change:extension', function() {
+ self._destroyExtensionInfo();
+ });
this.model.on('change:info', function() {
self._refreshInfo();
});
this.model.on('change:genome', function() {
self._refreshGenome();
});
+ this.model.on('change:file_size', function() {
+ self._refreshFileSize();
+ });
this.model.on('remove', function() {
self._destroyExtensionInfo();
self.remove();
@@ -109,8 +126,9 @@
// render
render: function() {
// read model
- var file_name = this.model.get('file_name');
- var file_size = this.model.get('file_size');
+ var file_name = this.model.get('file_name');
+ var file_size = this.model.get('file_size');
+ var file_mode = this.model.get('file_mode');
// link item
var it = this.$el;
@@ -119,10 +137,14 @@
it.find('#title').html(file_name);
// update info
- it.find('#size').html(this._formatSize (file_size));
+ it.find('#size').html(Utils.bytesToString (file_size));
- // activate text field if file content is zero
- if (file_size == -1)
+ // remove mode class
+ it.find('#mode').removeClass()
+ .addClass('mode');
+
+ // activate text field if file is new
+ if (file_mode == 'new')
{
// get text component
var text = it.find('#text');
@@ -141,9 +163,28 @@
// show text field
text.show();
+
+ // update icon
+ it.find('#mode').addClass('fa fa-pencil');
+ }
+
+ // file from local disk
+ if (file_mode == 'local') {
+ // update icon
+ it.find('#mode').addClass('fa fa-laptop');
+ }
+
+ // file from ftp
+ if (file_mode == 'ftp') {
+ // update icon
+ it.find('#mode').addClass('fa fa-code-fork');
}
},
+ //
+ // handle model events
+ //
+
// genome
_refreshGenome: function()
{
@@ -218,45 +259,69 @@
}
},
- // to string
- _formatSize : function (size)
- {
- // identify unit
- var unit = "";
- if (size >= 100000000000) { size = size / 100000000000; unit = 'TB'; } else
- if (size >= 100000000) { size = size / 100000000; unit = 'GB'; } else
- if (size >= 100000) { size = size / 100000; unit = 'MB'; } else
- if (size >= 100) { size = size / 100; unit = 'KB'; } else
- if (size > 0) { size = size * 10; unit = 'b'; } else
- return '<strong>-</strong>';
-
- // return formatted string
- return '<strong>' + (Math.round(size) / 10) + '</strong> ' + unit;
+ // refresh size
+ _refreshFileSize: function() {
+ var count = this.model.get('file_size');
+ this.$el.find('#size').html(Utils.bytesToString (count));
+ },
+
+ //
+ // handle ui events
+ //
+
+ // remove row
+ _removeRow: function() {
+ // get current status
+ var status = this.model.get('status');
+
+ // only remove from queue if not in processing line
+ if (status == 'init' || status == 'success' || status == 'error') {
+ // remove from collection
+ this.app.collection.remove(this.model);
+ }
},
// attach file info popup
_showExtensionInfo : function()
{
// initialize
- var self = this;
- var $el = $(this.el).find('#extension_info');
+ var $el = $(this.el).find('#extension-info');
var extension = this.model.get('extension');
var title = $(this.el).find('#extension').find('option:selected').text();
// create popup
- $el.popover({
- html: true,
- title: title,
- content: UploadExtensions(extension),
- placement: 'bottom',
- container: self.$el.parent()
- });
+ if (!this.extension_popup) {
+ this.extension_popup = new Popover.View({
+ content: UploadExtensions(extension),
+ placement: 'bottom',
+ container: $el
+ });
+ }
- // show popup
- $el.popover('show');
-
- // clear previous timers
- clearTimeout(this.popover_timeout);
+ // show / hide popup
+ if (!this.extension_popup.visible) {
+ this.extension_popup.title(title);
+ this.extension_popup.empty();
+ this.extension_popup.append(UploadExtensions(extension));
+ this.extension_popup.show();
+ } else {
+ this.extension_popup.hide();
+ }
+ },
+
+ // attach file info popup
+ _showSettings : function()
+ {
+ // check if popover is visible
+ if (!this.settings.visible) {
+ // show popover
+ this.settings.empty();
+ this.settings.append((new UploadSettings(this)).$el);
+ this.settings.show();
+ } else {
+ // hide popover
+ this.settings.hide();
+ }
},
// attach file info popup
@@ -272,9 +337,9 @@
// attach file info popup
_destroyExtensionInfo : function()
{
- this.$el.find('#extension_info').popover('destroy');
+ this.$el.find('#extension-info').popover('destroy');
},
-
+
// template
_template: function(options)
{
@@ -285,6 +350,7 @@
var tmpl = '<tr id="upload-item-' + options.id + '" class="upload-item">' +
'<td>' +
'<div style="position: relative;">' +
+ '<div id="mode"></div>' +
'<div id="title" class="title"></div>' +
'<div id="text" class="text">' +
'<div class="text-info">You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.</div>' +
@@ -292,7 +358,9 @@
'</div>' +
'</div>' +
'</td>' +
- '<td><div id="size" class="size"></div></td>';
+ '<td>' +
+ '<div id="size" class="size"></div>' +
+ '</td>';
// add file type selectore
tmpl += '<td>' +
@@ -300,7 +368,7 @@
for (key in self.app.select_extension)
tmpl += '<option value="' + self.app.select_extension[key][1] + '">' + self.app.select_extension[key][0] + '</option>';
tmpl += '</select>' +
- ' <i id="extension_info" class="fa fa-search" style="cursor: pointer;"/>' +
+ ' <i id="extension-info" class="upload-icon-button fa fa-search"/>' +
'</td>';
// add genome selector
@@ -312,7 +380,7 @@
'</td>';
// add next row
- tmpl += '<td><input id="space_to_tabs" type="checkbox"></input></td>' +
+ tmpl += '<td><div id="settings" class="upload-icon-button fa fa-gear"></div>' +
'<td>' +
'<div id="info" class="info">' +
'<div class="progress">' +
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/upload/upload-settings.js
--- /dev/null
+++ b/static/scripts/mvc/upload/upload-settings.js
@@ -0,0 +1,102 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// item view
+return Backbone.View.extend({
+ // options
+ options: {
+ class_check : 'upload-icon-button fa fa-check-square-o',
+ class_uncheck : 'upload-icon-button fa fa-square-o'
+ },
+
+ // render
+ initialize: function(app) {
+ // link app
+ this.app = app;
+
+ // link this
+ var self = this;
+
+ // set template
+ this.setElement(this._template());
+
+ // link model
+ this.model = this.app.model;
+
+ // ui event: space to tabs
+ this.$el.find('#upload-space-to-tabs').on('click', function() {
+ self._switch_state('#upload-space-to-tabs', 'space_to_tabs');
+ });
+
+ // ui event: to posix
+ this.$el.find('#upload-to-posix-lines').on('click', function() {
+ self._switch_state('#upload-to-posix-lines', 'to_posix_lines');
+ });
+
+ // render
+ this.render();
+ },
+
+ // events
+ events: {
+ 'mousedown' : function(e) { e.preventDefault(); }
+ },
+
+ // render
+ render: function() {
+ // render states
+ this._render_state('#upload-space-to-tabs', this.model.get('space_to_tabs'));
+ this._render_state('#upload-to-posix-lines', this.model.get('to_posix_lines'));
+
+ // disable options
+ var $cover = this.$el.find('#upload-settings-cover');
+ if (this.model.get('status') != 'init') {
+ $cover.show();
+ } else {
+ $cover.hide();
+ }
+ },
+
+ // switch state
+ _switch_state: function (element_id, parameter_id) {
+ if (this.model.get('status') == 'init') {
+ var checked = !this.model.get(parameter_id);
+ this.model.set(parameter_id, checked);
+ this._render_state(element_id, checked);
+ }
+ },
+
+ // render state
+ _render_state: function (element_id, checked) {
+ // swith icon class
+ var $it = this.$el.find(element_id);
+ $it.removeClass();
+ if (checked) {
+ $it.addClass(this.options.class_check);
+ } else {
+ $it.addClass(this.options.class_uncheck);
+ }
+ },
+
+ // load template
+ _template: function()
+ {
+ return '<div class="upload-settings" style="position: relative;">' +
+ '<div id="upload-settings-cover" class="upload-settings-cover"/>' +
+ '<table class="table table-striped">' +
+ '<tbody>' +
+ '<tr>' +
+ '<td><div id="upload-space-to-tabs"/></td>' +
+ '<td>Convert spaces to tabs</td>' +
+ '</tr>' +
+ '<tr>' +
+ '<td><div id="upload-to-posix-lines"/></td>' +
+ '<td>Use POSIX standard</td>' +
+ '</tr>' +
+ '</tbody>' +
+ '</table>' +
+ '</div>';
+ }
+});
+
+});
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -1,117 +1,36 @@
// dependencies
define(["galaxy.modal",
"utils/utils",
+ "mvc/upload/upload-button",
"mvc/upload/upload-model",
"mvc/upload/upload-row",
+ "mvc/upload/upload-ftp",
+ "mvc/ui.popover",
"mvc/ui",
"utils/uploadbox"],
function( Modal,
Utils,
+ UploadButton,
UploadModel,
- UploadItem
+ UploadItem,
+ UploadFtp,
+ Popover
) {
-// create model
-var ProgressButtonModel = Backbone.Model.extend({
- defaults: {
- percentage : 0,
- icon : 'fa-circle',
- label : '',
- status : ''
- }
-});
-
-// progress bar button on ui
-var ProgressButton = Backbone.View.extend({
- // model
- model : null,
-
- // initialize
- initialize : function(model) {
- // link this
- var self = this;
-
- // create model
- this.model = model;
-
- // get options
- this.options = this.model.attributes;
-
- // create new element
- this.setElement(this._template(this.options));
-
- // add event
- $(this.el).on('click', this.options.onclick);
-
- // add tooltip
- if (this.options.tooltip) {
- $(this.el).tooltip({title: this.options.tooltip, placement: 'bottom'});
- }
-
- // events
- this.model.on('change:percentage', function() {
- self._percentage(self.model.get('percentage'));
- });
- this.model.on('change:status', function() {
- self._status(self.model.get('status'));
- });
-
- // unload event
- var self = this;
- $(window).on('beforeunload', function() {
- var text = "";
- if (self.options.onunload) {
- text = self.options.onunload();
- }
- if (text != "") {
- return text;
- }
- });
- },
-
- // set status
- _status: function(value) {
- var $el = this.$el.find('.progress-bar');
- $el.removeClass();
- $el.addClass('progress-bar');
- $el.addClass('progress-bar-notransition');
- if (value != '') {
- $el.addClass('progress-bar-' + value);
- }
- },
-
- // set percentage
- _percentage: function(value) {
- var $el = this.$el.find('.progress-bar');
- $el.css({ width : value + '%' });
- },
-
- // template
- _template: function(options) {
- return '<div style="float: right">' +
- '<div class="progress-button">' +
- '<div class="progress">' +
- '<div class="progress-bar"></div>' +
- '</div>' +
- '<div id="label" class="label">' +
- '<a class="panel-header-button" href="javascript:void(0)">' +
- '<span class="fa fa-upload"></span>' +
- '</a>' +
- '</div>' +
- '</div>' +
- '</div>';
- }
-});
-
// galaxy upload
return Backbone.View.extend(
{
+ // options
+ options : {
+ nginx_upload_path : ''
+ },
+
// own modal
modal : null,
// button
- button_show : null,
+ ui_button : null,
// jquery uploadbox plugin
uploadbox: null,
@@ -131,6 +50,9 @@
// collection
collection : new UploadModel.Collection(),
+ // ftp file viewer
+ ftp : null,
+
// counter
counter : {
// stats
@@ -140,36 +62,29 @@
running : 0,
// reset stats
- reset : function()
- {
+ reset : function() {
this.announce = this.success = this.error = this.running = 0;
}
},
-
- // options
- options : {
- nginx_upload_path : ''
- },
-
+
// initialize
- initialize : function(options)
- {
+ initialize : function(options) {
// link this
var self = this;
// wait for galaxy history panel (workaround due to the use of iframes)
- if (!Galaxy.currHistoryPanel || !Galaxy.currHistoryPanel.model)
- {
+ if (!Galaxy.currHistoryPanel || !Galaxy.currHistoryPanel.model) {
window.setTimeout(function() { self.initialize() }, 500)
return;
}
// check if logged in
- if (!Galaxy.currUser.get('id'))
+ if (!Galaxy.currUser.get('id')) {
return;
+ }
// create model
- this.button_show = new ProgressButtonModel({
+ this.ui_button = new UploadButton.Model({
icon : 'fa-upload',
tooltip : 'Download from URL or upload files from disk',
label : 'Load Data',
@@ -186,7 +101,7 @@
});
// define location
- $('#left .unified-panel-header-inner').append((new ProgressButton(this.button_show)).$el);
+ $('#left .unified-panel-header-inner').append((new UploadButton.View(this.ui_button)).$el);
// load extension
var self = this;
@@ -242,33 +157,29 @@
//
// show/hide upload frame
- _eventShow : function (e)
- {
+ _eventShow : function (e) {
// prevent default
e.preventDefault();
- // stop propagation of event (for click-outside-of-modal-to-close functionality)
- e.stopPropagation();
// create modal
- if (!this.modal)
- {
+ if (!this.modal) {
// make modal
var self = this;
- this.modal = new Modal.GalaxyModal(
- {
+ this.modal = new Modal.GalaxyModal({
title : 'Download data directly from web or upload files from your disk',
body : this._template('upload-box', 'upload-info'),
buttons : {
- 'Choose files' : function() {self.uploadbox.select()},
- 'Create file' : function() {self._eventCreate()},
- 'Start' : function() {self._eventStart()},
- 'Pause' : function() {self._eventStop()},
- 'Reset' : function() {self._eventReset()},
- 'Close' : function() {self.modal.hide()},
+ 'Choose local file' : function() {self.uploadbox.select()},
+ 'Choose FTP file' : function() {self._eventFtp()},
+ 'Create new file' : function() {self._eventCreate()},
+ 'Start' : function() {self._eventStart()},
+ 'Pause' : function() {self._eventStop()},
+ 'Reset' : function() {self._eventReset()},
+ 'Close' : function() {self.modal.hide()},
},
height : '400',
width : '900',
- closing_events : true
+ closing_events : true
});
// set element
@@ -276,8 +187,7 @@
// file upload
var self = this;
- this.uploadbox = this.$el.uploadbox(
- {
+ this.uploadbox = this.$el.uploadbox({
announce : function(index, file, message) { self._eventAnnounce(index, file, message) },
initialize : function(index, file, message) { return self._eventInitialize(index, file, message) },
progress : function(index, file, message) { self._eventProgress(index, file, message) },
@@ -288,6 +198,17 @@
// setup info
this._updateScreen();
+
+ // add ftp file viewer
+ if (this.options.ftp_upload_dir && this.options.ftp_upload_site) {
+ var button = this.modal.getButton('Choose FTP file');
+ this.ftp = new Popover.View({
+ title : 'FTP files',
+ container : button
+ });
+ } else {
+ this.modal.hideButton('Choose FTP file');
+ }
}
// show modal
@@ -299,8 +220,7 @@
//
// remove item from upload list
- _eventRemove : function(item)
- {
+ _eventRemove : function(item) {
// update status
var status = item.get('status');
@@ -325,8 +245,7 @@
//
// a new file has been dropped/selected through the uploadbox plugin
- _eventAnnounce : function(index, file, message)
- {
+ _eventAnnounce : function(index, file, message) {
// update counter
this.counter.announce++;
@@ -337,22 +256,23 @@
var upload_item = new UploadItem(this, {
id : index,
file_name : file.name,
- file_size : file.size
+ file_size : file.size,
+ file_mode : file.mode,
+ file_path : file.path
});
// add to collection
this.collection.add(upload_item.model);
// add upload item element to table
- $(this.el).find('tbody:last').append(upload_item.$el);
+ $(this.el).find('tbody:first').append(upload_item.$el);
// render
upload_item.render();
},
// the uploadbox plugin is initializing the upload for this file
- _eventInitialize : function(index, file, message)
- {
+ _eventInitialize : function(index, file, message) {
// get element
var it = this.collection.get(index);
@@ -360,26 +280,38 @@
it.set('status', 'running');
// get configuration
- var file_type = it.get('extension');
var file_name = it.get('file_name');
+ var file_path = it.get('file_path');
+ var file_mode = it.get('file_mode');
+ var extension = it.get('extension');
var genome = it.get('genome');
var url_paste = it.get('url_paste');
var space_to_tabs = it.get('space_to_tabs');
+ var to_posix_lines = it.get('to_posix_lines');
// validate
if (!url_paste && !(file.size > 0))
return null;
// configure uploadbox
- this.uploadbox.configure({url : this.options.nginx_upload_path, paramname : "files_0|file_data"});
+ this.uploadbox.configure({url : this.options.nginx_upload_path});
+
+ // configure file mode
+ if (file_mode == 'ftp') {
+ this.uploadbox.configure({paramname : ''});
+ } else {
+ this.uploadbox.configure({paramname : 'files_0|file_data'});
+ }
// configure tool
tool_input = {};
tool_input['dbkey'] = genome;
- tool_input['file_type'] = file_type;
+ tool_input['file_type'] = extension;
tool_input['files_0|type'] = 'upload_dataset';
tool_input['files_0|url_paste'] = url_paste;
+ tool_input['files_0|ftp_files'] = file_path;
tool_input['space_to_tabs'] = space_to_tabs;
+ tool_input['to_posix_lines'] = to_posix_lines;
// setup data
data = {};
@@ -392,19 +324,17 @@
},
// progress
- _eventProgress : function(index, file, percentage)
- {
+ _eventProgress : function(index, file, percentage) {
// set progress for row
var it = this.collection.get(index);
it.set('percentage', percentage);
// update ui button
- this.button_show.set('percentage', this._upload_percentage(percentage, file.size));
+ this.ui_button.set('percentage', this._upload_percentage(percentage, file.size));
},
// success
- _eventSuccess : function(index, file, message)
- {
+ _eventSuccess : function(index, file, message) {
// update status
var it = this.collection.get(index);
it.set('status', 'success');
@@ -413,7 +343,7 @@
var file_size = it.get('file_size');
// update ui button
- this.button_show.set('percentage', this._upload_percentage(100, file_size));
+ this.ui_button.set('percentage', this._upload_percentage(100, file_size));
// update completed
this.upload_completed += file_size * 100;
@@ -430,8 +360,7 @@
},
// error
- _eventError : function(index, file, message)
- {
+ _eventError : function(index, file, message) {
// get element
var it = this.collection.get(index);
@@ -440,8 +369,8 @@
it.set('info', message);
// update ui button
- this.button_show.set('percentage', this._upload_percentage(100, file.size));
- this.button_show.set('status', 'danger');
+ this.ui_button.set('percentage', this._upload_percentage(100, file.size));
+ this.ui_button.set('status', 'danger');
// update completed
this.upload_completed += file.size * 100;
@@ -472,10 +401,27 @@
// events triggered by this view
//
- // create (pseudo) file
+ _eventFtp: function() {
+ // check if popover is visible
+ if (!this.ftp.visible) {
+ // show popover
+ this.ftp.empty();
+ this.ftp.append((new UploadFtp(this)).$el);
+ this.ftp.show();
+ } else {
+ // hide popover
+ this.ftp.hide();
+ }
+ },
+
+ // create a new file
_eventCreate : function ()
{
- this.uploadbox.add([{ name : 'New File', size : -1 }]);
+ this.uploadbox.add([{
+ name : 'New File',
+ size : 0,
+ mode : 'new'
+ }]);
},
// start upload process
@@ -498,8 +444,8 @@
});
// reset progress
- this.button_show.set('percentage', 0);
- this.button_show.set('status', 'success');
+ this.ui_button.set('percentage', 0);
+ this.ui_button.set('status', 'success');
// backup current history
this.current_history = Galaxy.currHistoryPanel.model.get('id');
@@ -520,7 +466,7 @@
}
// show upload has paused
- this.button_show.set('status', 'info');
+ this.ui_button.set('status', 'info');
// request pause
this.uploadbox.stop();
@@ -547,13 +493,12 @@
this.uploadbox.reset();
// reset button
- this.button_show.set('percentage', 0);
+ this.ui_button.set('percentage', 0);
}
},
// set screen
- _updateScreen: function ()
- {
+ _updateScreen: function () {
/*
update on screen info
*/
@@ -600,18 +545,20 @@
// select upload button
if (this.counter.running == 0)
{
- this.modal.enableButton('Choose files');
- this.modal.enableButton('Create file');
+ this.modal.enableButton('Choose local file');
+ this.modal.enableButton('Choose FTP file');
+ this.modal.enableButton('Create new file');
} else {
- this.modal.disableButton('Choose files');
- this.modal.disableButton('Create file');
+ this.modal.disableButton('Choose local file');
+ this.modal.disableButton('Choose FTP file');
+ this.modal.disableButton('Create new file');
}
// table visibility
if (this.counter.announce + this.counter.success + this.counter.error > 0)
- $(this.el).find('table').show();
+ $(this.el).find('#upload-table').show();
else
- $(this.el).find('table').hide();
+ $(this.el).find('#upload-table').hide();
},
// calculate percentage of all queued uploads
@@ -620,17 +567,16 @@
},
// load html template
- _template: function(id, idInfo)
- {
+ _template: function(id, idInfo) {
return '<div id="' + id + '" class="upload-box">' +
- '<table class="table table-striped" style="display: none;">' +
+ '<table id="upload-table" class="table table-striped" style="display: none;">' +
'<thead>' +
'<tr>' +
'<th>Name</th>' +
'<th>Size</th>' +
'<th>Type</th>' +
'<th>Genome</th>' +
- '<th>Space→Tab</th>' +
+ '<th>Settings</th>' +
'<th>Status</th>' +
'<th></th>' +
'</tr>' +
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/galaxy.modal.js
--- a/static/scripts/packed/galaxy.modal.js
+++ b/static/scripts/packed/galaxy.modal.js
@@ -1,1 +1,1 @@
-define([],function(){var a=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"galaxy-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(b){if(b){this._create(b)}},show:function(b){this.initialize(b);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",true)},showButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).show()},hideButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).hide()},scrollTop:function(){return this.$body.scrollTop()},_create:function(d){var c=this;this.options=_.defaults(d,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove();$(document).off("keyup")}this.setElement(this._template(this.options.title));this.$dialog=(this.$el).find(".modal-dialog");this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var b=0;$.each(this.options.buttons,function(e,g){var f="button-"+b++;c.$buttons.append($('<button id="'+f+'"></button>').text(e).click(g)).append(" ");c.buttonList[e]=f})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){c.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){c.hide()})}},_template:function(b){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+b+'</h4></div><div class="modal-body"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{GalaxyModal:a}});
\ No newline at end of file
+define([],function(){var a=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"galaxy-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(b){if(b){this._create(b)}},show:function(b){this.initialize(b);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",true)},showButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).show()},hideButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).hide()},getButton:function(b){var c=this.buttonList[b];return this.$buttons.find("#"+c)},scrollTop:function(){return this.$body.scrollTop()},_create:function(d){var c=this;this.options=_.defaults(d,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove();$(document).off("keyup")}this.setElement(this._template(this.options.title));this.$dialog=(this.$el).find(".modal-dialog");this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var b=0;$.each(this.options.buttons,function(e,g){var f="button-"+b++;c.$buttons.append($('<button id="'+f+'"></button>').text(e).click(g)).append(" ");c.buttonList[e]=f})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){c.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){c.hide()})}},_template:function(b){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+b+'</h4></div><div class="modal-body" style="position: static;"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{GalaxyModal:a}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/grid/grid-template.js
--- a/static/scripts/packed/mvc/grid/grid-template.js
+++ b/static/scripts/packed/mvc/grid/grid-template.js
@@ -1,1 +1,1 @@
-define([],function(){return{grid:function(b){var a="";if(b.embedded){a=this.grid_header(b)+this.grid_table(b)}else{a='<div class="loading-elt-overlay"></div><table><tr><td width="75%">'+this.grid_header(b)+'</td><td></td><td></td></tr><tr><td width="100%" id="grid-message" valign="top"></td><td></td><td></td></tr></table>'+this.grid_table(b)}if(b.info_text){a+='<br><div class="toolParamHelp" style="clear: both;">'+b.info_text+"</div>"}return a},grid_table:function(a){return'<form method="post" onsubmit="return false;"><table id="grid-table" class="grid"><thead id="grid-table-header"></thead><tbody id="grid-table-body"></tbody><tfoot id="grid-table-footer"></tfoot></table></form>'},grid_header:function(c){var b='<div class="grid-header">';if(!c.embedded){b+="<h2>"+c.title+"</h2>"}if(c.global_actions){b+='<ul class="manage-table-actions">';var d=(c.global_actions.length>=3);if(d){b+='<li><a class="action-button" id="popup-global-actions" class="menubutton">Actions</a></li><div popupmenu="popup-global-actions">'}for(i in c.global_actions){var e=c.global_actions[i];var a="";if(e.inbound){a="use-inbound"}else{a="use-outbound"}b+='<li><a class="action-button '+a+'" href="'+e.url_args+'" onclick="return false;">'+e.label+"</a></li>"}if(d){b+="</div>"}b+="</ul>"}if(c.insert){b+=c.insert}b+=this.grid_filters(c);b+="</div>";return b},header:function(b){var a="<tr>";if(b.show_item_checkboxes){a+="<th>";if(b.items.length>0){a+='<input type="checkbox" id="check_all" name=select_all_checkbox value="true"><input type="hidden" name=select_all_checkbox value="true">'}a+="</th>"}for(var c in b.columns){var d=b.columns[c];if(d.visible){a+='<th id="'+d.key+'-header">';if(d.href){a+='<a href="'+d.href+'" class="sort-link" sort_key="'+d.key+'">'+d.label+"</a>"}else{a+=d.label}a+='<span class="sort-arrow">'+d.extra+"</span></th>"}}a+="</tr>";return a},body:function(r){var k="";var s=0;var e=r.items.length;if(e==0){k+='<tr><td colspan="100"><em>No Items</em></td></tr>';s=1}for(var f in r.items){var p=r.items[f];var a=p.encode_id;var g="grid-"+f+"-popup";k+="<tr ";if(r.current_item_id==p.id){k+='class="current"'}k+=">";if(r.show_item_checkboxes){k+='<td style="width: 1.5em;"><input type="checkbox" name="id" value="'+a+'" id="'+a+'" class="grid-row-select-checkbox" /></td>'}for(j in r.columns){var d=r.columns[j];if(d.visible){var c="";if(d.nowrap){c='style="white-space:nowrap;"'}var q=p.column_config[d.label];var h=q.link;var l=q.value;var o=q.inbound;if(jQuery.type(l)==="string"){l=l.replace(/\/\//g,"/")}var b="";var n="";if(d.attach_popup){b="grid-"+f+"-popup";n="menubutton";if(h!=""){n+=" split"}n+=" popup"}k+="<td "+c+">";if(h){if(r.operations.length!=0){k+='<div id="'+b+'" class="'+n+'" style="float: left;">'}var m="";if(o){m="use-inbound"}else{m="use-outbound"}k+='<a class="label '+m+'" href="'+h+'" onclick="return false;">'+l+"</a>";if(r.operations.length!=0){k+="</div>"}}else{k+='<div id="'+b+'" class="'+n+'"><label id="'+d.label_id_prefix+a+'" for="'+a+'">'+l+"</label></div>"}k+="</td>"}}k+="</tr>";s++}return k},footer:function(o){var k="";if(o.use_paging&&o.num_pages>1){var m=o.num_page_links;var a=o.cur_page_num;var n=o.num_pages;var h=m/2;var g=a-h;var e=0;if(g==0){g=1;e=h-(a-g)}var d=h+e;var c=a+d;if(c<=n){max_offset=0}else{c=n;max_offset=d-(c+1-a)}if(max_offset!=0){g-=max_offset;if(g<1){g=1}}k+='<tr id="page-links-row">';if(o.show_item_checkboxes){k+="<td></td>"}k+='<td colspan="100"><span id="page-link-container">Page:';if(g>1){k+='<span class="page-link" id="page-link-1"><a href="javascript:void(0);" page_num="1" onclick="return false;">1</a></span> ...'}for(var l=g;l<c+1;l++){if(l==o.cur_page_num){k+='<span class="page-link inactive-link" id="page-link-'+l+'">'+l+"</span>"}else{k+='<span class="page-link" id="page-link-'+l+'"><a href="javascript:void(0);" onclick="return false;" page_num="'+l+'">'+l+"</a></span>"}}if(c<n){k+='...<span class="page-link" id="page-link-'+n+'"><a href="javascript:void(0);" onclick="return false;" page_num="'+n+'">'+n+"</a></span>"}k+="</span>";k+='<span class="page-link" id="show-all-link-span"> | <a href="javascript:void(0);" onclick="return false;" page_num="all">Show All</a></span></td></tr>'}if(o.show_item_checkboxes){k+='<tr><input type="hidden" id="operation" name="operation" value=""><td></td><td colspan="100">For <span class="grid-selected-count"></span> selected '+o.get_class_plural+": ";for(i in o.operations){var b=o.operations[i];if(b.allow_multiple){k+='<input type="button" value="'+b.label+'" class="operation-button action-button"> '}}k+="</td></tr>"}var f=false;for(i in o.operations){if(o.operations[i].global_operation){f=true;break}}if(f){k+='<tr><td colspan="100">';for(i in o.operations){var b=o.operations[i];if(b.global_operation){k+='<a class="action-button" href="'+b.global_operation+'">'+b.label+"</a>"}}k+="</td></tr>"}if(o.legend){k+='<tr><td colspan="100">'+o.legend+"</td></tr>"}return k},message:function(a){return'<p><div class="'+a.status+'message transient-message">'+a.message+'</div><div style="clear: both"></div></p>'},grid_filters:function(n){var a=n.default_filter_dict;var b=n.filters;var e="none";if(n.advanced_search){e="block"}var m=false;for(var g in n.columns){var d=n.columns[g];if(d.filterable=="advanced"){var l=d.key;var c=b[l];var f=a[l];if(c&&f&&c!=f){e="block"}m=true}}var k="block";if(e=="block"){k="none"}var h='<div id="standard-search" style="display: '+k+';"><table><tr><td style="padding: 0;"><table>';for(var g in n.columns){var d=n.columns[g];if(d.filterable=="standard"){h+=this.grid_column_filter(n,d)}}h+="</table></td></tr><tr><td>";if(m){h+='<a href="" class="advanced-search-toggle">Advanced Search</a>'}h+="</td></tr></table></div>";h+='<div id="advanced-search" style="display: '+e+'; margin-top: 5px; border: 1px solid #ccc;"><table><tr><td style="text-align: left" colspan="100"><a href="" class="advanced-search-toggle">Close Advanced Search</a></td></tr>';for(var g in n.columns){var d=n.columns[g];if(d.filterable=="advanced"){h+=this.grid_column_filter(n,d)}}h+="</table></div>";return h},grid_column_filter:function(e,c){var t=e.default_filter_dict;var l=e.filters;var a=c.label;var b=c.key;if(c.filterable=="advanced"){a=a.toLowerCase()}var k="<tr>";if(c.filterable=="advanced"){k+='<td align="left" style="padding-left: 10px">'+a+":</td>"}k+='<td style="padding-bottom: 1px;">';if(c.is_text){k+='<form class="text-filter-form" column_key="'+b+'" action="'+e.url+'" method="get" >';for(u in e.columns){var g=e.columns[u];var p=l[g.key];if(p){if(p!="All"){if(g.is_text){p=JSON.stringify(p)}k+='<input type="hidden" id="'+g.key+'" name="f-'+g.key+'" value="'+p+'"/>'}}}k+='<span id="'+b+'-filtering-criteria">';var h=l[b];if(h){var f=jQuery.type(h);if(f=="string"){if(h!="All"){k+=this.filter_element(b,h)}}if(f=="array"){for(var u in h){var n=h[u];var v=h;v=v.slice(u);k+=this.filter_element(b,n)}}}k+="</span>";var r="";if(c.filterable=="standard"){r=c.label.toLowerCase();var q=r.length;if(q<20){q=20}q=q+4}k+='<span class="search-box"><input class="search-box-input" id="input-'+b+'-filter" name="f-'+b+'" type="text" placeholder="'+r+'" size="'+q+'"/><button type="submit" style="background: transparent; border: none; padding: 4px; margin: 0px;"><i class="fa fa-plus-circle"></i></button></span></form>'}else{k+='<span id="'+b+'-filtering-criteria">';var s=false;for(cf_label in e.categorical_filters[b]){var o=e.categorical_filters[b][cf_label];var d="";var m="";for(key in o){d=key;m=o[key]}if(s){k+=" | "}s=true;var n=l[b];if(n&&o[b]&&n==m){k+='<span class="categorical-filter '+b+'-filter current-filter">'+cf_label+"</span>"}else{k+='<span class="categorical-filter '+b+'-filter"><a href="javascript:void(0);" filter_key="'+d+'" filter_val="'+m+'">'+cf_label+"</a></span>"}}k+="</span>"}k+="</td></tr>";return k},filter_element:function(b,a){return'<span class="text-filter-val">'+a+'<a href="javascript:void(0);" filter_key="'+b+'" filter_val="'+a+'"><i class="fa fa-times" style="padding-left: 5px; padding-bottom: 6px;"/></a></span>'}}});
\ No newline at end of file
+define([],function(){return{grid:function(b){var a="";if(b.embedded){a=this.grid_header(b)+this.grid_table(b)}else{a='<div class="loading-elt-overlay"></div><table><tr><td width="75%">'+this.grid_header(b)+'</td><td></td><td></td></tr><tr><td width="100%" id="grid-message" valign="top"></td><td></td><td></td></tr></table>'+this.grid_table(b)}if(b.info_text){a+='<br><div class="toolParamHelp" style="clear: both;">'+b.info_text+"</div>"}return a},grid_table:function(a){return'<form method="post" onsubmit="return false;"><table id="grid-table" class="grid"><thead id="grid-table-header"></thead><tbody id="grid-table-body"></tbody><tfoot id="grid-table-footer"></tfoot></table></form>'},grid_header:function(c){var b='<div class="grid-header">';if(!c.embedded){b+="<h2>"+c.title+"</h2>"}if(c.global_actions){b+='<ul class="manage-table-actions">';var d=(c.global_actions.length>=3);if(d){b+='<li><a class="action-button" id="popup-global-actions" class="menubutton">Actions</a></li><div popupmenu="popup-global-actions">'}for(i in c.global_actions){var e=c.global_actions[i];var a="";if(e.inbound){a="use-inbound"}else{a="use-outbound"}b+='<li><a class="action-button '+a+'" href="'+e.url_args+'" onclick="return false;">'+e.label+"</a></li>"}if(d){b+="</div>"}b+="</ul>"}if(c.insert){b+=c.insert}b+=this.grid_filters(c);b+="</div>";return b},header:function(b){var a="<tr>";if(b.show_item_checkboxes){a+="<th>";if(b.items.length>0){a+='<input type="checkbox" id="check_all" name=select_all_checkbox value="true"><input type="hidden" name=select_all_checkbox value="true">'}a+="</th>"}for(var c in b.columns){var d=b.columns[c];if(d.visible){a+='<th id="'+d.key+'-header">';if(d.href){a+='<a href="'+d.href+'" class="sort-link" sort_key="'+d.key+'">'+d.label+"</a>"}else{a+=d.label}a+='<span class="sort-arrow">'+d.extra+"</span></th>"}}a+="</tr>";return a},body:function(r){var k="";var s=0;var e=r.items.length;if(e==0){k+='<tr><td colspan="100"><em>No Items</em></td></tr>';s=1}for(var f in r.items){var p=r.items[f];var a=p.encode_id;var g="grid-"+f+"-popup";k+="<tr ";if(r.current_item_id==p.id){k+='class="current"'}k+=">";if(r.show_item_checkboxes){k+='<td style="width: 1.5em;"><input type="checkbox" name="id" value="'+a+'" id="'+a+'" class="grid-row-select-checkbox" /></td>'}for(j in r.columns){var d=r.columns[j];if(d.visible){var c="";if(d.nowrap){c='style="white-space:nowrap;"'}var q=p.column_config[d.label];var h=q.link;var l=q.value;var o=q.inbound;if(jQuery.type(l)==="string"){l=l.replace(/\/\//g,"/")}var b="";var n="";if(d.attach_popup){b="grid-"+f+"-popup";n="menubutton";if(h!=""){n+=" split"}n+=" popup"}k+="<td "+c+">";if(h){if(r.operations.length!=0){k+='<div id="'+b+'" class="'+n+'" style="float: left;">'}var m="";if(o){m="use-inbound"}else{m="use-outbound"}k+='<a class="label '+m+'" href="'+h+'" onclick="return false;">'+l+"</a>";if(r.operations.length!=0){k+="</div>"}}else{k+='<div id="'+b+'" class="'+n+'"><label id="'+d.label_id_prefix+a+'" for="'+a+'">'+l+"</label></div>"}k+="</td>"}}k+="</tr>";s++}return k},footer:function(o){var k="";if(o.use_paging&&o.num_pages>1){var m=o.num_page_links;var a=o.cur_page_num;var n=o.num_pages;var h=m/2;var g=a-h;var e=0;if(g==0){g=1;e=h-(a-g)}var d=h+e;var c=a+d;if(c<=n){max_offset=0}else{c=n;max_offset=d-(c+1-a)}if(max_offset!=0){g-=max_offset;if(g<1){g=1}}k+='<tr id="page-links-row">';if(o.show_item_checkboxes){k+="<td></td>"}k+='<td colspan="100"><span id="page-link-container">Page:';if(g>1){k+='<span class="page-link" id="page-link-1"><a href="javascript:void(0);" page_num="1" onclick="return false;">1</a></span> ...'}for(var l=g;l<c+1;l++){if(l==o.cur_page_num){k+='<span class="page-link inactive-link" id="page-link-'+l+'">'+l+"</span>"}else{k+='<span class="page-link" id="page-link-'+l+'"><a href="javascript:void(0);" onclick="return false;" page_num="'+l+'">'+l+"</a></span>"}}if(c<n){k+='...<span class="page-link" id="page-link-'+n+'"><a href="javascript:void(0);" onclick="return false;" page_num="'+n+'">'+n+"</a></span>"}k+="</span>";k+='<span class="page-link" id="show-all-link-span"> | <a href="javascript:void(0);" onclick="return false;" page_num="all">Show All</a></span></td></tr>'}if(o.show_item_checkboxes){k+='<tr><input type="hidden" id="operation" name="operation" value=""><td></td><td colspan="100">For <span class="grid-selected-count"></span> selected '+o.get_class_plural+": ";for(i in o.operations){var b=o.operations[i];if(b.allow_multiple){k+='<input type="button" value="'+b.label+'" class="operation-button action-button"> '}}k+="</td></tr>"}var f=false;for(i in o.operations){if(o.operations[i].global_operation){f=true;break}}if(f){k+='<tr><td colspan="100">';for(i in o.operations){var b=o.operations[i];if(b.global_operation){k+='<a class="action-button" href="'+b.global_operation+'">'+b.label+"</a>"}}k+="</td></tr>"}if(o.legend){k+='<tr><td colspan="100">'+o.legend+"</td></tr>"}return k},message:function(a){return'<p><div class="'+a.status+'message transient-message">'+a.message+'</div><div style="clear: both"></div></p>'},grid_filters:function(n){var a=n.default_filter_dict;var b=n.filters;var e="none";if(n.advanced_search){e="block"}var m=false;for(var g in n.columns){var d=n.columns[g];if(d.filterable=="advanced"){var l=d.key;var c=b[l];var f=a[l];if(c&&f&&c!=f){e="block"}m=true}}var k="block";if(e=="block"){k="none"}var h='<div id="standard-search" style="display: '+k+';"><table><tr><td style="padding: 0;"><table>';for(var g in n.columns){var d=n.columns[g];if(d.filterable=="standard"){h+=this.grid_column_filter(n,d)}}h+="</table></td></tr><tr><td>";if(m){h+='<a href="" class="advanced-search-toggle">Advanced Search</a>'}h+="</td></tr></table></div>";h+='<div id="advanced-search" style="display: '+e+'; margin-top: 5px; border: 1px solid #ccc;"><table><tr><td style="text-align: left" colspan="100"><a href="" class="advanced-search-toggle">Close Advanced Search</a></td></tr>';for(var g in n.columns){var d=n.columns[g];if(d.filterable=="advanced"){h+=this.grid_column_filter(n,d)}}h+="</table></div>";return h},grid_column_filter:function(e,c){var t=e.default_filter_dict;var l=e.filters;var a=c.label;var b=c.key;if(c.filterable=="advanced"){a=a.toLowerCase()}var k="<tr>";if(c.filterable=="advanced"){k+='<td align="left" style="padding-left: 10px">'+a+":</td>"}k+='<td style="padding-bottom: 1px;">';if(c.is_text){k+='<form class="text-filter-form" column_key="'+b+'" action="'+e.url+'" method="get" >';for(u in e.columns){var g=e.columns[u];var p=l[g.key];if(p){if(p!="All"){if(g.is_text){p=JSON.stringify(p)}k+='<input type="hidden" id="'+g.key+'" name="f-'+g.key+'" value="'+p+'"/>'}}}k+='<span id="'+b+'-filtering-criteria">';var h=l[b];if(h){var f=jQuery.type(h);if(f=="string"){if(h!="All"){k+=this.filter_element(b,h)}}if(f=="array"){for(var u in h){var n=h[u];var v=h;v=v.slice(u);k+=this.filter_element(b,n)}}}k+="</span>";var r="";if(c.filterable=="standard"){r=c.label.toLowerCase();var q=r.length;if(q<20){q=20}q=q+4}k+='<span class="search-box"><input class="search-box-input" id="input-'+b+'-filter" name="f-'+b+'" type="text" placeholder="'+r+'" size="'+q+'"/><button type="submit" style="background: transparent; border: none; padding: 4px; margin: 0px;"><i class="fa fa-search"></i></button></span></form>'}else{k+='<span id="'+b+'-filtering-criteria">';var s=false;for(cf_label in e.categorical_filters[b]){var o=e.categorical_filters[b][cf_label];var d="";var m="";for(key in o){d=key;m=o[key]}if(s){k+=" | "}s=true;var n=l[b];if(n&&o[b]&&n==m){k+='<span class="categorical-filter '+b+'-filter current-filter">'+cf_label+"</span>"}else{k+='<span class="categorical-filter '+b+'-filter"><a href="javascript:void(0);" filter_key="'+d+'" filter_val="'+m+'">'+cf_label+"</a></span>"}}k+="</span>"}k+="</td></tr>";return k},filter_element:function(b,a){return'<span class="text-filter-val">'+a+'<a href="javascript:void(0);" filter_key="'+b+'" filter_val="'+a+'"><i class="fa fa-times" style="padding-left: 5px; padding-bottom: 6px;"/></a></span>'}}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/ui.popover.js
--- /dev/null
+++ b/static/scripts/packed/mvc/ui.popover.js
@@ -0,0 +1,1 @@
+define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{with_close:true,container:"body",title:null,placement:"top"},visible:false,initialize:function(d){var c=this;this.options=_.defaults(d,this.optionsDefault);this.setElement(this._template(this.options));this.options.container.parent().append(this.$el);if(this.options.with_close){this.$el.find("#close").on("click",function(){c.hide()})}this.uuid=a.uuid();var c=this;$("body").on("mousedown."+this.uuid,function(f){c._hide(f)})},title:function(c){if(c!==undefined){this.$el.find(".popover-title-label").html(c)}},show:function(){this.$el.show();this.visible=true;var c=this._get_placement(this.options.placement);this.$el.css(c)},_get_placement:function(h){var d=this._get_width(this.$el);var j=this.$el.height();var k=this.options.container;var c=this._get_width(k);var f=this._get_height(k);var g=k.position();var i=0;var e=0;if(h=="top"||h=="bottom"){e=g.left-d+(c+d)/2;if(h=="top"){i=g.top-j-5}else{i=g.top+f+5}}return{top:i,left:e}},_get_width:function(c){return c.width()+parseInt(c.css("padding-left"))+parseInt(c.css("padding-right"))},_get_height:function(c){return c.height()+parseInt(c.css("padding-top"))+parseInt(c.css("padding-bottom"))},hide:function(){this.$el.hide();this.visible=false},append:function(c){this.$el.find(".popover-content").append(c)},empty:function(c){this.$el.find(".popover-content").empty()},remove:function(){$("body").off("mousedown."+this.uuid);this.$el.remove()},_hide:function(c){if(!$(this.options.container).is(c.target)&&!$(this.el).is(c.target)&&$(this.el).has(c.target).length===0){this.hide()}},_template:function(d){var c='<div class="popover-view popover fade '+d.placement+' in"><div class="arrow"></div><div class="popover-title"><div class="popover-title-label">'+d.title+"</div>";if(d.with_close){c+='<div id="close" class="popover-close fa fa-times-circle"></div>'}c+='</div><div class="popover-content"></div></div>';return c}});return{View:b}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/upload/upload-button.js
--- /dev/null
+++ b/static/scripts/packed/mvc/upload/upload-button.js
@@ -0,0 +1,1 @@
+define([],function(){var b=Backbone.Model.extend({defaults:{percentage:0,icon:"fa-circle",label:"",status:""}});var a=Backbone.View.extend({model:null,initialize:function(d){var c=this;this.model=d;this.options=this.model.attributes;this.setElement(this._template(this.options));$(this.el).on("click",this.options.onclick);if(this.options.tooltip){$(this.el).tooltip({title:this.options.tooltip,placement:"bottom"})}this.model.on("change:percentage",function(){c._percentage(c.model.get("percentage"))});this.model.on("change:status",function(){c._status(c.model.get("status"))});var c=this;$(window).on("beforeunload",function(){var e="";if(c.options.onunload){e=c.options.onunload()}if(e!=""){return e}})},_status:function(d){var c=this.$el.find(".progress-bar");c.removeClass();c.addClass("progress-bar");c.addClass("progress-bar-notransition");if(d!=""){c.addClass("progress-bar-"+d);console.log(c)}},_percentage:function(d){var c=this.$el.find(".progress-bar");c.css({width:d+"%"})},_template:function(c){return'<div style="float: right"><div class="upload-button"><div class="progress"><div class="progress-bar"></div></div><div id="label" class="label"><a class="panel-header-button" href="javascript:void(0)"><span class="fa fa-upload"></span></a></div></div></div>'}});return{Model:b,View:a}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/upload/upload-ftp.js
--- /dev/null
+++ b/static/scripts/packed/mvc/upload/upload-ftp.js
@@ -0,0 +1,1 @@
+define(["utils/utils"],function(a){return Backbone.View.extend({options:{class_add:"upload-icon-button fa fa-square-o",class_remove:"upload-icon-button fa fa-check-square-o"},initialize:function(c){this.app=c;var b=this;this.setElement(this._template());a.jsonFromUrl(galaxy_config.root+"api/ftp_files",function(d){b._fill(d)})},events:{mousedown:function(b){b.preventDefault()}},_fill:function(c){if(c.length>0){this.$el.find("#upload-ftp-content").html($(this._template_table()));var b=0;for(key in c){this.add(c[key]);b+=c[key].size}this.$el.find("#upload-ftp-number").html(c.length+" files");this.$el.find("#upload-ftp-disk").html(a.bytesToString(b,true))}else{this.$el.find("#upload-ftp-content").html($(this._template_info()))}this.$el.find("#upload-ftp-wait").hide()},add:function(e){var d=$(this._template_row(e));$(this.el).find("tbody").append(d);var c="";if(this._find(e)){c=this.options.class_remove}else{c=this.options.class_add}d.find("#upload-ftp-add").addClass(c);var b=this;d.find("#upload-ftp-add").on("click",function(){var f=b._find(e);$(this).removeClass();if(!f){b.app.uploadbox.add([{mode:"ftp",name:e.path,size:e.size,path:e.path}]);$(this).addClass(b.options.class_remove)}else{b.app.collection.remove(f);$(this).addClass(b.options.class_add)}})},_find:function(f){var c=this.app.collection.where({file_path:f.path});var b=null;for(var d in c){var e=c[d];if(e.get("status")=="init"&&e.get("file_mode")=="ftp"){b=e.get("id")}}return b},_template_row:function(b){return'<tr><td><div id="upload-ftp-add"/></td><td>'+b.path+'</td><td style="white-space: nowrap;">'+a.bytesToString(b.size)+'</td><td style="white-space: nowrap;">'+b.ctime+"</td></tr>"},_template_table:function(){return'<span style="whitespace: nowrap; float: left;">Available files: </span><span style="whitespace: nowrap; float: right;"><span class="upload-icon fa fa-file-text-o"/><span id="upload-ftp-number"/> <span class="upload-icon fa fa-hdd-o"/><span id="upload-ftp-disk"/></span><table class="grid"><thead><tr><th></th><th>Name</th><th>Size</th><th>Created</th></tr></thead><tbody></tbody></table>'},_template_info:function(){return'<div class="upload-ftp-warning warningmessage">Your FTP directory does not contain any files.</div>'},_template:function(){return'<div class="upload-ftp"><div id="upload-ftp-wait" class="upload-ftp-wait fa fa-spinner fa-spin"/><div class="upload-ftp-help">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>'+this.app.options.ftp_upload_site+'</strong> using your Galaxy credentials (email address and password).</div><div id="upload-ftp-content"></div><div>'}})});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/upload/upload-model.js
--- a/static/scripts/packed/mvc/upload/upload-model.js
+++ b/static/scripts/packed/mvc/upload/upload-model.js
@@ -1,1 +1,1 @@
-define([],function(){var b=Backbone.Model.extend({defaults:{extension:"auto",genome:"?",url_paste:"",space_to_tabs:false,status:"init",info:null}});var a=Backbone.Collection.extend({model:b});return{Model:b,Collection:a}});
\ No newline at end of file
+define([],function(){var b=Backbone.Model.extend({defaults:{extension:"auto",genome:"?",url_paste:"",status:"init",info:null,file_mode:"local",file_size:0,file_type:null,file_path:"",space_to_tabs:false,to_posix_lines:true}});var a=Backbone.Collection.extend({model:b});return{Model:b,Collection:a}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/upload/upload-row.js
--- a/static/scripts/packed/mvc/upload/upload-row.js
+++ b/static/scripts/packed/mvc/upload/upload-row.js
@@ -1,1 +1,1 @@
-define(["mvc/upload/upload-model","mvc/upload/upload-extensions"],function(a,b){return Backbone.View.extend({options:{padding:8,timeout:2000},status_classes:{init:"symbol fa fa-trash-o",queued:"symbol fa fa-spinner fa-spin",running:"symbol fa fa-spinner fa-spin",success:"symbol fa fa-check",error:"symbol fa fa-exclamation-triangle"},initialize:function(f,d){this.app=f;var c=this;this.model=new a.Model(d);this.setElement(this._template(d));var e=this.$el;e.find("#symbol").on("click",function(){var g=c.model.get("status");if(g=="init"||g=="success"||g=="error"){c.app.collection.remove(c.model)}});e.find("#extension_info").on("mouseover",function(){c._showExtensionInfo()}).on("mouseleave",function(){c._hideExtensionInfo()});e.find("#text-content").on("keyup",function(){var g=e.find("#text-content");var i=g.val();var h=i.length;e.find("#size").html(c._formatSize(h));c.model.set("url_paste",i);c.model.set("file_size",h)});e.find("#genome").on("change",function(g){c.model.set("genome",$(g.target).val())});e.find("#extension").on("change",function(g){c.model.set("extension",$(g.target).val());c.$el.find("#extension_info").popover("destroy")});e.find("#space_to_tabs").on("change",function(g){c.model.set("space_to_tabs",$(g.target).prop("checked"))});this.model.on("change:percentage",function(){c._refreshPercentage()});this.model.on("change:status",function(){c._refreshStatus()});this.model.on("change:info",function(){c._refreshInfo()});this.model.on("change:genome",function(){c._refreshGenome()});this.model.on("remove",function(){c._destroyExtensionInfo();c.remove()});this.app.collection.on("reset",function(){c._destroyExtensionInfo();c.remove()})},render:function(){var i=this.model.get("file_name");var d=this.model.get("file_size");var f=this.$el;f.find("#title").html(i);f.find("#size").html(this._formatSize(d));if(d==-1){var h=f.find("#text");var g=this.options.padding;var e=f.width()-2*g;var c=f.height()-g;h.css("width",e+"px");h.css("top",c+"px");f.height(c+h.height()+2*g);h.show()}},_refreshGenome:function(){var c=this.model.get("genome");this.$el.find("#genome").val(c)},_refreshInfo:function(){var c=this.model.get("info");if(c){this.$el.find("#info").html("<strong>Failed: </strong>"+c).show()}else{this.$el.find("#info").hide()}},_refreshPercentage:function(){var c=parseInt(this.model.get("percentage"));this.$el.find(".progress-bar").css({width:c+"%"});if(c!=100){this.$el.find("#percentage").html(c+"%")}else{this.$el.find("#percentage").html("Adding to history...")}},_refreshStatus:function(){var d=this.$el;var c=this.model.get("status");var f=this.status_classes[c];var e=this.$el.find("#symbol");e.removeClass();e.addClass(f);if(c=="init"){d.find("#text-content").attr("disabled",false);d.find("#genome").attr("disabled",false);d.find("#extension").attr("disabled",false);d.find("#space_to_tabs").attr("disabled",false)}else{d.find("#text-content").attr("disabled",true);d.find("#genome").attr("disabled",true);d.find("#extension").attr("disabled",true);d.find("#space_to_tabs").attr("disabled",true)}if(c=="success"){d.addClass("success");d.find("#percentage").html("100%")}if(c=="error"){d.addClass("danger");d.find(".progress").remove()}},_formatSize:function(c){var d="";if(c>=100000000000){c=c/100000000000;d="TB"}else{if(c>=100000000){c=c/100000000;d="GB"}else{if(c>=100000){c=c/100000;d="MB"}else{if(c>=100){c=c/100;d="KB"}else{if(c>0){c=c*10;d="b"}else{return"<strong>-</strong>"}}}}}return"<strong>"+(Math.round(c)/10)+"</strong> "+d},_showExtensionInfo:function(){var c=this;var d=$(this.el).find("#extension_info");var f=this.model.get("extension");var e=$(this.el).find("#extension").find("option:selected").text();d.popover({html:true,title:e,content:b(f),placement:"bottom",container:c.$el.parent()});d.popover("show");clearTimeout(this.popover_timeout)},_hideExtensionInfo:function(){var c=this;this.popover_timeout=setTimeout(function(){c._destroyExtensionInfo()},this.options.timeout)},_destroyExtensionInfo:function(){this.$el.find("#extension_info").popover("destroy")},_template:function(e){var d=this;var c='<tr id="upload-item-'+e.id+'" class="upload-item"><td><div style="position: relative;"><div id="title" class="title"></div><div id="text" class="text"><div class="text-info">You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.</div><textarea id="text-content" class="text-content form-control"></textarea></div></div></td><td><div id="size" class="size"></div></td>';c+='<td><select id="extension" class="extension">';for(key in d.app.select_extension){c+='<option value="'+d.app.select_extension[key][1]+'">'+d.app.select_extension[key][0]+"</option>"}c+='</select> <i id="extension_info" class="fa fa-search" style="cursor: pointer;"/></td>';c+='<td><select id="genome" class="genome">';for(key in d.app.select_genome){c+='<option value="'+d.app.select_genome[key][1]+'">'+d.app.select_genome[key][0]+"</option>"}c+="</select></td>";c+='<td><input id="space_to_tabs" type="checkbox"></input></td><td><div id="info" class="info"><div class="progress"><div class="progress-bar progress-bar-success"></div><div id="percentage" class="percentage">0%</div></div></div></td><td><div id="symbol" class="'+this.status_classes.init+'"></div></td></tr>';return c}})});
\ No newline at end of file
+define(["utils/utils","mvc/upload/upload-model","mvc/upload/upload-extensions","mvc/upload/upload-settings","mvc/ui.popover"],function(d,b,e,a,c){return Backbone.View.extend({options:{padding:8,timeout:2000},status_classes:{init:"upload-icon-button fa fa-trash-o",queued:"upload-icon fa fa-spinner fa-spin",running:"upload-icon fa fa-spinner fa-spin",success:"upload-icon-button fa fa-check",error:"upload-icon-button fa fa-exclamation-triangle"},settings:null,initialize:function(i,g){this.app=i;var f=this;this.model=new b.Model(g);this.setElement(this._template(g));var h=this.$el;this.settings=new c.View({title:"Upload configuration",container:h.find("#settings"),placement:"bottom"});h.find("#symbol").on("click",function(){f._removeRow()});h.find("#extension-info").on("click",function(j){f._showExtensionInfo()}).on("mousedown",function(j){j.preventDefault()});h.find("#settings").on("click",function(j){f._showSettings()}).on("mousedown",function(j){j.preventDefault()});h.find("#text-content").on("keyup",function(j){f.model.set("url_paste",$(j.target).val());f.model.set("file_size",$(j.target).val().length)});h.find("#genome").on("change",function(j){f.model.set("genome",$(j.target).val())});h.find("#extension").on("change",function(j){f.model.set("extension",$(j.target).val())});h.find("#space_to_tabs").on("change",function(j){f.model.set("space_to_tabs",$(j.target).prop("checked"))});this.model.on("change:percentage",function(){f._refreshPercentage()});this.model.on("change:status",function(){f._refreshStatus()});this.model.on("change:extension",function(){f._destroyExtensionInfo()});this.model.on("change:info",function(){f._refreshInfo()});this.model.on("change:genome",function(){f._refreshGenome()});this.model.on("change:file_size",function(){f._refreshFileSize()});this.model.on("remove",function(){f._destroyExtensionInfo();f.remove()});this.app.collection.on("reset",function(){f._destroyExtensionInfo();f.remove()})},render:function(){var m=this.model.get("file_name");var g=this.model.get("file_size");var j=this.model.get("file_mode");var i=this.$el;i.find("#title").html(m);i.find("#size").html(d.bytesToString(g));i.find("#mode").removeClass().addClass("mode");if(j=="new"){var l=i.find("#text");var k=this.options.padding;var h=i.width()-2*k;var f=i.height()-k;l.css("width",h+"px");l.css("top",f+"px");i.height(f+l.height()+2*k);l.show();i.find("#mode").addClass("fa fa-pencil")}if(j=="local"){i.find("#mode").addClass("fa fa-laptop")}if(j=="ftp"){i.find("#mode").addClass("fa fa-code-fork")}},_refreshGenome:function(){var f=this.model.get("genome");this.$el.find("#genome").val(f)},_refreshInfo:function(){var f=this.model.get("info");if(f){this.$el.find("#info").html("<strong>Failed: </strong>"+f).show()}else{this.$el.find("#info").hide()}},_refreshPercentage:function(){var f=parseInt(this.model.get("percentage"));this.$el.find(".progress-bar").css({width:f+"%"});if(f!=100){this.$el.find("#percentage").html(f+"%")}else{this.$el.find("#percentage").html("Adding to history...")}},_refreshStatus:function(){var g=this.$el;var f=this.model.get("status");var i=this.status_classes[f];var h=this.$el.find("#symbol");h.removeClass();h.addClass(i);if(f=="init"){g.find("#text-content").attr("disabled",false);g.find("#genome").attr("disabled",false);g.find("#extension").attr("disabled",false);g.find("#space_to_tabs").attr("disabled",false)}else{g.find("#text-content").attr("disabled",true);g.find("#genome").attr("disabled",true);g.find("#extension").attr("disabled",true);g.find("#space_to_tabs").attr("disabled",true)}if(f=="success"){g.addClass("success");g.find("#percentage").html("100%")}if(f=="error"){g.addClass("danger");g.find(".progress").remove()}},_refreshFileSize:function(){var f=this.model.get("file_size");this.$el.find("#size").html(d.bytesToString(f))},_removeRow:function(){var f=this.model.get("status");if(f=="init"||f=="success"||f=="error"){this.app.collection.remove(this.model)}},_showExtensionInfo:function(){var f=$(this.el).find("#extension-info");var h=this.model.get("extension");var g=$(this.el).find("#extension").find("option:selected").text();if(!this.extension_popup){this.extension_popup=new c.View({content:e(h),placement:"bottom",container:f})}if(!this.extension_popup.visible){this.extension_popup.title(g);this.extension_popup.empty();this.extension_popup.append(e(h));this.extension_popup.show()}else{this.extension_popup.hide()}},_showSettings:function(){if(!this.settings.visible){this.settings.empty();this.settings.append((new a(this)).$el);this.settings.show()}else{this.settings.hide()}},_hideExtensionInfo:function(){var f=this;this.popover_timeout=setTimeout(function(){f._destroyExtensionInfo()},this.options.timeout)},_destroyExtensionInfo:function(){this.$el.find("#extension-info").popover("destroy")},_template:function(h){var g=this;var f='<tr id="upload-item-'+h.id+'" class="upload-item"><td><div style="position: relative;"><div id="mode"></div><div id="title" class="title"></div><div id="text" class="text"><div class="text-info">You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.</div><textarea id="text-content" class="text-content form-control"></textarea></div></div></td><td><div id="size" class="size"></div></td>';f+='<td><select id="extension" class="extension">';for(key in g.app.select_extension){f+='<option value="'+g.app.select_extension[key][1]+'">'+g.app.select_extension[key][0]+"</option>"}f+='</select> <i id="extension-info" class="upload-icon-button fa fa-search"/></td>';f+='<td><select id="genome" class="genome">';for(key in g.app.select_genome){f+='<option value="'+g.app.select_genome[key][1]+'">'+g.app.select_genome[key][0]+"</option>"}f+="</select></td>";f+='<td><div id="settings" class="upload-icon-button fa fa-gear"></div><td><div id="info" class="info"><div class="progress"><div class="progress-bar progress-bar-success"></div><div id="percentage" class="percentage">0%</div></div></div></td><td><div id="symbol" class="'+this.status_classes.init+'"></div></td></tr>';return f}})});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/upload/upload-settings.js
--- /dev/null
+++ b/static/scripts/packed/mvc/upload/upload-settings.js
@@ -0,0 +1,1 @@
+define(["utils/utils"],function(a){return Backbone.View.extend({options:{class_check:"upload-icon-button fa fa-check-square-o",class_uncheck:"upload-icon-button fa fa-square-o"},initialize:function(c){this.app=c;var b=this;this.setElement(this._template());this.model=this.app.model;this.$el.find("#upload-space-to-tabs").on("click",function(){b._switch_state("#upload-space-to-tabs","space_to_tabs")});this.$el.find("#upload-to-posix-lines").on("click",function(){b._switch_state("#upload-to-posix-lines","to_posix_lines")});this.render()},events:{mousedown:function(b){b.preventDefault()}},render:function(){this._render_state("#upload-space-to-tabs",this.model.get("space_to_tabs"));this._render_state("#upload-to-posix-lines",this.model.get("to_posix_lines"));var b=this.$el.find("#upload-settings-cover");if(this.model.get("status")!="init"){b.show()}else{b.hide()}},_switch_state:function(c,b){if(this.model.get("status")=="init"){var d=!this.model.get(b);this.model.set(b,d);this._render_state(c,d)}},_render_state:function(b,d){var c=this.$el.find(b);c.removeClass();if(d){c.addClass(this.options.class_check)}else{c.addClass(this.options.class_uncheck)}},_template:function(){return'<div class="upload-settings" style="position: relative;"><div id="upload-settings-cover" class="upload-settings-cover"/><table class="table table-striped"><tbody><tr><td><div id="upload-space-to-tabs"/></td><td>Convert spaces to tabs</td></tr><tr><td><div id="upload-to-posix-lines"/></td><td>Use POSIX standard</td></tr></tbody></table></div>'}})});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","utils/utils","mvc/upload/upload-model","mvc/upload/upload-row","mvc/ui","utils/uploadbox"],function(c,f,e,d){var b=Backbone.Model.extend({defaults:{percentage:0,icon:"fa-circle",label:"",status:""}});var a=Backbone.View.extend({model:null,initialize:function(h){var g=this;this.model=h;this.options=this.model.attributes;this.setElement(this._template(this.options));$(this.el).on("click",this.options.onclick);if(this.options.tooltip){$(this.el).tooltip({title:this.options.tooltip,placement:"bottom"})}this.model.on("change:percentage",function(){g._percentage(g.model.get("percentage"))});this.model.on("change:status",function(){g._status(g.model.get("status"))});var g=this;$(window).on("beforeunload",function(){var i="";if(g.options.onunload){i=g.options.onunload()}if(i!=""){return i}})},_status:function(h){var g=this.$el.find(".progress-bar");g.removeClass();g.addClass("progress-bar");g.addClass("progress-bar-notransition");if(h!=""){g.addClass("progress-bar-"+h)}},_percentage:function(h){var g=this.$el.find(".progress-bar");g.css({width:h+"%"})},_template:function(g){return'<div style="float: right"><div class="progress-button"><div class="progress"><div class="progress-bar"></div></div><div id="label" class="label"><a class="panel-header-button" href="javascript:void(0)"><span class="fa fa-upload"></span></a></div></div></div>'}});return Backbone.View.extend({modal:null,button_show:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new e.Collection(),counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},options:{nginx_upload_path:""},initialize:function(h){var g=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){g.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.button_show=new b({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(i){if(i){g._eventShow(i)}},onunload:function(){if(g.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new a(this.button_show)).$el);var g=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes",function(i){for(key in i){g.select_extension.push([i[key],i[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(i){var j=g.select_genome[0];g.select_genome=[];for(key in i){if(i[key].length>1){if(i[key][1]!==j[1]){g.select_genome.push(i[key])}}}g.select_genome.sort(function(l,k){return l[0]>k[0]?1:l[0]<k[0]?-1:0});g.select_genome.unshift(j)});if(h){this.options=_.defaults(h,this.options)}this.collection.on("remove",function(i){g._eventRemove(i)});this.collection.on("change:genome",function(j){var i=j.get("genome");g.collection.each(function(k){if(k.get("status")=="init"&&k.get("genome")=="?"){k.set("genome",i)}})})},_eventShow:function(h){h.preventDefault();h.stopPropagation();if(!this.modal){var g=this;this.modal=new c.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose files":function(){g.uploadbox.select()},"Create file":function(){g._eventCreate()},Start:function(){g._eventStart()},Pause:function(){g._eventStop()},Reset:function(){g._eventReset()},Close:function(){g.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var g=this;this.uploadbox=this.$el.uploadbox({announce:function(i,j,k){g._eventAnnounce(i,j,k)},initialize:function(i,j,k){return g._eventInitialize(i,j,k)},progress:function(i,j,k){g._eventProgress(i,j,k)},success:function(i,j,k){g._eventSuccess(i,j,k)},error:function(i,j,k){g._eventError(i,j,k)},complete:function(){g._eventComplete()}});this._updateScreen()}this.modal.show()},_eventRemove:function(h){var g=h.get("status");if(g=="success"){this.counter.success--}else{if(g=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(h.id)},_eventAnnounce:function(g,h,j){this.counter.announce++;this._updateScreen();var i=new d(this,{id:g,file_name:h.name,file_size:h.size});this.collection.add(i.model);$(this.el).find("tbody:last").append(i.$el);i.render()},_eventInitialize:function(k,g,o){var i=this.collection.get(k);i.set("status","running");var h=i.get("extension");var l=i.get("file_name");var n=i.get("genome");var m=i.get("url_paste");var j=i.get("space_to_tabs");if(!m&&!(g.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path,paramname:"files_0|file_data"});tool_input={};tool_input.dbkey=n;tool_input.file_type=h;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=m;tool_input.space_to_tabs=j;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(h,i,g){var j=this.collection.get(h);j.set("percentage",g);this.button_show.set("percentage",this._upload_percentage(g,i.size))},_eventSuccess:function(h,i,k){var j=this.collection.get(h);j.set("status","success");var g=j.get("file_size");this.button_show.set("percentage",this._upload_percentage(100,g));this.upload_completed+=g*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(g,h,j){var i=this.collection.get(g);i.set("status","error");i.set("info",j);this.button_show.set("percentage",this._upload_percentage(100,h.size));this.button_show.set("status","danger");this.upload_completed+=h.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(g){if(g.get("status")=="queued"){g.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:-1}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var g=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(h){if(h.get("status")=="init"){h.set("status","queued");g.upload_size+=h.get("file_size")}});this.button_show.set("percentage",0);this.button_show.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.button_show.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.button_show.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose files");this.modal.enableButton("Create file")}else{this.modal.disableButton("Choose files");this.modal.disableButton("Create file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("table").show()}else{$(this.el).find("table").hide()}},_upload_percentage:function(g,h){return(this.upload_completed+(g*h))/this.upload_size},_template:function(h,g){return'<div id="'+h+'" class="upload-box"><table class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Space→Tab</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+g+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui.popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,select_extension:[["Auto-detect","auto"]],select_genome:[["Unspecified (?)","?"]],collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}if(!Galaxy.currUser.get("id")){return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.jsonFromUrl(galaxy_config.root+"api/datatypes",function(j){for(key in j){h.select_extension.push([j[key],j[key]])}});f.jsonFromUrl(galaxy_config.root+"api/genomes",function(j){var k=h.select_genome[0];h.select_genome=[];for(key in j){if(j[key].length>1){if(j[key][1]!==k[1]){h.select_genome.push(j[key])}}}h.select_genome.sort(function(m,l){return m[0]>l[0]?1:m[0]<l[0]?-1:0});h.select_genome.unshift(k)});if(i){this.options=_.defaults(i,this.options)}this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Create new file":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});this._updateScreen();if(this.options.ftp_upload_dir&&this.options.ftp_upload_site){var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}else{this.modal.hideButton("Choose FTP file")}}this.modal.show()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="ftp"){this.uploadbox.configure({paramname:""})}else{this.uploadbox.configure({paramname:"files_0|file_data"})}tool_input={};tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input["files_0|url_paste"]=q;tool_input["files_0|ftp_files"]=n;tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.current_history=Galaxy.currHistoryPanel.model.get("id");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Create new file")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Create new file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/utils/config.js
--- a/static/scripts/packed/utils/config.js
+++ b/static/scripts/packed/utils/config.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/trackster/util","utils/config"],function(c,f,b){var d=Backbone.Model.extend({initialize:function(g){var h=this.get("key");this.set("id",h);var i=c.find(d.known_settings_defaults,function(j){return j.key===h});if(i){this.set(c.extend({},i,g))}if(this.get("type")==="color"&&!this.get("value")){this.set("value",f.get_random_color())}},set_value:function(h){var g=this.get("type");if(g==="float"){h=parseFloat(h)}else{if(g==="int"){h=parseInt(h,10)}}this.set("value",h)}},{known_settings_defaults:[{key:"name",label:"Name",type:"text",default_value:""},{key:"color",label:"Color",type:"color",default_value:null},{key:"min_value",label:"Min Value",type:"float",default_value:null},{key:"max_value",label:"Max Value",type:"float",default_value:null},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"block_color",label:"Block color",type:"color",default_value:null},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:null},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}]});var e=Backbone.Collection.extend({model:d,to_key_value_dict:function(){var g={};this.each(function(h){g[h.get("key")]=h.get("value")});return g},get_value:function(g){var h=this.get(g);if(h){return h.get("value")}return undefined}},{from_config_dict:function(h){var g=c.map(c.keys(h),function(i){return{key:i,value:h[i]}});return new e(g)}});var a=Backbone.View.extend({className:"config-settings-view",render:function(){var g=this.$el;this.collection.each(function(k,p){if(k.get("hidden")){return}var j="param_"+p,q=k.get("type"),u=k.get("value");var w=$("<div class='form-row' />").appendTo(g);w.append($("<label />").attr("for",j).text(k.get("label")+":"));if(q==="bool"){w.append($('<input type="checkbox" />').attr("id",j).attr("name",j).attr("checked",u))}else{if(q==="text"){w.append($('<input type="text"/>').attr("id",j).val(u).click(function(){$(this).select()}))}else{if(q==="select"){var s=$("<select />").attr("id",j);for(var n=0;n<k.options.length;n++){$("<option/>").text(k.options[n].label).attr("value",k.options[n].value).appendTo(s)}s.val(u);w.append(s)}else{if(q==="color"){var v=$("<div/>").appendTo(w),r=$("<input />").attr("id",j).attr("name",j).val(u).css("float","left").appendTo(v).click(function(x){$(".tooltip").removeClass("in");var i=$(this).siblings(".tooltip").addClass("in");i.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(i).height()/2)+($(this).height()/2)}).show();i.click(function(y){y.stopPropagation()});$(document).bind("click.color-picker",function(){i.hide();$(document).unbind("click.color-picker")});x.stopPropagation()}),o=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(v).attr("title","Set new random color").tooltip(),t=$("<div class='tooltip right' style='position: absolute;' />").appendTo(v).hide(),l=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(t),h=$("<div class='tooltip-arrow'></div>").appendTo(t),m=$.farbtastic(l,{width:100,height:100,callback:r,color:u});v.append($("<div/>").css("clear","both"));(function(i){o.click(function(){i.setColor(f.get_random_color())})})(m)}else{w.append($("<input />").attr("id",j).attr("name",j).val(u))}}}}if(k.help){w.append($("<div class='help'/>").text(k.help))}});return this},render_in_modal:function(k){var g=this,j=function(){Galaxy.modal.hide();$(window).unbind("keypress.check_enter_esc")},h=function(){g.update_from_form();Galaxy.modal.hide();$(window).unbind("keypress.check_enter_esc")},i=function(l){if((l.keyCode||l.which)===27){j()}else{if((l.keyCode||l.which)===13){h()}}};$(window).bind("keypress.check_enter_esc",i);if(this.$el.children().length===0){this.render()}Galaxy.modal.show({title:k||"Configure",body:this.$el,buttons:{Cancel:j,OK:h}})},update_from_form:function(){var g=this;this.collection.each(function(i,h){if(!i.get("hidden")){var k="param_"+h;var j=g.$el.find("#"+k).val();if(i.get("type")==="bool"){j=container.find("#"+k).is(":checked")}i.set_value(j)}})}});return{ConfigSettingCollection:e,ConfigSettingCollectionView:a}});
\ No newline at end of file
+define(["libs/underscore","viz/trackster/util","utils/config"],function(c,f,b){var d=Backbone.Model.extend({initialize:function(g){var h=this.get("key");this.set("id",h);var i=c.find(d.known_settings_defaults,function(j){return j.key===h});if(i){this.set(c.extend({},i,g))}if(this.get("type")==="color"&&!this.get("value")){this.set("value",f.get_random_color())}},set_value:function(h){var g=this.get("type");if(g==="float"){h=parseFloat(h)}else{if(g==="int"){h=parseInt(h,10)}}this.set("value",h)}},{known_settings_defaults:[{key:"name",label:"Name",type:"text",default_value:""},{key:"color",label:"Color",type:"color",default_value:null},{key:"min_value",label:"Min Value",type:"float",default_value:null},{key:"max_value",label:"Max Value",type:"float",default_value:null},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:32,hidden:true},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"block_color",label:"Block color",type:"color",default_value:null},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:null},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}]});var e=Backbone.Collection.extend({model:d,to_key_value_dict:function(){var g={};this.each(function(h){g[h.get("key")]=h.get("value")});return g},get_value:function(g){var h=this.get(g);if(h){return h.get("value")}return undefined}},{from_config_dict:function(h){var g=c.map(c.keys(h),function(i){return{key:i,value:h[i]}});return new e(g)}});var a=Backbone.View.extend({className:"config-settings-view",render:function(){var g=this.$el;this.collection.each(function(k,p){if(k.get("hidden")){return}var j="param_"+p,q=k.get("type"),u=k.get("value");var w=$("<div class='form-row' />").appendTo(g);w.append($("<label />").attr("for",j).text(k.get("label")+":"));if(q==="bool"){w.append($('<input type="checkbox" />').attr("id",j).attr("name",j).attr("checked",u))}else{if(q==="text"){w.append($('<input type="text"/>').attr("id",j).val(u).click(function(){$(this).select()}))}else{if(q==="select"){var s=$("<select />").attr("id",j);for(var n=0;n<k.options.length;n++){$("<option/>").text(k.options[n].label).attr("value",k.options[n].value).appendTo(s)}s.val(u);w.append(s)}else{if(q==="color"){var v=$("<div/>").appendTo(w),r=$("<input />").attr("id",j).attr("name",j).val(u).css("float","left").appendTo(v).click(function(x){$(".tooltip").removeClass("in");var i=$(this).siblings(".tooltip").addClass("in");i.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(i).height()/2)+($(this).height()/2)}).show();i.click(function(y){y.stopPropagation()});$(document).bind("click.color-picker",function(){i.hide();$(document).unbind("click.color-picker")});x.stopPropagation()}),o=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(v).attr("title","Set new random color").tooltip(),t=$("<div class='tooltip right' style='position: absolute;' />").appendTo(v).hide(),l=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(t),h=$("<div class='tooltip-arrow'></div>").appendTo(t),m=$.farbtastic(l,{width:100,height:100,callback:r,color:u});v.append($("<div/>").css("clear","both"));(function(i){o.click(function(){i.setColor(f.get_random_color())})})(m)}else{w.append($("<input />").attr("id",j).attr("name",j).val(u))}}}}if(k.help){w.append($("<div class='help'/>").text(k.help))}});return this},render_in_modal:function(k){var g=this,j=function(){Galaxy.modal.hide();$(window).unbind("keypress.check_enter_esc")},h=function(){Galaxy.modal.hide();$(window).unbind("keypress.check_enter_esc");g.update_from_form()},i=function(l){if((l.keyCode||l.which)===27){j()}else{if((l.keyCode||l.which)===13){h()}}};$(window).bind("keypress.check_enter_esc",i);if(this.$el.children().length===0){this.render()}Galaxy.modal.show({title:k||"Configure",body:this.$el,buttons:{Cancel:j,OK:h}})},update_from_form:function(){var g=this;this.collection.each(function(i,h){if(!i.get("hidden")){var k="param_"+h;var j=g.$el.find("#"+k).val();if(i.get("type")==="bool"){j=container.find("#"+k).is(":checked")}i.set_value(j)}})}});return{ConfigSettingCollection:e,ConfigSettingCollectionView:a}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/utils/uploadbox.js
--- a/static/scripts/packed/utils/uploadbox.js
+++ b/static/scripts/packed/utils/uploadbox.js
@@ -1,1 +1,1 @@
-(function(c){jQuery.event.props.push("dataTransfer");var h={url:"",paramname:"content",maxfilesize:2048,maxfilenumber:50,dragover:function(){},dragleave:function(){},announce:function(){},initialize:function(){},progress:function(){},success:function(){},error:function(k,l,m){alert(m)},complete:function(){},error_filesize:"File exceeds 2GB. Please use an FTP client.",error_default:"Please make sure the file is available.",error_server:"Upload request failed.",error_login:"Uploads require you to log in.",error_missing:"No upload content available."};var a={};var e={};var f=0;var j=0;var d=false;var g=false;var b=null;var i=null;c.fn.uploadbox=function(A){a=c.extend({},h,A);b=this;b.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');b.on("drop",o);b.on("dragover",p);b.on("dragleave",x);c("#uploadbox_input").change(function(B){z(B.target.files);c(this).val("")});function o(B){if(!B.dataTransfer){return}z(B.dataTransfer.files);B.preventDefault();return false}function p(B){B.preventDefault();a.dragover.call(B)}function x(B){B.stopPropagation();a.dragleave.call(B)}function k(B){if(B.lengthComputable){a.progress(this.index,this.file,Math.round((B.loaded*100)/B.total))}}function z(D){if(d){return}for(var C=0;C<D.length;C++){if(j>=a.maxfilenumber){break}var B=String(f++);e[B]=D[C];a.announce(B,e[B],"");j++}}function r(B){if(e[B]){delete e[B];j--}}function m(){if(j==0||g){g=false;d=false;a.complete();return}else{d=true}var D=-1;for(var F in e){D=F;break}var E=e[D];r(D);var C=E.size;var B=1048576*a.maxfilesize;if(C<B){var G=a.initialize(D,E);if(G){q(D,E,G)}else{u(D,E,a.error_missing)}}else{u(D,E,a.error_filesize)}}function q(B,D,E){var F=new FormData();for(var C in E){F.append(C,E[C])}if(D.size>0){F.append(a.paramname,D,D.name)}i=new XMLHttpRequest();i.open("POST",a.url,true);i.setRequestHeader("Accept","application/json");i.setRequestHeader("Cache-Control","no-cache");i.setRequestHeader("X-Requested-With","XMLHttpRequest");i.onreadystatechange=function(){if(i.readyState!=i.DONE){return}var G=null;if(i.responseText){try{G=jQuery.parseJSON(i.responseText)}catch(H){G=i.responseText}}if(i.status<200||i.status>299){var I=i.statusText;if(i.status==403){I=a.error_login}else{if(i.status==0){I=a.error_server}else{if(!I){I=a.error_default}}}u(B,D,I+" ("+i.status+")")}else{y(B,D,G)}};i.upload.index=B;i.upload.file=D;i.upload.addEventListener("progress",k,false);i.send(F)}function y(B,C,D){a.success(B,C,D);m()}function u(B,C,D){a.error(B,C,D);m()}function w(){c("#uploadbox_input").trigger("click")}function t(B){for(B in e){r(B)}}function l(){if(!d){d=true;m()}}function v(){g=true}function n(B){a=c.extend({},a,B);return a}function s(){return window.File&&window.FormData&&window.XMLHttpRequest&&window.FileList}return{select:w,add:z,remove:r,start:l,stop:v,reset:t,configure:n,compatible:s}}})(jQuery);
\ No newline at end of file
+(function(c){jQuery.event.props.push("dataTransfer");var h={url:"",paramname:"content",maxfilesize:2048,maxfilenumber:50,dragover:function(){},dragleave:function(){},announce:function(){},initialize:function(){},progress:function(){},success:function(){},error:function(k,l,m){alert(m)},complete:function(){},error_filesize:"File exceeds 2GB. Please use an FTP client.",error_default:"Please make sure the file is available.",error_server:"Upload request failed.",error_login:"Uploads require you to log in.",error_missing:"No upload content available."};var a={};var e={};var f=0;var j=0;var d=false;var g=false;var b=null;var i=null;c.fn.uploadbox=function(A){a=c.extend({},h,A);b=this;b.append('<input id="uploadbox_input" type="file" style="display: none" multiple>');b.on("drop",o);b.on("dragover",p);b.on("dragleave",x);c("#uploadbox_input").change(function(B){z(B.target.files);c(this).val("")});function o(B){if(!B.dataTransfer){return}z(B.dataTransfer.files);B.preventDefault();return false}function p(B){B.preventDefault();a.dragover.call(B)}function x(B){B.stopPropagation();a.dragleave.call(B)}function k(B){if(B.lengthComputable){a.progress(this.index,this.file,Math.round((B.loaded*100)/B.total))}}function z(D){if(d){return}var E=f;for(var C=0;C<D.length;C++){if(j>=a.maxfilenumber){break}var B=String(f++);e[B]=D[C];a.announce(B,e[B],"");j++}return E}function r(B){if(e[B]){delete e[B];j--}}function m(){if(j==0||g){g=false;d=false;a.complete();return}else{d=true}var D=-1;for(var F in e){D=F;break}var E=e[D];r(D);var C=E.size;var H=E.mode;var B=1048576*a.maxfilesize;if(C<B||E.mode=="ftp"){var G=a.initialize(D,E);if(G){q(D,E,G)}else{u(D,E,a.error_missing)}}else{u(D,E,a.error_filesize)}}function q(B,D,E){var F=new FormData();for(var C in E){F.append(C,E[C])}if(D.size>0){F.append(a.paramname,D,D.name)}i=new XMLHttpRequest();i.open("POST",a.url,true);i.setRequestHeader("Accept","application/json");i.setRequestHeader("Cache-Control","no-cache");i.setRequestHeader("X-Requested-With","XMLHttpRequest");i.onreadystatechange=function(){if(i.readyState!=i.DONE){return}var G=null;if(i.responseText){try{G=jQuery.parseJSON(i.responseText)}catch(H){G=i.responseText}}if(i.status<200||i.status>299){var I=i.statusText;if(i.status==403){I=a.error_login}else{if(i.status==0){I=a.error_server}else{if(!I){I=a.error_default}}}u(B,D,I+" ("+i.status+")")}else{y(B,D,G)}};i.upload.index=B;i.upload.file=D;i.upload.addEventListener("progress",k,false);i.send(F)}function y(B,C,D){a.success(B,C,D);m()}function u(B,C,D){a.error(B,C,D);m()}function w(){c("#uploadbox_input").trigger("click")}function t(B){for(B in e){r(B)}}function l(){if(!d){d=true;m()}}function v(){g=true}function n(B){a=c.extend({},a,B);return a}function s(){return window.File&&window.FormData&&window.XMLHttpRequest&&window.FileList}return{select:w,add:z,remove:r,start:l,stop:v,reset:t,configure:n,compatible:s}}})(jQuery);
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/utils/utils.js
--- a/static/scripts/packed/utils/utils.js
+++ b/static/scripts/packed/utils/utils.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(c){function d(h,g,f){var i=new XMLHttpRequest();i.open("GET",h,true);i.setRequestHeader("Accept","application/json");i.setRequestHeader("Cache-Control","no-cache");i.setRequestHeader("X-Requested-With","XMLHttpRequest");i.onloadend=function(){var j=i.status;if(j==200){try{response=jQuery.parseJSON(i.responseText)}catch(k){response=i.responseText}g&&g(response)}else{f&&f(j)}};i.send()}function b(i,f){var g=$('<div class="'+i+'"></div>');g.appendTo(":eq(0)");var h=g.css(f);g.remove();return h}function a(f){if(!$('link[href^="'+f+'"]').length){$('<link href="'+galaxy_config.root+f+'" rel="stylesheet">').appendTo("head")}}function e(f,g){if(f){return c.defaults(f,g)}else{return g}}return{cssLoadFile:a,cssGetAttribute:b,jsonFromUrl:d,merge:e}});
\ No newline at end of file
+define(["libs/underscore"],function(c){function f(j,i,h){var k=new XMLHttpRequest();k.open("GET",j,true);k.setRequestHeader("Accept","application/json");k.setRequestHeader("Cache-Control","no-cache");k.setRequestHeader("X-Requested-With","XMLHttpRequest");k.onloadend=function(){var l=k.status;if(l==200){try{response=jQuery.parseJSON(k.responseText)}catch(m){response=k.responseText}i&&i(response)}else{h&&h(l)}};k.send()}function b(k,h){var i=$('<div class="'+k+'"></div>');i.appendTo(":eq(0)");var j=i.css(h);i.remove();return j}function a(h){if(!$('link[href^="'+h+'"]').length){$('<link href="'+galaxy_config.root+h+'" rel="stylesheet">').appendTo("head")}}function g(h,i){if(h){return c.defaults(h,i)}else{return i}}function d(i,k){var j="";if(i>=100000000000){i=i/100000000000;j="TB"}else{if(i>=100000000){i=i/100000000;j="GB"}else{if(i>=100000){i=i/100000;j="MB"}else{if(i>=100){i=i/100;j="KB"}else{if(i>0){i=i*10;j="b"}else{return"<strong>-</strong>"}}}}}var h=(Math.round(i)/10);if(k){return h+" "+j}else{return"<strong>"+h+"</strong> "+j}}function e(){return(new Date().getTime()).toString(36)}return{cssLoadFile:a,cssGetAttribute:b,jsonFromUrl:f,merge:g,bytesToString:d,uuid:e}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/packed/viz/circster.js
--- a/static/scripts/packed/viz/circster.js
+++ b/static/scripts/packed/viz/circster.js
@@ -1,1 +1,1 @@
-define(["utils/utils","libs/underscore","libs/d3","viz/visualization","utils/config"],function(h,i,n,k,c){h.cssLoadFile("static/style/circster.css");var o=Backbone.Model.extend({is_visible:function(s,p){var q=s.getBoundingClientRect(),r=$("svg")[0].getBoundingClientRect();if(q.right<0||q.left>r.right||q.bottom<0||q.top>r.bottom){return false}return true}});var j={drawTicks:function(t,s,x,r,p){var w=t.append("g").selectAll("g").data(s).enter().append("g").selectAll("g").data(x).enter().append("g").attr("class","tick").attr("transform",function(y){return"rotate("+(y.angle*180/Math.PI-90)+")translate("+y.radius+",0)"});var v=[],u=[],q=function(y){return y.angle>Math.PI?"end":null};if(p){v=[0,0,0,-4];u=[4,0,"",".35em"];q=null}else{v=[1,0,4,0];u=[0,4,".35em",""]}w.append("line").attr("x1",v[0]).attr("y1",v[1]).attr("x2",v[2]).attr("y1",v[3]).style("stroke","#000");w.append("text").attr("x",u[0]).attr("y",u[1]).attr("dx",u[2]).attr("dy",u[3]).attr("text-anchor",q).attr("transform",r).text(function(y){return y.label})},formatNum:function(q,p){if(p===undefined){p=2}if(q===null){return null}var s=null;if(q<1){s=q.toPrecision(p)}else{var r=Math.round(q.toPrecision(p));if(q<1000){s=r}else{if(q<1000000){s=Math.round((r/1000).toPrecision(3)).toFixed(0)+"K"}else{if(q<1000000000){s=Math.round((r/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return s}};var d=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(p){this.genome=p.genome;this.track_gap=10;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("drawables").on("add",this.add_track,this);this.model.get("drawables").on("remove",this.remove_track,this);var q=this.model.get("config");q.get("arc_dataset_height").on("change:value",this.update_track_bounds,this)},get_circular_tracks:function(){return this.model.get("drawables").filter(function(p){return p.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("drawables").filter(function(p){return p.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var r=this.get_circular_tracks(),s=this.model.get("config").get_value("arc_dataset_height"),p=Math.min(this.$el.width(),this.$el.height()),u=p/2-r.length*(s+this.track_gap)-(this.label_arc_height+this.track_gap),t=n.range(u,p/2,s+this.track_gap);var q=this;return i.map(t,function(v){return[v,v+s]})},render:function(){var y=this,p=y.$el.width(),x=y.$el.height(),u=this.get_circular_tracks(),s=this.get_chord_tracks(),r=y.model.get("config").get_value("total_gap"),t=this.get_tracks_bounds(),q=n.select(y.$el[0]).append("svg").attr("width",p).attr("height",x).attr("pointer-events","all").append("svg:g").call(n.behavior.zoom().on("zoom",function(){var z=n.event.scale;q.attr("transform","translate("+n.event.translate+") scale("+z+")");if(y.scale!==z){if(y.zoom_drag_timeout){clearTimeout(y.zoom_drag_timeout)}y.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+p/2+","+x/2+")").append("svg:g").attr("class","tracks");this.circular_views=u.map(function(A,B){var z=new e({el:q.append("g")[0],track:A,radius_bounds:t[B],genome:y.genome,total_gap:r});z.render();return z});this.chords_views=s.map(function(A){var z=new l({el:q.append("g")[0],track:A,radius_bounds:t[0],genome:y.genome,total_gap:r});z.render();return z});var w=this.circular_views[this.circular_views.length-1].radius_bounds[1],v=[w,w+this.label_arc_height];this.label_track_view=new b({el:q.append("g")[0],track:new d(),radius_bounds:v,genome:y.genome,total_gap:r});this.label_track_view.render()},add_track:function(w){var q=this.model.get("config").get_value("total_gap");if(w.get("track_type")==="DiagonalHeatmapTrack"){var s=this.circular_views[0].radius_bounds,v=new l({el:n.select("g.tracks").append("g")[0],track:w,radius_bounds:s,genome:this.genome,total_gap:q});v.render();this.chords_views.push(v)}else{var u=this.get_tracks_bounds();i.each(this.circular_views,function(x,y){x.update_radius_bounds(u[y])});i.each(this.chords_views,function(x){x.update_radius_bounds(u[0])});var t=this.circular_views.length,p=new e({el:n.select("g.tracks").append("g")[0],track:w,radius_bounds:u[t],genome:this.genome,total_gap:q});p.render();this.circular_views.push(p);var r=u[u.length-1];r[1]=r[0];this.label_track_view.update_radius_bounds(r)}},remove_track:function(q,s,r){var p=this.circular_views[r.index];this.circular_views.splice(r.index,1);p.$el.remove();var t=this.get_tracks_bounds();i.each(this.circular_views,function(u,v){u.update_radius_bounds(t[v])})},update_track_bounds:function(){var p=this.get_tracks_bounds();i.each(this.circular_views,function(q,r){q.update_radius_bounds(p[r])})}});var m=Backbone.View.extend({tagName:"g",initialize:function(p){this.bg_stroke="ccc";this.loading_bg_fill="000";this.bg_fill="ccc";this.total_gap=p.total_gap;this.track=p.track;this.radius_bounds=p.radius_bounds;this.genome=p.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=n.select(this.$el[0])},get_fill_color:function(){var p=this.track.get("config").get_value("block_color");if(!p){p=this.track.get("config").get_value("color")}return p},render:function(){var t=this.parent_elt;if(!t){console.log("no parent elt")}var s=this.chroms_layout,v=n.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),p=t.selectAll("g").data(s).enter().append("svg:g"),r=p.append("path").attr("d",v).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);r.append("title").text(function(x){return x.data.chrom});var q=this,u=q.track.get("data_manager"),w=(u?u.data_is_ready():true);$.when(w).then(function(){$.when(q._render_data(t)).then(function(){r.style("fill",q.bg_fill);q.render_labels()})})},render_labels:function(){},update_radius_bounds:function(q){this.radius_bounds=q;var p=n.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",p);this._transition_chrom_data();this._transition_labels()},update_scale:function(s){var r=this.scale;this.scale=s;if(s<=r){return}var q=this,p=new o();this.parent_elt.selectAll("path.chrom-data").filter(function(u,t){return p.is_visible(this)}).each(function(z,v){var y=n.select(this),u=y.attr("chrom"),x=q.genome.get_chrom_region(u),w=q.track.get("data_manager"),t;if(!w.can_get_more_detailed_data(x)){return}t=q.track.get("data_manager").get_more_detailed_data(x,"Coverage",0,s);$.when(t).then(function(C){y.remove();q._update_data_bounds();var B=i.find(q.chroms_layout,function(D){return D.data.chrom===u});var A=q.get_fill_color();q._render_chrom_data(q.parent_elt,B,C).style("stroke",A).style("fill",A)})});return q},_transition_chrom_data:function(){var q=this.track,s=this.chroms_layout,p=this.parent_elt.selectAll("g>path.chrom-data"),t=p[0].length;if(t>0){var r=this;$.when(q.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){var u=i.reject(i.map(v,function(w,x){var y=null,z=r._get_path_function(s[x],w);if(z){y=z(w.data)}return y}),function(w){return w===null});p.each(function(x,w){n.select(this).transition().duration(1000).attr("d",u[w])})})}},_transition_labels:function(){},_update_data_bounds:function(){var p=this.data_bounds;this.data_bounds=this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));if(this.data_bounds[0]<p[0]||this.data_bounds[1]>p[1]){this._transition_chrom_data()}},_render_data:function(s){var r=this,q=this.chroms_layout,p=this.track,t=$.Deferred();$.when(p.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){r.data_bounds=r.get_data_bounds(v);layout_and_data=i.zip(q,v),chroms_data_layout=i.map(layout_and_data,function(w){var x=w[0],y=w[1];return r._render_chrom_data(s,x,y)});var u=r.get_fill_color();r.parent_elt.selectAll("path.chrom-data").style("stroke",u).style("fill",u);t.resolve(s)});return t},_render_chrom_data:function(p,q,r){},_get_path_function:function(q,p){},_chroms_layout:function(){var q=this.genome.get_chroms_info(),s=n.layout.pie().value(function(u){return u.len}).sort(null),t=s(q),p=2*Math.PI*this.total_gap/q.length,r=i.map(t,function(w,v){var u=w.endAngle-p;w.endAngle=(u>w.startAngle?u:w.startAngle);return w});return r}});var b=m.extend({initialize:function(p){m.prototype.initialize.call(this,p);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="fff";this.bg_fill="fff";this.min_arc_len=0.05},_render_data:function(r){var q=this,p=r.selectAll("g");p.selectAll("path").attr("id",function(v){return"label-"+v.data.chrom});p.append("svg:text").filter(function(v){return v.endAngle-v.startAngle>q.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("class","chrom-label").attr("xlink:href",function(v){return"#label-"+v.data.chrom}).attr("startOffset","25%").text(function(v){return v.data.chrom});var s=function(x){var v=(x.endAngle-x.startAngle)/x.value,w=n.range(0,x.value,25000000).map(function(y,z){return{radius:q.innerRadius,angle:y*v+x.startAngle,label:z===0?0:(z%3?null:q.formatNum(y))}});if(w.length<4){w[w.length-1].label=q.formatNum(Math.round((w[w.length-1].angle-x.startAngle)/v))}return w};var u=function(v){return v.angle>Math.PI?"rotate(180)translate(-16)":null};var t=i.filter(this.chroms_layout,function(v){return v.endAngle-v.startAngle>q.min_arc_len});this.drawTicks(this.parent_elt,t,s,u)}});i.extend(b.prototype,j);var g=m.extend({_quantile:function(q,p){q.sort(n.ascending);return n.quantile(q,p)},_render_chrom_data:function(p,s,q){var t=this._get_path_function(s,q);if(!t){return null}var r=p.datum(q.data),u=r.append("path").attr("class","chrom-data").attr("chrom",s.data.chrom).attr("d",t);return u},_get_path_function:function(s,r){if(typeof r==="string"||!r.data||r.data.length===0){return null}var p=n.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var t=n.scale.linear().domain([0,r.data.length]).range([s.startAngle,s.endAngle]);var q=n.svg.line.radial().interpolate("linear").radius(function(u){return p(u[1])}).angle(function(v,u){return t(u)});return n.svg.area.radial().interpolate(q.interpolate()).innerRadius(p(0)).outerRadius(q.radius()).angle(q.angle())},render_labels:function(){var p=this,q=function(){return"rotate(90)"};this.drawTicks(this.parent_elt,[this.chroms_layout[0]],this._data_bounds_ticks_fn(),q,true)},_transition_labels:function(){if(this.data_bounds.length===0){return}var q=this,s=i.filter(this.chroms_layout,function(t){return t.endAngle-t.startAngle>0.08}),r=i.filter(s,function(u,t){return t%3===0}),p=i.flatten(i.map(r,function(t){return q._data_bounds_ticks_fn()(t)}));this.parent_elt.selectAll("g.tick").data(p).transition().attr("transform",function(t){return"rotate("+(t.angle*180/Math.PI-90)+")translate("+t.radius+",0)"})},_data_bounds_ticks_fn:function(){var p=this;visibleChroms=0;return function(q){return[{radius:p.radius_bounds[0],angle:q.startAngle,label:p.formatNum(p.data_bounds[0])},{radius:p.radius_bounds[1],angle:q.startAngle,label:p.formatNum(p.data_bounds[1])}]}},get_data_bounds:function(p){}});i.extend(g.prototype,j);var e=g.extend({get_data_bounds:function(q){var p=i.flatten(i.map(q,function(r){if(r){return i.map(r.data,function(s){return parseInt(s[1],10)||0})}else{return 0}}));return[i.min(p),this._quantile(p,0.98)||i.max(p)]}});var l=m.extend({render:function(){var p=this;$.when(p.track.get("data_manager").data_is_ready()).then(function(){$.when(p.track.get("data_manager").get_genome_wide_data(p.genome)).then(function(s){var r=[],q=p.genome.get_chroms_info();i.each(s,function(w,v){var t=q[v].chrom;var u=i.map(w.data,function(y){var x=p._get_region_angle(t,y[1]),z=p._get_region_angle(y[3],y[4]);return{source:{startAngle:x,endAngle:x+0.01},target:{startAngle:z,endAngle:z+0.01}}});r=r.concat(u)});p.parent_elt.append("g").attr("class","chord").selectAll("path").data(r).enter().append("path").style("fill",p.get_fill_color()).attr("d",n.svg.chord().radius(p.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(p){this.radius_bounds=p;this.parent_elt.selectAll("path").transition().attr("d",n.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(r,p){var q=i.find(this.chroms_layout,function(s){return s.data.chrom===r});return q.endAngle-((q.endAngle-q.startAngle)*(q.data.len-p)/q.data.len)}});var f=Backbone.View.extend({initialize:function(){var p=new k.Genome(galaxy_config.app.genome),q=new k.GenomeVisualization(galaxy_config.app.viz_config);q.get("config").add([{key:"arc_dataset_height",label:"Arc Dataset Height",type:"int",value:25,view:"circster"},{key:"total_gap",label:"Gap [0-1]",type:"float",value:0.4,view:"circster",hidden:true}]);var s=new a({el:$("#center .unified-panel-body"),genome:p,model:q});s.render();$("#center .unified-panel-header-inner").append(galaxy_config.app.viz_config.title+" "+galaxy_config.app.viz_config.dbkey);var r=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){k.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",q.get("dbkey"),function(t){q.add_tracks(t)})}},{icon_class:"gear",title:"Settings",on_click:function(){var t=new c.ConfigSettingCollectionView({collection:q.get("config")});t.render_in_modal("Configure Visualization")}},{icon_class:"disk--arrow",title:"Save",on_click:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});$.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:q.get("vis_id"),title:q.get("title"),dbkey:q.get("dbkey"),type:"trackster",vis_json:JSON.stringify(q)}}).success(function(t){Galaxy.modal.hide();q.set("vis_id",t.vis_id)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=galaxy_config.root+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});r.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(r.$el);$(".menu-button").tooltip({placement:"bottom"})}});return{GalaxyApp:f}});
\ No newline at end of file
+define(["utils/utils","libs/underscore","libs/d3","viz/visualization","utils/config"],function(h,i,n,k,c){h.cssLoadFile("static/style/circster.css");var o=Backbone.Model.extend({is_visible:function(s,p){var q=s.getBoundingClientRect(),r=$("svg")[0].getBoundingClientRect();if(q.right<0||q.left>r.right||q.bottom<0||q.top>r.bottom){return false}return true}});var j={drawTicks:function(t,s,x,r,p){var w=t.append("g").selectAll("g").data(s).enter().append("g").selectAll("g").data(x).enter().append("g").attr("class","tick").attr("transform",function(y){return"rotate("+(y.angle*180/Math.PI-90)+")translate("+y.radius+",0)"});var v=[],u=[],q=function(y){return y.angle>Math.PI?"end":null};if(p){v=[0,0,0,-4];u=[4,0,"",".35em"];q=null}else{v=[1,0,4,0];u=[0,4,".35em",""]}w.append("line").attr("x1",v[0]).attr("y1",v[1]).attr("x2",v[2]).attr("y1",v[3]).style("stroke","#000");w.append("text").attr("x",u[0]).attr("y",u[1]).attr("dx",u[2]).attr("dy",u[3]).attr("text-anchor",q).attr("transform",r).text(function(y){return y.label})},formatNum:function(q,p){if(p===undefined){p=2}if(q===null){return null}var s=null;if(q<1){s=q.toPrecision(p)}else{var r=Math.round(q.toPrecision(p));if(q<1000){s=r}else{if(q<1000000){s=Math.round((r/1000).toPrecision(3)).toFixed(0)+"K"}else{if(q<1000000000){s=Math.round((r/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return s}};var d=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(p){this.genome=p.genome;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("drawables").on("add",this.add_track,this);this.model.get("drawables").on("remove",this.remove_track,this);var q=this.model.get("config");q.get("arc_dataset_height").on("change:value",this.update_track_bounds,this);q.get("track_gap").on("change:value",this.update_track_bounds,this)},get_circular_tracks:function(){return this.model.get("drawables").filter(function(p){return p.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("drawables").filter(function(p){return p.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var r=this.get_circular_tracks(),t=this.model.get("config").get_value("arc_dataset_height"),s=this.model.get("config").get_value("track_gap"),p=Math.min(this.$el.width(),this.$el.height())-20,v=p/2-r.length*(t+s)+s-this.label_arc_height,u=n.range(v,p/2,t+s);var q=this;return i.map(u,function(w){return[w,w+t]})},render:function(){var y=this,p=y.$el.width(),x=y.$el.height(),u=this.get_circular_tracks(),s=this.get_chord_tracks(),r=y.model.get("config").get_value("total_gap"),t=this.get_tracks_bounds(),q=n.select(y.$el[0]).append("svg").attr("width",p).attr("height",x).attr("pointer-events","all").append("svg:g").call(n.behavior.zoom().on("zoom",function(){var z=n.event.scale;q.attr("transform","translate("+n.event.translate+") scale("+z+")");if(y.scale!==z){if(y.zoom_drag_timeout){clearTimeout(y.zoom_drag_timeout)}y.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+p/2+","+x/2+")").append("svg:g").attr("class","tracks");this.circular_views=u.map(function(A,B){var z=new e({el:q.append("g")[0],track:A,radius_bounds:t[B],genome:y.genome,total_gap:r});z.render();return z});this.chords_views=s.map(function(A){var z=new l({el:q.append("g")[0],track:A,radius_bounds:t[0],genome:y.genome,total_gap:r});z.render();return z});var w=this.circular_views[this.circular_views.length-1].radius_bounds[1],v=[w,w+this.label_arc_height];this.label_track_view=new b({el:q.append("g")[0],track:new d(),radius_bounds:v,genome:y.genome,total_gap:r});this.label_track_view.render()},add_track:function(v){var q=this.model.get("config").get_value("total_gap");if(v.get("track_type")==="DiagonalHeatmapTrack"){var r=this.circular_views[0].radius_bounds,u=new l({el:n.select("g.tracks").append("g")[0],track:v,radius_bounds:r,genome:this.genome,total_gap:q});u.render();this.chords_views.push(u)}else{var t=this.get_tracks_bounds();i.each(this.circular_views,function(w,x){w.update_radius_bounds(t[x])});i.each(this.chords_views,function(w){w.update_radius_bounds(t[0])});var s=this.circular_views.length,p=new e({el:n.select("g.tracks").append("g")[0],track:v,radius_bounds:t[s],genome:this.genome,total_gap:q});p.render();this.circular_views.push(p)}},remove_track:function(q,s,r){var p=this.circular_views[r.index];this.circular_views.splice(r.index,1);p.$el.remove();var t=this.get_tracks_bounds();i.each(this.circular_views,function(u,v){u.update_radius_bounds(t[v])})},update_track_bounds:function(){var p=this.get_tracks_bounds();i.each(this.circular_views,function(q,r){q.update_radius_bounds(p[r])});i.each(this.chords_views,function(q){q.update_radius_bounds(p[0])})}});var m=Backbone.View.extend({tagName:"g",initialize:function(p){this.bg_stroke="ddd";this.loading_bg_fill="ffc";this.bg_fill="ddd";this.total_gap=p.total_gap;this.track=p.track;this.radius_bounds=p.radius_bounds;this.genome=p.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=n.select(this.$el[0])},get_fill_color:function(){var p=this.track.get("config").get_value("block_color");if(!p){p=this.track.get("config").get_value("color")}return p},render:function(){var t=this.parent_elt;if(!t){console.log("no parent elt")}var s=this.chroms_layout,v=n.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),p=t.selectAll("g").data(s).enter().append("svg:g"),r=p.append("path").attr("d",v).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);r.append("title").text(function(x){return x.data.chrom});var q=this,u=q.track.get("data_manager"),w=(u?u.data_is_ready():true);$.when(w).then(function(){$.when(q._render_data(t)).then(function(){r.style("fill",q.bg_fill);q.render_labels()})})},render_labels:function(){},update_radius_bounds:function(q){this.radius_bounds=q;var p=n.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",p);this._transition_chrom_data();this._transition_labels()},update_scale:function(s){var r=this.scale;this.scale=s;if(s<=r){return}var q=this,p=new o();this.parent_elt.selectAll("path.chrom-data").filter(function(u,t){return p.is_visible(this)}).each(function(z,v){var y=n.select(this),u=y.attr("chrom"),x=q.genome.get_chrom_region(u),w=q.track.get("data_manager"),t;if(!w.can_get_more_detailed_data(x)){return}t=q.track.get("data_manager").get_more_detailed_data(x,"Coverage",0,s);$.when(t).then(function(C){y.remove();q._update_data_bounds();var B=i.find(q.chroms_layout,function(D){return D.data.chrom===u});var A=q.get_fill_color();q._render_chrom_data(q.parent_elt,B,C).style("stroke",A).style("fill",A)})});return q},_transition_chrom_data:function(){var q=this.track,s=this.chroms_layout,p=this.parent_elt.selectAll("g>path.chrom-data"),t=p[0].length;if(t>0){var r=this;$.when(q.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){var u=i.reject(i.map(v,function(w,x){var y=null,z=r._get_path_function(s[x],w);if(z){y=z(w.data)}return y}),function(w){return w===null});p.each(function(x,w){n.select(this).transition().duration(1000).attr("d",u[w])})})}},_transition_labels:function(){},_update_data_bounds:function(){var p=this.data_bounds;this.data_bounds=this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));if(this.data_bounds[0]<p[0]||this.data_bounds[1]>p[1]){this._transition_chrom_data()}},_render_data:function(s){var r=this,q=this.chroms_layout,p=this.track,t=$.Deferred();$.when(p.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){r.data_bounds=r.get_data_bounds(v);layout_and_data=i.zip(q,v),chroms_data_layout=i.map(layout_and_data,function(w){var x=w[0],y=w[1];return r._render_chrom_data(s,x,y)});var u=r.get_fill_color();r.parent_elt.selectAll("path.chrom-data").style("stroke",u).style("fill",u);t.resolve(s)});return t},_render_chrom_data:function(p,q,r){},_get_path_function:function(q,p){},_chroms_layout:function(){var q=this.genome.get_chroms_info(),s=n.layout.pie().value(function(u){return u.len}).sort(null),t=s(q),p=2*Math.PI*this.total_gap/q.length,r=i.map(t,function(w,v){var u=w.endAngle-p;w.endAngle=(u>w.startAngle?u:w.startAngle);return w});return r}});var b=m.extend({initialize:function(p){m.prototype.initialize.call(this,p);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="fff";this.bg_fill="fff";this.min_arc_len=0.05},_render_data:function(r){var q=this,p=r.selectAll("g");p.selectAll("path").attr("id",function(v){return"label-"+v.data.chrom});p.append("svg:text").filter(function(v){return v.endAngle-v.startAngle>q.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("class","chrom-label").attr("xlink:href",function(v){return"#label-"+v.data.chrom}).attr("startOffset","25%").text(function(v){return v.data.chrom});var s=function(x){var v=(x.endAngle-x.startAngle)/x.value,w=n.range(0,x.value,25000000).map(function(y,z){return{radius:q.innerRadius,angle:y*v+x.startAngle,label:z===0?0:(z%3?null:q.formatNum(y))}});if(w.length<4){w[w.length-1].label=q.formatNum(Math.round((w[w.length-1].angle-x.startAngle)/v))}return w};var u=function(v){return v.angle>Math.PI?"rotate(180)translate(-16)":null};var t=i.filter(this.chroms_layout,function(v){return v.endAngle-v.startAngle>q.min_arc_len});this.drawTicks(this.parent_elt,t,s,u)}});i.extend(b.prototype,j);var g=m.extend({_quantile:function(q,p){q.sort(n.ascending);return n.quantile(q,p)},_render_chrom_data:function(p,s,q){var t=this._get_path_function(s,q);if(!t){return null}var r=p.datum(q.data),u=r.append("path").attr("class","chrom-data").attr("chrom",s.data.chrom).attr("d",t);return u},_get_path_function:function(s,r){if(typeof r==="string"||!r.data||r.data.length===0){return null}var p=n.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var t=n.scale.linear().domain([0,r.data.length]).range([s.startAngle,s.endAngle]);var q=n.svg.line.radial().interpolate("linear").radius(function(u){return p(u[1])}).angle(function(v,u){return t(u)});return n.svg.area.radial().interpolate(q.interpolate()).innerRadius(p(0)).outerRadius(q.radius()).angle(q.angle())},render_labels:function(){var p=this,q=function(){return"rotate(90)"};this.drawTicks(this.parent_elt,[this.chroms_layout[0]],this._data_bounds_ticks_fn(),q,true)},_transition_labels:function(){if(this.data_bounds.length===0){return}var q=this,s=i.filter(this.chroms_layout,function(t){return t.endAngle-t.startAngle>0.08}),r=i.filter(s,function(u,t){return t%3===0}),p=i.flatten(i.map(r,function(t){return q._data_bounds_ticks_fn()(t)}));this.parent_elt.selectAll("g.tick").data(p).transition().attr("transform",function(t){return"rotate("+(t.angle*180/Math.PI-90)+")translate("+t.radius+",0)"})},_data_bounds_ticks_fn:function(){var p=this;visibleChroms=0;return function(q){return[{radius:p.radius_bounds[0],angle:q.startAngle,label:p.formatNum(p.data_bounds[0])},{radius:p.radius_bounds[1],angle:q.startAngle,label:p.formatNum(p.data_bounds[1])}]}},get_data_bounds:function(p){}});i.extend(g.prototype,j);var e=g.extend({get_data_bounds:function(q){var p=i.flatten(i.map(q,function(r){if(r){return i.map(r.data,function(s){return parseInt(s[1],10)||0})}else{return 0}}));return[i.min(p),this._quantile(p,0.5)||i.max(p)]}});var l=m.extend({render:function(){var p=this;$.when(p.track.get("data_manager").data_is_ready()).then(function(){$.when(p.track.get("data_manager").get_genome_wide_data(p.genome)).then(function(s){var r=[],q=p.genome.get_chroms_info();i.each(s,function(w,v){var t=q[v].chrom;var u=i.map(w.data,function(y){var x=p._get_region_angle(t,y[1]),z=p._get_region_angle(y[3],y[4]);return{source:{startAngle:x,endAngle:x+0.01},target:{startAngle:z,endAngle:z+0.01}}});r=r.concat(u)});p.parent_elt.append("g").attr("class","chord").selectAll("path").data(r).enter().append("path").style("fill",p.get_fill_color()).attr("d",n.svg.chord().radius(p.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(p){this.radius_bounds=p;this.parent_elt.selectAll("path").transition().attr("d",n.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(r,p){var q=i.find(this.chroms_layout,function(s){return s.data.chrom===r});return q.endAngle-((q.endAngle-q.startAngle)*(q.data.len-p)/q.data.len)}});var f=Backbone.View.extend({initialize:function(){var p=new k.Genome(galaxy_config.app.genome),q=new k.GenomeVisualization(galaxy_config.app.viz_config);q.get("config").add([{key:"arc_dataset_height",label:"Arc Dataset Height",type:"int",value:25,view:"circster"},{key:"track_gap",label:"Gap Between Tracks",type:"int",value:5,view:"circster"},{key:"total_gap",label:"Gap [0-1]",type:"float",value:0.4,view:"circster",hidden:true}]);var s=new a({el:$("#center .unified-panel-body"),genome:p,model:q});s.render();$("#center .unified-panel-header-inner").append(galaxy_config.app.viz_config.title+" "+galaxy_config.app.viz_config.dbkey);var r=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){k.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",q.get("dbkey"),function(t){q.add_tracks(t)})}},{icon_class:"gear",title:"Settings",on_click:function(){var t=new c.ConfigSettingCollectionView({collection:q.get("config")});t.render_in_modal("Configure Visualization")}},{icon_class:"disk--arrow",title:"Save",on_click:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});$.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:q.get("vis_id"),title:q.get("title"),dbkey:q.get("dbkey"),type:"trackster",vis_json:JSON.stringify(q)}}).success(function(t){Galaxy.modal.hide();q.set("vis_id",t.vis_id)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=galaxy_config.root+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});r.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(r.$el);$(".menu-button").tooltip({placement:"bottom"})}});return{GalaxyApp:f}});
\ No newline at end of file
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/utils/uploadbox.js
--- a/static/scripts/utils/uploadbox.js
+++ b/static/scripts/utils/uploadbox.js
@@ -123,6 +123,10 @@
if (queue_running)
return;
+ // backup queue index
+ var current_index = queue_index;
+
+ // add files to queue
for (var i = 0; i < files.length; i++)
{
// check
@@ -136,11 +140,14 @@
queue[index] = files[i];
// announce
- opts.announce(index, queue[index], "");
+ opts.announce(index, queue[index], '');
// increase counter
queue_length++;
}
+
+ // return
+ return current_index;
}
// remove entry from queue
@@ -183,12 +190,15 @@
// remove from queue
remove(index)
+ // collect file details
+ var filesize = file.size;
+ var filemode = file.mode;
+
// identify maximum file size
- var filesize = file.size;
var maxfilesize = 1048576 * opts.maxfilesize;
- // check file size
- if (filesize < maxfilesize)
+ // check file size, unless its an ftp file
+ if (filesize < maxfilesize || file.mode == 'ftp')
{
// get parameters
var data = opts.initialize(index, file);
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/scripts/utils/utils.js
--- a/static/scripts/utils/utils.js
+++ b/static/scripts/utils/utils.js
@@ -71,12 +71,39 @@
return optionsDefault;
};
+// to string
+function bytesToString (size, normal_font) {
+ // identify unit
+ var unit = "";
+ if (size >= 100000000000) { size = size / 100000000000; unit = 'TB'; } else
+ if (size >= 100000000) { size = size / 100000000; unit = 'GB'; } else
+ if (size >= 100000) { size = size / 100000; unit = 'MB'; } else
+ if (size >= 100) { size = size / 100; unit = 'KB'; } else
+ if (size > 0) { size = size * 10; unit = 'b'; } else
+ return '<strong>-</strong>';
+
+ // return formatted string
+ var rounded = (Math.round(size) / 10);
+ if (normal_font) {
+ return rounded + ' ' + unit;
+ } else {
+ return '<strong>' + rounded + '</strong> ' + unit;
+ }
+};
+
+// unique ide
+function uuid(){
+ return (new Date().getTime()).toString(36);
+};
+
// return
return {
cssLoadFile : cssLoadFile,
cssGetAttribute : cssGetAttribute,
jsonFromUrl : jsonFromUrl,
- merge : merge
+ merge : merge,
+ bytesToString: bytesToString,
+ uuid: uuid
};
});
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1250,26 +1250,34 @@
.galaxy-frame .frame .f-close{right:5px;top:3px}
.galaxy-frame .frame .f-pin{left:6px;top:3px}
.galaxy-frame .frame .f-resize{background:#fff;width:16px;height:16px;color:#2c3143;right:0px;bottom:0px;text-align:center;line-height:16px;border:0px}
-.progress-button{position:relative;width:31px;height:21px;top:-4px;cursor:pointer;-moz-border-radius:3px;border-radius:3px}.progress-button .progress{height:21px}
-.progress-button .progress-bar-danger{background:#f9c7c5}
-.progress-button .progress-bar-success{background:#aff1af}
-.progress-button .progress-bar-info{background:#ffc}
-.progress-button .progress-bar-notransition{-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}
-.progress-button .label{position:absolute;top:2px;width:inherit;text-align:center;line-height:19px;font-size:1.2em}
+.upload-button{position:relative;width:31px;height:21px;top:-4px;cursor:pointer;-moz-border-radius:3px;border-radius:3px}.upload-button .progress{height:21px}
+.upload-button .progress-bar-danger{background:#f9c7c5}
+.upload-button .progress-bar-success{background:#aff1af}
+.upload-button .progress-bar-info{background:#ffc}
+.upload-button .progress-bar-notransition{-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none}
+.upload-button .label{position:absolute;top:2px;width:inherit;text-align:center;line-height:19px;font-size:1.2em}
+.upload-icon{font-size:1.2em;width:1.2em}
+.upload-icon-button{font-size:1.2em;width:1.2em;cursor:pointer}
.upload-info{font-weight:normal;text-align:center}
.upload-box{width:100%;height:95%;text-align:center;overflow:scroll;font-size:12px;line-height:1.33;-moz-border-radius:5px;border-radius:5px;border:1px dashed #bfbfbf;padding:10px;overflow-x:hidden;-ms-overflow-style:none}.upload-box .popover{max-width:500px;width:auto}
.upload-box .table{width:100%}
.upload-box .table th{text-align:center;white-space:nowrap}
.upload-box .table td{margin:0px;paddign:0px}
-.upload-box .title{width:130px;word-wrap:break-word;font-size:11px}
+.upload-box .mode{float:left;font-size:1.2em;width:1.2em;color:#555}
+.upload-box .title{width:130px;word-wrap:break-word;font-size:11px;float:left}
.upload-box .text{position:absolute;display:none}.upload-box .text .text-content{font-size:11px;width:100%;height:50px;resize:none;background:inherit;color:#000}
.upload-box .text .text-info{font-size:11px}
.upload-box .extension{width:100px;font-size:11px}
.upload-box .genome{width:150px;font-size:11px}
.upload-box .size{width:60px;white-space:nowrap}
-.upload-box .info{width:130px;font-size:11px}.upload-box .info .progress{top:1px;position:relative;width:100%;padding:0px;margin:0px}.upload-box .info .progress .progress-bar{border-radius:inherit;-moz-border-radius:inherit}
+.upload-box .info{width:130px;font-size:11px;line-height:1.2em}.upload-box .info .progress{top:1px;position:relative;width:100%;padding:0px;margin:0px;line-height:1.55em}.upload-box .info .progress .progress-bar{border-radius:inherit;-moz-border-radius:inherit}
.upload-box .info .progress .percentage{position:absolute;text-align:center;width:100%;color:#fff}
-.upload-box .symbol{font-size:1.2em;cursor:pointer}
+.upload-ftp{height:250px;width:500px;overflow:auto}.upload-ftp .upload-ftp-wait{font-size:1.2em;position:absolute;bottom:10px;right:10px}
+.upload-ftp .upload-ftp-help{margin-bottom:10px}
+.upload-ftp .upload-ftp-warning{text-align:center;margin-top:20px}
+.upload-settings .upload-settings-cover{position:absolute;width:100%;height:100%;top:0px;left:0px;background:#fff;opacity:0.4;cursor:no-drop}
+.popover-view{max-width:700px;display:none}.popover-view .popover-close{position:absolute;right:10px;top:7px;font-size:1.2em;cursor:pointer}
+.popover-view .popover-title{padding:4px 10px}
.libraryRow{background-color:#ebd9b2}
.datasetHighlighted{background-color:#f9f9f9}
.libraryItemDeleted-True{font-style:italic}
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/style/src/less/base.less
--- a/static/style/src/less/base.less
+++ b/static/style/src/less/base.less
@@ -23,6 +23,7 @@
// galaxy sub-components
@import "frame.less";
@import "upload.less";
+@import "ui.less";
@import "library.less";
@import "toastr.less";
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/style/src/less/ui.less
--- /dev/null
+++ b/static/style/src/less/ui.less
@@ -0,0 +1,16 @@
+.popover-view {
+ max-width: 700px;
+ display: none;
+
+ .popover-close {
+ position: absolute;
+ right: 10px;
+ top: 7px;
+ font-size: 1.2em;
+ cursor: pointer;
+ }
+
+ .popover-title {
+ padding: 4px 10px;
+ }
+}
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 static/style/src/less/upload.less
--- a/static/style/src/less/upload.less
+++ b/static/style/src/less/upload.less
@@ -1,4 +1,4 @@
-.progress-button {
+.upload-button {
position: relative;
width: 31px;
height: 21px;
@@ -41,6 +41,17 @@
}
}
+.upload-icon {
+ font-size: 1.2em;
+ width: 1.2em;
+}
+
+.upload-icon-button {
+ font-size: 1.2em;
+ width: 1.2em;
+ cursor: pointer;
+}
+
.upload-info {
font-weight: normal;
text-align: center;
@@ -79,10 +90,18 @@
paddign: 0px;
}
+ .mode {
+ float: left;
+ font-size: 1.2em;
+ width: 1.2em;
+ color: @gray;
+ }
+
.title {
width: 130px;
word-wrap: break-word;
font-size : @font-size-small;
+ float: left;
}
.text {
@@ -122,6 +141,7 @@
.info {
width: 130px;
font-size : @font-size-small;
+ line-height: 1.2em;
.progress {
top:1px;
@@ -129,7 +149,8 @@
width: 100%;
padding: 0px;
margin: 0px;
-
+ line-height: 1.55em;
+
.progress-bar {
border-radius: inherit;
-moz-border-radius: inherit;
@@ -143,9 +164,40 @@
}
}
}
+}
+
+.upload-ftp {
+ height: 250px;
+ width: 500px;
+ overflow: auto;
- .symbol {
+ .upload-ftp-wait {
font-size: 1.2em;
- cursor: pointer;
+ position: absolute;
+ bottom: 10px;
+ right: 10px;
+ }
+
+ .upload-ftp-help {
+ margin-bottom: 10px;
+ }
+
+ .upload-ftp-warning {
+ text-align: center;
+ margin-top: 20px;
}
}
+
+
+.upload-settings {
+ .upload-settings-cover {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0px;
+ left: 0px;
+ background: @white;
+ opacity: 0.4;
+ cursor: no-drop;
+ }
+}
diff -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 -r d8fcf33cbe4ac5e1129c674b1807675b2c02ccc6 templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -52,6 +52,8 @@
'logo_url' : h.url_for(app.config.get( 'logo_url', '/')),
'is_admin_user' : trans.user and app.config.is_admin_user(trans.user),
'active_view' : active_view,
+ 'ftp_upload_dir' : app.config.get("ftp_upload_dir", None),
+ 'ftp_upload_site' : app.config.get("ftp_upload_site", None),
## user details
'user' : {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Minor style and refactoring touch up to new workflow/run.py.
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/21c6fe1aec03/
Changeset: 21c6fe1aec03
User: jmchilton
Date: 2014-02-07 23:59:37
Summary: Minor style and refactoring touch up to new workflow/run.py.
Reduces cyclomatic complexity and makes downstream diffs with dataset collection work less dramatic.
Affected #: 2 files
diff -r 749db2ae03b4ff4c83053322ef291af3b9173325 -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -152,6 +152,7 @@
.add_text( "name", "Name", value=self.state['name'] )
return self.trans.fill_template( "workflow/editor_generic_form.mako",
module=self, form=form )
+
def get_state( self, secure=True ):
return to_json_string( self.state )
@@ -168,11 +169,11 @@
return state
def encode_runtime_state( self, trans, state ):
- fake_tool = Bunch( inputs = self.get_runtime_inputs() )
+ fake_tool = Bunch( inputs=self.get_runtime_inputs() )
return state.encode( fake_tool, trans.app )
def decode_runtime_state( self, trans, string ):
- fake_tool = Bunch( inputs = self.get_runtime_inputs() )
+ fake_tool = Bunch( inputs=self.get_runtime_inputs() )
state = galaxy.tools.DefaultToolState()
state.decode( string, fake_tool, trans.app )
return state
@@ -221,7 +222,7 @@
module.state = galaxy.tools.DefaultToolState()
if module.tool is not None:
if d.get('tool_version', 'Unspecified') != module.get_tool_version():
- module.version_changes.append("%s: using version '%s' instead of version '%s' indicated in this workflow." % (tool_id, d.get('tool_version', 'Unspecified'), module.get_tool_version()) )
+ module.version_changes.append( "%s: using version '%s' instead of version '%s' indicated in this workflow." % ( tool_id, d.get( 'tool_version', 'Unspecified' ), module.get_tool_version() ) )
module.state.decode( d[ "tool_state" ], module.tool, module.trans.app, secure=secure )
module.errors = d.get( "tool_errors", None )
module.post_job_actions = d.get( "post_job_actions", {} )
@@ -329,7 +330,7 @@
data_inputs = None
for name, tool_output in self.tool.outputs.iteritems():
if tool_output.format_source != None:
- formats = [ 'input' ] # default to special name "input" which remove restrictions on connections
+ formats = [ 'input' ] # default to special name "input" which remove restrictions on connections
if data_inputs == None:
data_inputs = self.get_data_inputs()
# find the input parameter referenced by format_source
diff -r 749db2ae03b4ff4c83053322ef291af3b9173325 -r 21c6fe1aec03c44a4fd9abbc2267bec5b29611d5 lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -64,7 +64,6 @@
def _execute_tool_step( self, step ):
trans = self.trans
outputs = self.outputs
- replacement_dict = self.replacement_dict
tool = trans.app.toolbox.get_tool( step.tool_id )
@@ -72,12 +71,7 @@
def callback( input, value, prefixed_name, prefixed_label ):
replacement = None
if isinstance( input, DataToolParameter ):
- if prefixed_name in step.input_connections_by_name:
- conn = step.input_connections_by_name[ prefixed_name ]
- if input.multiple:
- replacement = [outputs[ c.output_step.id ][ c.output_name ] for c in conn]
- else:
- replacement = outputs[ conn[0].output_step.id ][ conn[0].output_name ]
+ replacement = self._replacement_for_input( input, prefixed_name, step )
return replacement
try:
# Replace DummyDatasets with historydatasetassociations
@@ -85,17 +79,10 @@
except KeyError, k:
raise exceptions.MessageException( "Error due to input mapping of '%s' in '%s'. A common cause of this is conditional outputs that cannot be determined until runtime, please review your workflow." % (tool.name, k.message))
# Execute it
- job, out_data = tool.execute( trans, step.state.inputs, history=self.target_history)
+ job, out_data = tool.execute( trans, step.state.inputs, history=self.target_history )
outputs[ step.id ] = out_data
- # Create new PJA associations with the created job, to be run on completion.
- # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
- # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
- for pja in step.post_job_actions:
- if pja.action_type in ActionBox.immediate_actions:
- ActionBox.execute( trans.app, trans.sa_session, pja, job, replacement_dict )
- else:
- job.add_post_job_action(pja)
+ self._handle_post_job_actions( step, job )
return job
def _execute_input_step( self, step ):
@@ -110,10 +97,35 @@
if self.copy_inputs_to_history:
for input_dataset_hda in out_data.values():
new_hda = input_dataset_hda.copy( copy_children=True )
- self.target_history.add_dataset(new_hda)
- outputs[ step.id ]['input_ds_copy'] = new_hda
+ self.target_history.add_dataset( new_hda )
+ outputs[ step.id ][ 'input_ds_copy' ] = new_hda
if self.ds_map:
- outputs[step.id]['output'] = self.ds_map[ str( step.id ) ][ 'hda' ]
+ outputs[ step.id ][ 'output' ] = self.ds_map[ str( step.id ) ][ 'hda' ]
+
return job
+ def _handle_post_job_actions( self, step, job ):
+ # Create new PJA associations with the created job, to be run on completion.
+ # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
+ # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
+ for pja in step.post_job_actions:
+ if pja.action_type in ActionBox.immediate_actions:
+ ActionBox.execute( self.trans.app, self.trans.sa_session, pja, job, self.replacement_dict )
+ else:
+ job.add_post_job_action( pja )
+
+ def _replacement_for_input( self, input, prefixed_name, step ):
+ """ For given workflow 'step' that has had input_connections_by_name
+ populated fetch the actual runtime input for the given tool 'input'.
+ """
+ replacement = None
+ if prefixed_name in step.input_connections_by_name:
+ outputs = self.outputs
+ connection = step.input_connections_by_name[ prefixed_name ]
+ if input.multiple:
+ replacement = [ outputs[ c.output_step.id ][ c.output_name ] for c in connection ]
+ else:
+ replacement = outputs[ connection[ 0 ].output_step.id ][ connection[ 0 ].output_name ]
+ return replacement
+
__all__ = [ invoke ]
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/def88c93886e/
Changeset: def88c93886e
User: jeremy goecks
Date: 2014-02-07 21:02:49
Summary: Backbone config settings view: hide modal before updating model.
Affected #: 1 file
diff -r a253d56a0dd6be3816581a0c7ed0ada191a1693b -r def88c93886e490e70f449644e002277be996b30 static/scripts/utils/config.js
--- a/static/scripts/utils/config.js
+++ b/static/scripts/utils/config.js
@@ -225,9 +225,9 @@
var self = this,
cancel_fn = function() { Galaxy.modal.hide(); $(window).unbind("keypress.check_enter_esc"); },
ok_fn = function() {
- self.update_from_form();
Galaxy.modal.hide();
$(window).unbind("keypress.check_enter_esc");
+ self.update_from_form();
},
check_enter_esc = function(e) {
if ((e.keyCode || e.which) === 27) { // Escape key
https://bitbucket.org/galaxy/galaxy-central/commits/749db2ae03b4/
Changeset: 749db2ae03b4
User: jeremy goecks
Date: 2014-02-07 21:04:42
Summary: Circster: (a) fix bad math that led to incorrect track positioning and (b) make gap between tracks a configurable option.
Affected #: 1 file
diff -r def88c93886e490e70f449644e002277be996b30 -r 749db2ae03b4ff4c83053322ef291af3b9173325 static/scripts/viz/circster.js
--- a/static/scripts/viz/circster.js
+++ b/static/scripts/viz/circster.js
@@ -134,7 +134,6 @@
initialize: function(options) {
this.genome = options.genome;
- this.track_gap = 10;
this.label_arc_height = 50;
this.scale = 1;
this.circular_views = null;
@@ -147,6 +146,7 @@
// When config settings change, update view.
var vis_config = this.model.get('config');
vis_config.get('arc_dataset_height').on('change:value', this.update_track_bounds, this);
+ vis_config.get('track_gap').on('change:value', this.update_track_bounds, this);
},
// HACKs: using track_type for circular/chord distinction in the functions below for now.
@@ -175,16 +175,20 @@
get_tracks_bounds: function() {
var circular_tracks = this.get_circular_tracks(),
dataset_arc_height = this.model.get('config').get_value('arc_dataset_height'),
- min_dimension = Math.min(this.$el.width(), this.$el.height()),
+ track_gap = this.model.get('config').get_value('track_gap'),
+ // Subtract 20 to make sure chrom labels are on screen.
+ min_dimension = Math.min(this.$el.width(), this.$el.height()) - 20,
// Compute radius start based on model, will be centered
// and fit entirely inside element by default.
radius_start = min_dimension / 2 -
- circular_tracks.length * (dataset_arc_height + this.track_gap) -
- (this.label_arc_height + this.track_gap),
+ circular_tracks.length * (dataset_arc_height + track_gap) +
+ // Add track_gap back in because no gap is needed for last track.
+ track_gap -
+ this.label_arc_height,
// Compute range of track starting radii.
- tracks_start_radii = d3.range(radius_start, min_dimension / 2, dataset_arc_height + this.track_gap);
-
+ tracks_start_radii = d3.range(radius_start, min_dimension / 2, dataset_arc_height + track_gap);
+
// Map from track start to bounds.
var self = this;
return _.map(tracks_start_radii, function(radius) {
@@ -317,7 +321,7 @@
else {
// Added circular track.
- // Recompute and update track bounds.
+ // Recompute and update circular track bounds.
var new_track_bounds = this.get_tracks_bounds();
_.each(this.circular_views, function(track_view, i) {
track_view.update_radius_bounds(new_track_bounds[i]);
@@ -341,9 +345,13 @@
this.circular_views.push(track_view);
// Update label track.
+ /*
+ FIXME: should never have to update label track because vis always expands to fit area
+ within label track.
var track_bounds = new_track_bounds[ new_track_bounds.length-1 ];
track_bounds[1] = track_bounds[0];
this.label_track_view.update_radius_bounds(track_bounds);
+ */
}
},
@@ -369,6 +377,12 @@
_.each(this.circular_views, function(track_view, i) {
track_view.update_radius_bounds(new_track_bounds[i]);
});
+
+ // Update chords tracks.
+ _.each(this.chords_views, function(track_view) {
+ track_view.update_radius_bounds(new_track_bounds[0]);
+ });
+
}
});
@@ -381,11 +395,11 @@
/* ----------------------- Public Methods ------------------------- */
initialize: function(options) {
- this.bg_stroke = 'ccc';
+ this.bg_stroke = 'ddd';
// Fill color when loading data.
- this.loading_bg_fill = '000';
+ this.loading_bg_fill = 'ffc';
// Fill color when data has been loaded.
- this.bg_fill = 'ccc';
+ this.bg_fill = 'ddd';
this.total_gap = options.total_gap;
this.track = options.track;
this.radius_bounds = options.radius_bounds;
@@ -898,7 +912,7 @@
// For max, use 98% quantile in attempt to avoid very large values. However, this max may be 0
// for sparsely populated data, so use max in that case.
- return [ _.min(values), this._quantile(values, 0.98) || _.max(values) ];
+ return [ _.min(values), this._quantile(values, 0.5) || _.max(values) ];
}
});
@@ -987,6 +1001,7 @@
// Add Circster-specific config options.
vis.get('config').add([
{ key: 'arc_dataset_height', label: 'Arc Dataset Height', type: 'int', value: 25, view: 'circster' },
+ { key: 'track_gap', label: 'Gap Between Tracks', type: 'int', value: 5, view: 'circster' },
{ key: 'total_gap', label: 'Gap [0-1]', type: 'float', value: 0.4, view: 'circster', hidden: true }
]);
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: Visualizations framework: allow for saving and loading registry visualizations, allow better merging of kwargs, config, saved config, add config utilities to common/templates; Scatterplot: allow saving as visualization, more mvc-based, increase max zoom, refactor and cleanup; Charts, Scatterplot: remove visualization data_source
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a253d56a0dd6/
Changeset: a253d56a0dd6
User: carlfeberhard
Date: 2014-02-07 17:24:32
Summary: Visualizations framework: allow for saving and loading registry visualizations, allow better merging of kwargs, config, saved config, add config utilities to common/templates; Scatterplot: allow saving as visualization, more mvc-based, increase max zoom, refactor and cleanup; Charts, Scatterplot: remove visualization data_source
Affected #: 14 files
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/charts/config/charts.xml
--- a/config/plugins/visualizations/charts/config/charts.xml
+++ b/config/plugins/visualizations/charts/config/charts.xml
@@ -7,15 +7,9 @@
<test type="isinstance" test_attr="datatype" result_type="datatype">tabular.Tabular</test><to_param param_attr="id">dataset_id</to_param></data_source>
- <data_source>
- <model_class>Visualization</model_class>
- <test test_attr="type">charts</test>
- <to_param param_attr="id">visualization_id</to_param>
- </data_source></data_sources><params><param type="dataset" var_name_in_template="hda" required="true">dataset_id</param>
- <param type="visualization" var_name_in_template="visualization">visualization_id</param></params><template>charts.mako</template></visualization>
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/common/templates/config_utils.mako
--- /dev/null
+++ b/config/plugins/visualizations/common/templates/config_utils.mako
@@ -0,0 +1,46 @@
+<%def name="add_config_defaults( defaults )">
+## overwrite default_config_dict with config (if any) then assign to config
+<%
+ for key, default in defaults.items():
+ if key not in config or config[ key ] is None:
+ config[ key ] = default
+%>
+</%def>
+
+<%def name="config_form( config_dict )">
+## render form for everything in possible config
+</%def>
+
+<%def name="link_to_change_config( link_contents, new_settings, target='' )">
+<%
+ # assumes there's a config var
+ url_for_args = {
+ 'controller' : 'visualization',
+ 'action' : 'render',
+ 'visualization_name' : visualization_name,
+ 'title' : title
+ }
+ url_for_args.update( config )
+ url_for_args.update( new_settings )
+ if visualization_id:
+ url_for_args[ 'id' ] = visualization_id
+%>
+ <a href="${h.url_for( **url_for_args )}" target="${target}">${link_contents}</a>
+</%def>
+
+<%def name="save_button( text='Save' )">
+<%
+ # still a GET
+ url_for_args = {
+ 'controller' : 'visualization',
+ 'action' : 'saved',
+ 'type' : visualization_name,
+ 'title' : title,
+ 'config' : h.to_json_string( config )
+ }
+ # save to existing visualization
+ if visualization_id:
+ url_for_args[ 'id' ] = visualization_id
+%>
+ <form action="${h.url_for( **url_for_args )}" method="post"><input type="submit" value="${text}" /></form>
+</%def>
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/common/templates/visualization_base.mako
--- /dev/null
+++ b/config/plugins/visualizations/common/templates/visualization_base.mako
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+<% _=n_ %>
+
+%if embedded:
+ ${self.as_embedded()}
+%else:
+ ${self.as_page()}
+%endif
+
+## render this inside another page or via ajax
+<%def name="as_embedded()">
+ ${self.stylesheets()}
+ ${self.javascripts()}
+ ${self.get_body()}
+</%def>
+
+## render this as it's own page
+<%def name="as_page()">
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>${self.title()}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ ${self.metas()}
+ ${self.stylesheets()}
+ ${self.javascripts()}
+ </head>
+ <body>
+ ${self.get_body()}
+ </body>
+</html>
+</%def>
+##TODO: late_javascripts
+
+## Default body
+<%def name="get_body()"></%def>
+
+## Default title
+<%def name="title()">${visualization_name}</%def>
+
+## Additional metas can be defined by templates inheriting from this one.
+<%def name="metas()"></%def>
+
+## Default stylesheets
+<%def name="stylesheets()">
+${h.css('base')}
+</%def>
+
+## Default javascripts
+<%def name="javascripts()">
+${h.js(
+ "libs/jquery/jquery",
+ "libs/jquery/jquery.migrate"
+)}
+
+<script type="text/javascript">
+ // console protection
+ window.console = window.console || {
+ log : function(){},
+ debug : function(){},
+ info : function(){},
+ warn : function(){},
+ error : function(){},
+ assert : function(){}
+ };
+</script>
+</%def>
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/config/scatterplot.xml
--- a/config/plugins/visualizations/scatterplot/config/scatterplot.xml
+++ b/config/plugins/visualizations/scatterplot/config/scatterplot.xml
@@ -7,15 +7,9 @@
<test type="isinstance" test_attr="datatype" result_type="datatype">tabular.Tabular</test><to_param param_attr="id">dataset_id</to_param></data_source>
- <data_source>
- <model_class>Visualization</model_class>
- <test test_attr="type">scatterplot</test>
- <to_param param_attr="id">visualization_id</to_param>
- </data_source></data_sources><params><param type="dataset" var_name_in_template="hda" required="true">dataset_id</param>
- <param type="visualization" var_name_in_template="visualization">visualization_id</param></params><template>scatterplot.mako</template></visualization>
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/src/handlebars/editor.handlebars
--- a/config/plugins/visualizations/scatterplot/src/handlebars/editor.handlebars
+++ b/config/plugins/visualizations/scatterplot/src/handlebars/editor.handlebars
@@ -10,14 +10,20 @@
<a title="Use this tab to change how the chart is drawn"
href="#chart-control" data-toggle="tab" >Chart Controls</a></li>
- {{! both stats and chart start as disabled since there's no info yet }}
+ {{! chart starts as disabled since there's no info yet }}
<li class="disabled"><a title="This tab will display the chart"
href="#chart-display" data-toggle="tab">Chart</a></li>
+ {{! ... }}
+ <li class="file-controls">
+<!-- <button class="copy-btn btn btn-default"
+ title="Save this as a new visualization">Save to new</button>-->
+ <button class="save-btn btn btn-default">Save</button>
+ </li></ul>
- {{! data form, chart config form, stats, and chart all get their own tab }}
+ {{! data form, chart config form, chart all get their own tab }}
<div class="tab-content">
{{! ---------------------------- tab for data settings form }}
<div id="data-control" class="scatterplot-config-control tab-pane active">
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
--- a/config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
+++ b/config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
@@ -1,24 +1,22 @@
/* =============================================================================
todo:
- Remove 'chart' names
- Make this (the config control/editor) and the ScatterplotView (in scatterplot.js) both
- views onto a visualization/revision model
+ import button(display), func(model) - when user doesn't match
Move margins into wid/hi calcs (so final svg dims are w/h)
Better separation of AJAX in scatterplot.js (maybe pass in function?)
Labels should auto fill in chart control when dataset has column_names
Allow column selection/config using the peek output as a base for UI
- Allow setting perPage of config
- Auto render if given data and/or config
+ Allow setting perPage in config
Allow option to auto set width/height based on screen real estate avail.
Handle large number of pages better (Known genes hg19)
Use d3.nest to allow grouping, pagination/filtration by group (e.g. chromCol)
Semantic HTML (figure, caption)
- Save as visualization, load from visualization
Save as SVG/png
Does it work w/ Galaxy.Frame?
Embedding
Small multiples
Drag & Drop other splots onto current (redraw with new axis and differentiate the datasets)
+ Remove 'chart' names
+ Somehow link out from info box?
Subclass on specific datatypes? (vcf, cuffdiff, etc.)
What can be common/useful to other visualizations?
@@ -40,138 +38,190 @@
if( !this.model ){
this.model = new Visualization({ type: 'scatterplot' });
}
- console.log( this + '.initialize, attributes:', attributes );
+ this.log( this + '.initialize, attributes:', attributes );
if( !attributes || !attributes.dataset ){
throw new Error( "ScatterplotConfigEditor requires a dataset" );
}
this.dataset = attributes.dataset;
- console.log( 'dataset:', this.dataset );
+ this.log( 'dataset:', this.dataset );
-//TODO: ScatterplotView -> ScatterplotDisplay, this.plotView -> this.display
- this.plotView = new ScatterplotView({
+ this.display = new ScatterplotDisplay({
dataset : attributes.dataset,
model : this.model
-//TODO: if data
});
},
// ------------------------------------------------------------------------- CONTROLS RENDERING
render : function(){
//console.log( this + '.render' );
-
// render the tab controls, areas and loading indicator
- this.$el.append( ScatterplotConfigEditor.templates.mainLayout({}));
+ this.$el.empty().append( ScatterplotConfigEditor.templates.mainLayout({}));
+ if( this.model.id ){
+ this.$el.find( '.copy-btn' ).show();
+ this.$el.find( '.save-btn' ).text( 'Update saved' );
+ }
+ this.$el.find( '[title]' ).tooltip();
// render the tab content
- this.$el.find( '#data-control' ).append( this._render_dataControl() );
- this._render_chartControls( this.$el.find( '#chart-control' ) );
- //this.$statsDisplay = this.$el.find( '.tab-pane#stats-display' );
+ this._render_dataControl();
+ this._render_chartControls();
this._render_chartDisplay();
- //TODO: auto render if given both x, y column choices in query for page
+ // set up behaviours
- // set up behaviours
- this.$el.find( '[title]' ).tooltip();
-
- // uncomment any of the following to have that tab show on initial load (for testing)
- //this.$el.find( 'ul.nav' ).find( 'a[href="#data-control"]' ).tab( 'show' );
- //this.$el.find( 'ul.nav' ).find( 'a[href="#chart-control"]' ).tab( 'show' );
- //this.$el.find( 'ul.nav' ).find( 'a[href="#stats-display"]' ).tab( 'show' );
- //this.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
+ // auto render if given both x, y column choices
+ var config = this.model.get( 'config' );
+ if( this.model.id && _.isFinite( config.xColumn ) && _.isFinite( config.yColumn ) ){
+ this.renderChart();
+ }
return this;
},
- _render_dataControl : function(){
- // controls for which columns are used to plot datapoints (and ids/additional info to attach if desired)
- var dataset = this.dataset;
+ /** controls for which columns are used to plot datapoints (and ids/additional info to attach if desired) */
+ _render_dataControl : function( $where ){
+ //TODO: better handling of missing column names, column types
+ $where = $where || this.$el;
+ var editor = this,
+ dataset = this.dataset,
+ column_names = dataset.metadata_column_names || [],
+ config = this.model.get( 'config' );
//console.log( 'metadata_column_types:', this.dataset.metadata_column_types );
//console.log( 'metadata_column_names:', this.dataset.metadata_column_names );
- var allColumns = _.map( dataset.metadata_column_types, function( type, i ){
- var column = { index: i, type: type, name: ( 'column ' + ( i + 1 ) ) };
- if( dataset.metadata_column_names && dataset.metadata_column_names[ i ] ){
- column.name = dataset.metadata_column_names[ i ];
- }
- return column;
- });
- var numericColumns = _.filter( allColumns, function( column, i ){
- return ( ( column.type === 'int' ) || ( column.type === 'float' ) );
- });
- if( numericColumns < 2 ){
+//TODO: to peek based control
+ var numericColumns = [],
+ allColumns = _.map( dataset.metadata_column_types, function( type, i ){
+ // save column data for select rendering, adding metadata name if available in dataset
+ var column = { index: i, type: type, name: ( column_names[ i ] || ( 'column ' + ( i + 1 )) ) };
+ // also add column to numerics if numeric type
+ if( ( column.type === 'int' ) || ( column.type === 'float' ) ){
+ numericColumns.push( column );
+ }
+ return column;
+ });
+ if( numericColumns.length < 2 ){
numericColumns = allColumns;
}
//console.log( 'allColumns:', allColumns );
//console.log( 'numericColumns:', numericColumns );
// render the html
- var $dataControl = this.$el.find( '.tab-pane#data-control' );
+ var $dataControl = $where.find( '.tab-pane#data-control' );
$dataControl.html( ScatterplotConfigEditor.templates.dataControl({
allColumns : allColumns,
numericColumns : numericColumns
}));
- // preset to column selectors if they were passed in the config in the query string
- $dataControl.find( '[name="xColumn"]' ).val( this.plotView.config.xColumn || numericColumns[0].index );
- $dataControl.find( '[name="yColumn"]' ).val( this.plotView.config.yColumn || numericColumns[1].index );
- if( this.plotView.config.idColumn !== undefined ){
+//TODO: column selection boilerplate
+ // preset to column selectors if they were passed in the config in the query string; set up events
+ var newConfig = {
+ xColumn : ( _.isFinite( config.xColumn ) )? ( config.xColumn ): ( numericColumns[0].index ),
+ yColumn : ( _.isFinite( config.yColumn ) )? ( config.yColumn ): ( numericColumns[1].index ),
+ idColumn : allColumns[0].index
+ };
+ // use an idColumn from the config or attempt to get one different from the numeric
+ if( _.isFinite( config.idColumn ) ){
+ newConfig.idColumn = config.idColumn;
+ } else {
+ if( allColumns.length > 2 ){
+ var uniqueCol = _.find( allColumns, function( column, i ){
+ return i !== newConfig.xColumn && i !== newConfig.yColumn;
+ });
+ newConfig.idColumn = uniqueCol.index;
+ }
+ }
+ config = this.model.set( 'config', newConfig, { silent: true }).get( 'config' );
+
+ $dataControl.find( '[name="xColumn"]' ).val( config.xColumn ).on( 'change', function(){
+ editor.model.set( 'config', { xColumn: Number( $( this ).val() ) });
+ });
+ $dataControl.find( '[name="yColumn"]' ).val( config.yColumn ).on( 'change', function(){
+ editor.model.set( 'config', { yColumn: Number( $( this ).val() ) });
+ });
+ $dataControl.find( 'select[name="idColumn"]' ).val( config.idColumn ).on( 'change', function(){
+ editor.model.set( 'config', { idColumn: Number( $( this ).val() ) });
+ });
+ if( config.idColumn !== undefined ){
$dataControl.find( '#include-id-checkbox' ).prop( 'checked', true ).trigger( 'change' );
- $dataControl.find( 'select[name="idColumn"]' ).val( this.plotView.config.idColumn );
}
+ $dataControl.find( '[title]' ).tooltip();
return $dataControl;
},
- _render_chartControls : function( $chartControls ){
- // tab content to control how the chart is rendered (data glyph size, chart size, etc.)
- $chartControls.html( ScatterplotConfigEditor.templates.chartControl( this.plotView.config ) );
+ /** tab content to control how the chart is rendered (data glyph size, chart size, etc.) */
+ _render_chartControls : function( $where ){
+ $where = $where || this.$el;
+ var editor = this,
+ config = this.model.get( 'config' ),
+ $chartControls = $where.find( '#chart-control' );
+
+ // ---- skeleton/form for controls
+ $chartControls.html( ScatterplotConfigEditor.templates.chartControl( config ) );
//console.debug( '$chartControl:', $chartControls );
- // set up behaviours, js on sliders
- //console.debug( 'numeric sliders:', $chartControls.find( '.numeric-slider-input' ) );
- // what to do when the slider changes: update display and update chartConfig
- var view = this,
- // limits for controls (by control/chartConfig id)
- //TODO: move into TwoVarScatterplot
- controlRanges = {
+ // ---- slider controls
+ // limits for controls (by control/chartConfig id)
+ //TODO: as class attribute
+ var controlRanges = {
'datapointSize' : { min: 2, max: 10, step: 1 },
'width' : { min: 200, max: 800, step: 20 },
'height' : { min: 200, max: 800, step: 20 }
};
function onSliderChange(){
- var $this = $( this );
- $this.siblings( '.slider-output' ).text( $this.slider( 'value' ) );
+ // set the model config when changed and update the slider output text
+ var $this = $( this ),
+ //note: returns a number nicely enough
+ newVal = $this.slider( 'value' );
+ // parent of slide event target has html5 attr data-config-key
+ editor.model.set( 'config', _.object([[ $this.parent().data( 'config-key' ), newVal ]]) );
+ $this.siblings( '.slider-output' ).text( newVal );
}
+
+ //console.debug( 'numeric sliders:', $chartControls.find( '.numeric-slider-input' ) );
$chartControls.find( '.numeric-slider-input' ).each( function(){
+ // set up the slider with control ranges, change event; set output text to initial value
var $this = $( this ),
configKey = $this.attr( 'data-config-key' ),
sliderSettings = _.extend( controlRanges[ configKey ], {
- value : view.plotView.config[ configKey ],
+ value : config[ configKey ],
change : onSliderChange,
slide : onSliderChange
});
//console.debug( configKey + ' slider settings:', sliderSettings );
$this.find( '.slider' ).slider( sliderSettings );
+ $this.children( '.slider-output' ).text( config[ configKey ] );
});
-//TODO: to more common area (like render)?
+
+ // ---- axes labels
+ var columnNames = this.dataset.metadata_column_names || [];
+ var xLabel = config.xLabel || columnNames[ config.xColumn ] || 'X';
+ var yLabel = config.yLabel || columnNames[ config.yColumn ] || 'Y';
// set label inputs to current x, y metadata_column_names (if any)
- if( this.dataset.metadata_column_names ){
- //var colNames = this.dataset.metadata_column_names;
- //$chartControls.find( 'input[name="X-axis-label"]' ).val( colNames );
- //$chartControls.find( 'input[name="Y-axis-label"]' ).val( colNames );
-//TODO: on change of x, y data controls
- }
+ $chartControls.find( 'input[name="X-axis-label"]' ).val( xLabel )
+ .on( 'change', function(){
+ editor.model.set( 'config', { xLabel: $( this ).val() });
+ });
+ $chartControls.find( 'input[name="Y-axis-label"]' ).val( yLabel )
+ .on( 'change', function(){
+ editor.model.set( 'config', { yLabel: $( this ).val() });
+ });
//console.debug( '$chartControls:', $chartControls );
+ $chartControls.find( '[title]' ).tooltip();
return $chartControls;
},
- _render_chartDisplay : function(){
- // render the tab content where the chart is displayed (but not the chart itself)
- var $chartDisplay = this.$el.find( '.tab-pane#chart-display' );
- this.plotView.setElement( $chartDisplay );
- this.plotView.render();
+ /** render the tab content where the chart is displayed (but not the chart itself) */
+ _render_chartDisplay : function( $where ){
+ $where = $where || this.$el;
+ var $chartDisplay = $where.find( '.tab-pane#chart-display' );
+ this.display.setElement( $chartDisplay );
+ this.display.render();
+
+ $chartDisplay.find( '[title]' ).tooltip();
return $chartDisplay;
},
@@ -179,7 +229,22 @@
events : {
'change #include-id-checkbox' : 'toggleThirdColumnSelector',
'click #data-control .render-button' : 'renderChart',
- 'click #chart-control .render-button' : 'renderChart'
+ 'click #chart-control .render-button' : 'renderChart',
+ 'click .save-btn' : 'saveVisualization',
+ //'click .copy-btn' : function(e){ this.model.save(); }
+ },
+
+ saveVisualization : function(){
+ var editor = this;
+ this.model.save()
+ .fail( function( xhr, status, message ){
+ console.error( xhr, status, message );
+ editor.trigger( 'save:error', view );
+ alert( 'Error loading data:\n' + xhr.responseText );
+ })
+ .then( function(){
+ editor.render();
+ });
},
toggleThirdColumnSelector : function(){
@@ -192,42 +257,9 @@
//console.log( this + '.renderChart' );
// fetch the data, (re-)render the chart
this.$el.find( '.nav li.disabled' ).removeClass( 'disabled' );
- this.updateConfigWithDataSettings();
- this.updateConfigWithChartSettings();
this.$el.find( 'ul.nav' ).find( 'a[href="#chart-display"]' ).tab( 'show' );
- this.plotView.fetchData();
- //console.debug( this.plotView.$el );
- },
-
- // ------------------------------------------------------------------------- GET DATA/CHART SETTINGS
- updateConfigWithDataSettings : function(){
- // parse the column values for both indeces (for the data fetch) and names (for the chart)
- var $dataControls = this.$el.find( '#data-control' );
- var settings = {
- xColumn : Number( $dataControls.find( '[name="xColumn"]' ).val() ),
- yColumn : Number( $dataControls.find( '[name="yColumn"]' ).val() )
- };
- if( $dataControls.find( '#include-id-checkbox' ).prop( 'checked' ) ){
- settings.idColumn = $dataControls.find( '[name="idColumn"]' ).val();
- }
- //console.log( '\t data settings:', settings );
- return _.extend( this.plotView.config, settings );
- },
-
- updateConfigWithChartSettings : function(){
- // gets the user-selected chartConfig from the chart settings panel
- var plotView = this.plotView,
- $chartControls = this.$el.find( '#chart-control' );
- // use a loop of config keys to get the form values for these sliders
- [ 'datapointSize', 'width', 'height' ].forEach( function( v, i ){
- plotView.config[ v ] = $chartControls.find( '.numeric-slider-input[data-config-key="' + v + '"]' )
- .find( '.slider' ).slider( 'value' );
- });
- // update axes labels using chartSettings inputs (if not at defaults), otherwise the selects' colName
- plotView.config.x.label = $chartControls.find( 'input[name="X-axis-label"]' ).val();
- plotView.config.y.label = $chartControls.find( 'input[name="Y-axis-label"]' ).val();
- //console.log( '\t chartSettings:', settings );
- return plotView.config;
+ this.display.fetchData();
+ //console.debug( this.display.$el );
},
toString : function(){
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/src/scatterplot-display.js
--- a/config/plugins/visualizations/scatterplot/src/scatterplot-display.js
+++ b/config/plugins/visualizations/scatterplot/src/scatterplot-display.js
@@ -6,242 +6,242 @@
* computing and displaying data stats
* controls for pagination of data (if needed)
*/
-var ScatterplotView = Backbone.View.extend({
- //TODO: should be a view on visualization(revision) model
+var ScatterplotDisplay = Backbone.View.extend({
- defaults : {
- metadata : {
- dataLines : undefined
- },
-
- pagination : {
- currPage : 0,
- perPage : 3000
- },
-
- width : 400,
- height : 400,
-
- margin : {
- top : 16,
- right : 16,
- bottom : 40,
- left : 54
- },
-
- x : {
- ticks : 10,
- label : 'X'
- },
- y : {
- ticks : 10,
- label : 'Y'
- },
-
- datapointSize : 4,
- animDuration : 500
+ initialize : function( attributes ){
+ this.data = null,
+ this.dataset = attributes.dataset;
+ this.calcNumPages();
},
- initialize : function( attributes ){
- this.config = _.extend( _.clone( this.defaults ), attributes.config || {});
- this.dataset = attributes.dataset;
- //console.debug( this + '.config:', this.config );
- },
-
- updateConfig : function( newConfig ){
- //console.log( this + '.updateConfig:', newConfig );
- this.config = this.config || {};
- //TODO: validate here
- _.extend( this.config, newConfig );
- //TODO: implement rerender flag
+ calcNumPages : function(){
+ var config = this.model.get( 'config' );
+ this.lineCount = this.dataset.metadata_data_lines,
+ this.numPages = ( this.lineCount )?( Math.ceil( this.lineCount / config.pagination.perPage ) ):( undefined );
+ if( !this.lineCount || this.numPages === undefined ){
+ console.warn( 'no data total found' );
+ }
},
fetchData : function(){
//TODO: doesn't work bc it's rendered in render()...
this.showLoadingIndicator( 'getting data' );
//console.debug( 'currPage', this.config.pagination.currPage );
- var view = this;
+ var view = this,
+ config = this.model.get( 'config' ),
//TODO: very tied to datasets - should be generalized eventually
xhr = jQuery.getJSON( '/api/datasets/' + this.dataset.id, {
data_type : 'raw_data',
provider : 'dataset-column',
- limit : this.config.pagination.perPage,
- offset : ( this.config.pagination.currPage * this.config.pagination.perPage )
+ limit : config.pagination.perPage,
+ offset : ( config.pagination.currPage * config.pagination.perPage )
});
xhr.done( function( data ){
- view.renderData( data.data );
+ view.data = data.data;
+ view.trigger( 'data:fetched', view );
+ view.renderData();
});
xhr.fail( function( xhr, status, message ){
+ console.error( xhr, status, message );
+ view.trigger( 'data:error', view );
alert( 'Error loading data:\n' + xhr.responseText );
- console.error( xhr, status, message );
- });
- xhr.always( function(){
- view.hideLoadingIndicator();
});
return xhr;
},
- render : function( data ){
- this.$el.addClass( 'scatterplot-display' ).html([
- '<div class="controls clear"></div>',
+ showLoadingIndicator : function(){
+ // display the loading indicator over the tab panels if hidden, update message (if passed)
+ this.$el.find( '.scatterplot-data-info' ).html([
'<div class="loading-indicator">',
'<span class="fa fa-spinner fa-spin"></span>',
- '<span class="loading-indicator-message"></span>',
+ '<span class="loading-indicator-message">loading...</span>',
+ '</div>'
+ ].join( '' ));
+ },
+
+ template : function(){
+ var html = [
+ '<div class="controls clear">',
+ '<div class="left">',
+ '</div>',
+ '<div class="right">',
+ '<p class="scatterplot-data-info"></p>',
+ '<button class="stats-toggle-btn">Stats</button>',
+ '<button class="rerender-btn">Redraw</button>',
+ '</div>',
'</div>',
'<svg/>', //TODO: id
'<div class="stats-display"></div>'
- ].join( '' ));
- this.$el.children().hide();
+ ].join( '' );
+ return html;
+ },
- if( data ){
- this.renderData( data );
+ render : function(){
+ this.$el.addClass( 'scatterplot-display' ).html( this.template() );
+ if( this.data ){
+ this.renderData();
}
return this;
},
- showLoadingIndicator : function( message, speed ){
- // display the loading indicator over the tab panels if hidden, update message (if passed)
-//TODO: move loading indicator into data-info-text
- message = message || '';
- speed = speed || 'fast';
- var $indicator = this.$el.find( '.loading-indicator' );
-
- if( message ){ $indicator.find( '.loading-indicator-message' ).text( message ); }
- if( !$indicator.is( ':visible' ) ){
- this.toggleStats( false );
- $indicator.css({ left: ( this.config.width / 2 ), top: this.config.height / 2 }).show();
- }
+ renderData : function(){
+ this.renderLeftControls();
+ this.renderRightControls();
+ this.renderPlot( this.data );
+ this.getStats();
},
- hideLoadingIndicator : function( speed ){
- speed = speed || 'fast';
- this.$el.find( '.loading-indicator' ).hide();
+ renderLeftControls : function(){
+ if( this.lineCount ){
+ this.$el.find( '.controls .left' ).empty().append( this.renderPagination() );
+ } else {
+ this.$el.find( '.controls .left' ).empty().append( this.renderPrevNext() );
+ }
+ return this;
},
- renderData : function( data ){
- this.$el.find( '.controls' ).empty().append( this.renderControls( data ) ).show();
- this.renderPlot( data );
- this.getStats( data );
+ renderRightControls : function(){
+ var view = this;
+ this.setLineInfo( this.data );
+ // clear prev. handlers due to closure around data
+ this.$el.find( '.stats-toggle-btn' )
+ .off().click( function(){
+ view.toggleStats();
+ });
+ this.$el.find( '.rerender-btn' )
+ .off().click( function(){
+ view.resetZoom();
+ view.renderPlot( this.data );
+ });
},
- renderControls : function( data ){
- var view = this;
- var $left = $( '<div class="left"></div>' ),
- $right = $( '<div class="right"></div>' );
-
- $left.append([
- this.renderPrevNext( data ),
- this.renderPagination( data )
- ]);
- $right.append([
- this.renderLineInfo( data ),
- $( '<button>Stats</button>' ).addClass( 'stats-toggle-btn' )
- .click( function(){
- view.toggleStats();
- }),
- $( '<button>Redraw</button>' ).addClass( 'rerender-btn' )
- .click( function(){
- view.renderPlot( data );
- })
- ]);
- return [ $left, $right ];
+ /** render and show the d3 plot into the svg node of the view */
+ renderPlot : function(){
+ var view = this,
+ $svg = this.$el.find( 'svg' );
+ // turn off stats, clear previous svg, and make it visible
+ this.toggleStats( false );
+ $svg.off().empty().show()
+ // set up listeners for events from plot
+ .on( 'zoom.scatterplot', function( ev, zoom ){
+ //TODO: possibly throttle this
+ //console.debug( 'zoom.scatterplot', zoom.scale, zoom.translate );
+ view.model.set( 'config', zoom );
+ });
+ //TODO: may not be necessary to off/on this more than the initial on
+ // call the sep. d3 function to generate the plot
+ scatterplot( $svg.get( 0 ), this.model.get( 'config' ), this.data );
},
- renderLineInfo : function( data ){
- var totalLines = this.dataset.metadata_data_lines || 'an unknown number of',
- lineStart = ( this.config.pagination.currPage * this.config.pagination.perPage ),
- lineEnd = lineStart + data.length;
- return $( '<p/>' ).addClass( 'scatterplot-data-info' )
- .text([ 'Displaying lines', lineStart + 1, 'to', lineEnd, 'of', totalLines, 'lines' ].join( ' ' ));
+ setLineInfo : function( data, contents ){
+ if( data ){
+ var config = this.model.get( 'config' ),
+ totalLines = this.lineCount || 'an unknown total',
+ lineStart = config.pagination.currPage * config.pagination.perPage,
+ lineEnd = lineStart + data.length;
+ this.$el.find( '.controls p.scatterplot-data-info' )
+ .text([ lineStart + 1, 'to', lineEnd, 'of', totalLines ].join( ' ' ));
+ } else {
+ this.$el.find( '.controls p.scatterplot-data-info' ).html( contents || '' );
+ }
+
+ return this;
},
- renderPrevNext : function( data ){
- // this is cra-zazy
- if( !data
- || ( this.config.pagination.currPage === 0 && data.length < this.config.pagination.perPage ) ){ return null; }
+ resetZoom : function( scale, translate ){
+ scale = ( scale !== undefined )?( scale ):( 1 );
+ translate = ( translate !== undefined )?( translate ):( [ 0, 0 ] );
+ this.model.set( 'config', { scale: scale, translate: translate } );
+ return this;
+ },
- function makePage$Li( text ){
- return $([ '<li><a href="javascript:void(0);">', text, '</a></li>' ].join( '' ));
- }
-//TODO: cache numPages/numLines in config
+ // ------------------------------------------------------------------------ data pagination
+//TODO: to pagination control
+ goToPage : function( page ){
+ var pagination = this.model.get( 'config' ).pagination;
+ //console.debug( 'goToPage', page, pagination, this.numPages );
+ if( page <= 0 ){ page = 0; }
+ if( this.numPages && page >= this.numPages ){ page = this.numPages - 1; }
+ if( page === pagination.currPage ){ return this; }
+
+ //console.debug( '\t going to page ' + page )
+ pagination.currPage = page;
+ this.model.set( 'config', { pagination: pagination });
+ this.resetZoom();
+ this.fetchData();
+ return this;
+ },
+
+ nextPage : function(){
+ var currPage = this.model.get( 'config' ).pagination.currPage;
+ return this.goToPage( currPage + 1 );
+ },
+
+ prevPage : function(){
+ var currPage = this.model.get( 'config' ).pagination.currPage;
+ return this.goToPage( currPage - 1 );
+ },
+
+ /** render previous and next pagination buttons */
+ renderPrevNext : function(){
+ var config = this.model.get( 'config' );
+ // if there's no data or there's less than one page of data - return null
+ if( !this.data ){ return null; }
+ if( config.pagination.currPage === 0 && this.data.length < config.pagination.perPage ){ return null; }
+
var view = this,
- dataLines = this.dataset.metadata_data_lines,
- numPages = ( dataLines )?( Math.ceil( dataLines / this.config.pagination.perPage ) ):( undefined );
- //console.debug( 'data:', this.dataset.metadata_data_lines, 'numPages:', numPages );
+ $prev = $( '<li><a href="javascript:void(0);">Prev</a></li>' )
+ .click( function(){ view.prevPage(); }),
+ $next = $( '<li><a href="javascript:void(0);">Next</a></li>' )
+ .click( function(){ view.nextPage(); });
- // prev next buttons
- var $prev = makePage$Li( 'Prev' ).click( function(){
- if( view.config.pagination.currPage > 0 ){
- view.config.pagination.currPage -= 1;
- view.fetchData();
- }
- }),
- $next = makePage$Li( 'Next' ).click( function(){
- if( !numPages || view.config.pagination.currPage < ( numPages - 1 ) ){
- view.config.pagination.currPage += 1;
- view.fetchData();
- }
- }),
- $prevNextList = $( '<ul/>' ).addClass( 'pagination data-prev-next' )
- .append([ $prev, $next ]);
-
- if( view.config.pagination.currPage === 0 ){
+ // disable if it either end
+ if( config.pagination.currPage === 0 ){
$prev.addClass( 'disabled' );
}
- if( numPages && view.config.pagination.currPage === ( numPages - 1 ) ){
+ if( this.numPages && config.pagination.currPage === ( this.numPages - 1 ) ){
$next.addClass( 'disabled' );
}
- return $prevNextList;
+ return $( '<ul/>' ).addClass( 'pagination data-prev-next' ).append([ $prev, $next ]);
},
- renderPagination : function( data ){
- // this is cra-zazy
- if( !data
- || ( this.config.pagination.currPage === 0 && data.length < this.config.pagination.perPage ) ){ return null; }
+ /** render page links for each possible page (if we can) */
+ renderPagination : function(){
+ var config = this.model.get( 'config' );
+ // if there's no data, no page count, or there's less than one page of data - return null
+ if( !this.data ){ return null; }
+ if( !this.numPages ){ return null; }
+ if( config.pagination.currPage === 0 && this.data.length < config.pagination.perPage ){ return null; }
- function makePage$Li( text ){
- return $([ '<li><a href="javascript:void(0);">', text, '</a></li>' ].join( '' ));
- }
-//TODO: cache numPages/numLines in config
var view = this,
- dataLines = this.dataset.metadata_data_lines,
- numPages = ( dataLines )?( Math.ceil( dataLines / this.config.pagination.perPage ) ):( undefined );
- //console.debug( 'data:', this.dataset.metadata_data_lines, 'numPages:', numPages );
+ $pagesList = $( '<ul/>' ).addClass( 'pagination data-pages' );
+ pageNumClick = function( ev ){
+ view.goToPage( $( this ).data( 'page' ) );
+ };
- // page numbers (as separate control)
- //var $paginationContainer = $( '<div/>' ).addClass( 'pagination-container' ),
- var $pagesList = $( '<ul/>' ).addClass( 'pagination data-pages' );
- function pageNumClick( ev ){
- view.config.pagination.currPage = $( this ).data( 'page' );
- view.fetchData();
- }
- for( var i=0; i<numPages; i+=1 ){
- // add page data for later event handling
- var $pageLi = makePage$Li( i + 1 ).attr( 'data-page', i ).click( pageNumClick );
- if( i === this.config.pagination.currPage ){
+ for( var i=0; i<this.numPages; i+=1 ){
+ // add html5 data tag 'page' for later click event handler use
+ var $pageLi = $([ '<li><a href="javascript:void(0);">', i + 1, '</a></li>' ].join( '' ))
+ .attr( 'data-page', i ).click( pageNumClick );
+ // highlight the current page
+ if( i === config.pagination.currPage ){
$pageLi.addClass( 'active' );
}
$pagesList.append( $pageLi );
}
- // placing the pages list in an extra container allows us to set a max-width and scroll if overflow
- //$paginationContainer.append( $pagesList );
- //return $paginationContainer;
return $pagesList;
},
- renderPlot : function( data ){
- this.toggleStats( false );
- var $svg = this.$el.find( 'svg' );
- $svg.off().empty().show();
- scatterplot( $svg.get( 0 ), this.config, data );
- },
-
- getStats : function( data ){
- var view = this;
+ // ------------------------------------------------------------------------ statistics display
+ /** create a webworker to calc stats for data given */
+ getStats : function(){
+ if( !this.data ){ return; }
+ var view = this,
+ config = this.model.get( 'config' ),
meanWorker = new Worker( '/plugins/visualizations/scatterplot/static/worker-stats.js' );
meanWorker.postMessage({
- data : data,
- keys : [ this.config.xColumn, this.config.yColumn ]
+ data : this.data,
+ keys : [ config.xColumn, config.yColumn ]
});
meanWorker.onerror = function( event ){
meanWorker.terminate();
@@ -254,9 +254,9 @@
renderStats : function( stats, error ){
//console.debug( 'renderStats:', stats, error );
//console.debug( JSON.stringify( stats, null, ' ' ) );
- var $statsTable = this.$el.find( '.stats-display' );
-
- var xLabel = this.config.x.label, yLabel = this.config.y.label,
+ var config = this.model.get( 'config' ),
+ $statsTable = this.$el.find( '.stats-display' ),
+ xLabel = config.x.label, yLabel = config.y.label,
$table = $( '<table/>' ).addClass( 'table' )
.append([ '<thead><th></th><th>', xLabel, '</th><th>', yLabel, '</th></thead>' ].join( '' ))
.append( _.map( stats, function( stat, key ){
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/src/scatterplot.js
--- a/config/plugins/visualizations/scatterplot/src/scatterplot.js
+++ b/config/plugins/visualizations/scatterplot/src/scatterplot.js
@@ -46,8 +46,9 @@
var zoom = d3.behavior.zoom()
.x( interpolaterFns.x )
.y( interpolaterFns.y )
- .scaleExtent([ 1, 10 ]);
-//TODO: you can prog. set the zoom and pan with zoom.scale( val ) and zoom.translate([ x, y ])...
+ .scaleExtent([ 1, 30 ])
+ .scale( config.scale || 1 )
+ .translate( config.translate || [ 0, 0 ] );
//console.debug( renderTo );
var svg = d3.select( renderTo )
@@ -99,7 +100,7 @@
//console.log( 'axis.y.g:', axis.y.g );
// ................................ axis labels
- var padding = 4;
+ var padding = 6;
// x-axis label
axis.x.label = svg.append( 'text' )
.attr( 'class', 'axis-label' )
@@ -176,18 +177,17 @@
.enter().append( 'svg:circle' )
.classed( "glyph", true )
.attr( "cx", function( d, i ){ return interpolaterFns.x( getX( d, i ) ); })
- // give them a 'entry' position and style
- .attr( "cy", config.height )
+ .attr( "cy", function( d, i ){ return interpolaterFns.y( getY( d, i ) ); })
.attr( "r", 0 );
// for all EXISTING glyphs and those that need to be added: transition anim to final state
datapoints.transition().duration( config.animDuration )
- .attr( "cy", function( d, i ){ return interpolaterFns.y( getY( d, i ) ); })
.attr( "r", config.datapointSize );
//console.log( 'datapoints:', datapoints );
function _redrawDatapointsClipped(){
return datapoints
+ //TODO: interpolates twice
.attr( "cx", function( d, i ){ return interpolaterFns.x( getX( d, i ) ); })
.attr( "cy", function( d, i ){ return interpolaterFns.y( getY( d, i ) ); })
.style( 'display', 'block' )
@@ -200,29 +200,34 @@
return false;
}).style( 'display', 'none' );
}
+ _redrawDatapointsClipped();
// .................................................................... behaviors
function zoomed( scale, translateX, translateY ){
- //console.debug( 'zoom', this, scale, translateX, translateY, arguments );
+ //console.debug( 'zoom', this, zoom.scale(), zoom.translate() );
+
// re-render axis, grid, and datapoints
+ $( '.chart-info-box' ).remove();
axis.redraw();
_redrawDatapointsClipped();
grid = renderGrid();
- $( '.chart-info-box' ).remove();
- $( svg.node() ).trigger( 'zoom.scatterplot', [] );
+
+ $( svg.node() ).trigger( 'zoom.scatterplot', {
+ scale : zoom.scale(),
+ translate : zoom.translate()
+ });
}
//TODO: programmatically set zoom/pan and save in config
//TODO: set pan/zoom limits
zoom.on( "zoom", zoomed );
-
function infoBox( top, left, d ){
// create an abs pos. element containing datapoint data (d) near the point (top, left)
// with added padding to clear the mouse pointer
left += 8;
return $([
'<div class="chart-info-box" style="position: absolute">',
- (( config.idColumn )?( '<div>' + d[ config.idColumn ] + '</div>' ):( '' )),
+ (( config.idColumn !== undefined )?( '<div>' + d[ config.idColumn ] + '</div>' ):( '' )),
'<div>', getX( d ), '</div>',
'<div>', getY( d ), '</div>',
'</div>'
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
--- a/config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
+++ b/config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
@@ -1,1 +1,1 @@
-function scatterplot(a,b,c){function d(){var a={v:{},h:{}};return a.v.lines=p.selectAll("line.v-grid-line").data(m.x.ticks(q.x.fn.ticks()[0])),a.v.lines.enter().append("svg:line").classed("grid-line v-grid-line",!0),a.v.lines.attr("x1",m.x).attr("x2",m.x).attr("y1",0).attr("y2",b.height),a.v.lines.exit().remove(),a.h.lines=p.selectAll("line.h-grid-line").data(m.y.ticks(q.y.fn.ticks()[0])),a.h.lines.enter().append("svg:line").classed("grid-line h-grid-line",!0),a.h.lines.attr("x1",0).attr("x2",b.width).attr("y1",m.y).attr("y2",m.y),a.h.lines.exit().remove(),a}function e(){return t.attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",function(a,b){return m.y(k(a,b))}).style("display","block").filter(function(){var a=d3.select(this).attr("cx"),c=d3.select(this).attr("cy");return 0>a||a>b.width?!0:0>c||c>b.height?!0:!1}).style("display","none")}function f(){q.redraw(),e(),s=d(),$(".chart-info-box").remove(),$(o.node()).trigger("zoom.scatterplot",[])}function g(a,c,d){return c+=8,$(['<div class="chart-info-box" style="position: absolute">',b.idColumn?"<div>"+d[b.idColumn]+"</div>":"","<div>",j(d),"</div>","<div>",k(d),"</div>","</div>"].join("")).css({top:a,left:c,"z-index":2})}var h=function(a,b){return"translate("+a+","+b+")"},i=function(a,b,c){return"rotate("+a+","+b+","+c+")"},j=function(a){return a[b.xColumn]},k=function(a){return a[b.yColumn]},l={x:{extent:d3.extent(c,j)},y:{extent:d3.extent(c,k)}},m={x:d3.scale.linear().domain(l.x.extent).range([0,b.width]),y:d3.scale.linear().domain(l.y.extent).range([b.height,0])},n=d3.behavior.zoom().x(m.x).y(m.y).scaleExtent([1,10]),o=d3.select(a).attr("class","scatterplot").attr("width","100%").attr("height",b.height+(b.margin.top+b.margin.bottom)),p=o.append("g").attr("class","content").attr("transform",h(b.margin.left,b.margin.top)).call(n);p.append("rect").attr("class","zoom-rect").attr("width",b.width).attr("height",b.height).style("fill","transparent");var q={x:{},y:{}};q.x.fn=d3.svg.axis().orient("bottom").scale(m.x).ticks(b.x.ticks).tickFormat(d3.format("s")),q.y.fn=d3.svg.axis().orient("left").scale(m.y).ticks(b.y.ticks).tickFormat(d3.format("s")),q.x.g=p.append("g").attr("class","x axis").attr("transform",h(0,b.height)).call(q.x.fn),q.y.g=p.append("g").attr("class","y axis").call(q.y.fn);var r=4;q.x.label=o.append("text").attr("class","axis-label").text(b.x.label).attr("text-anchor","middle").attr("dominant-baseline","text-after-edge").attr("x",b.width/2+b.margin.left).attr("y",b.height+b.margin.bottom+b.margin.top-r),q.y.label=o.append("text").attr("class","axis-label").text(b.y.label).attr("text-anchor","middle").attr("dominant-baseline","text-before-edge").attr("x",r).attr("y",b.height/2).attr("transform",i(-90,r,b.height/2)),q.redraw=function(){o.select(".x.axis").call(q.x.fn),o.select(".y.axis").call(q.y.fn)};var s=d(),t=p.selectAll(".glyph").data(c).enter().append("svg:circle").classed("glyph",!0).attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",b.height).attr("r",0);t.transition().duration(b.animDuration).attr("cy",function(a,b){return m.y(k(a,b))}).attr("r",b.datapointSize),n.on("zoom",f),t.on("mouseover",function(a,c){var d=d3.select(this);d.style("fill","red").style("fill-opacity",1),p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")-b.datapointSize).attr("y1",d.attr("cy")).attr("x2",0).attr("y2",d.attr("cy")).classed("hoverline",!0),d.attr("cy")<b.height&&p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")).attr("y1",+d.attr("cy")+b.datapointSize).attr("x2",d.attr("cx")).attr("y2",b.height).classed("hoverline",!0);var e=this.getBoundingClientRect();$("body").append(g(e.top,e.right,a)),$(o.node()).trigger("mouseover-datapoint.scatterplot",[this,a,c])}),t.on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",.2),p.selectAll(".hoverline").remove(),$(".chart-info-box").remove()})}this.scatterplot=this.scatterplot||{},this.scatterplot.chartcontrol=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f,g="",h="function",i=this.escapeExpression;return g+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n<div data-config-key="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">',(f=c.datapointSize)?f=f.call(b,{hash:{},data:e}):(f=b.datapointSize,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n</div>\n\n<div data-config-key="width" class="form-input numeric-slider-input">\n <label for="width">Chart width: </label>\n <div class="slider-output">',(f=c.width)?f=f.call(b,{hash:{},data:e}):(f=b.width,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="height" class="form-input numeric-slider-input">\n <label for="height">Chart height: </label>\n <div class="slider-output">',(f=c.height)?f=f.call(b,{hash:{},data:e}):(f=b.height,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="'+i((f=b.x,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<div data-config-key="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="'+i((f=b.y,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.scatterplot.datacontrol=Handlebars.template(function(a,b,c,d,e){function f(a,b){var d,e="";return e+='\n <option value="',(d=c.index)?d=d.call(a,{hash:{},data:b}):(d=a.index,d=typeof d===j?d.apply(a):d),e+=k(d)+'">',(d=c.name)?d=d.call(a,{hash:{},data:b}):(d=a.name,d=typeof d===j?d.apply(a):d),e+=k(d)+"</option>\n "}function g(){return'checked="true"'}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var h,i="",j="function",k=this.escapeExpression,l=this;return i+='<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\n<div class="column-select">\n <label>Data column for X: </label>\n <select name="xColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n<div class="column-select">\n <label>Data column for Y: </label>\n <select name="yColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\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="idColumn">\n ',h=c.each.call(b,b.allColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="first-line-header" style="display: none;">\n <p>Possible headers: ',(h=c.possibleHeaders)?h=h.call(b,{hash:{},data:e}):(h=b.possibleHeaders,h=typeof h===j?h.apply(b):h),i+=k(h)+'\n </p>\n <label for="first-line-header-checkbox">Use the above as column headers?</label>\n <input type="checkbox" name="include-id" id="first-line-header-checkbox"\n ',h=c["if"].call(b,b.usePossibleHeaders,{hash:{},inverse:l.noop,fn:l.program(3,g,e),data:e}),(h||0===h)&&(i+=h),i+='/>\n <p class="help-text-small">\n It looks like Galaxy couldn\'t get proper column headers for this data.\n Would you like to use the column headers above as column names to select columns?\n </p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.scatterplot.editor=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f="";return f+='<div class="scatterplot-editor tabbable tabs-left">\n \n <ul class="nav nav-tabs">\n \n <li class="active">\n <a title="Use this tab to change which data are used"\n href="#data-control" data-toggle="tab">Data Controls</a>\n </li>\n <li>\n <a title="Use this tab to change how the chart is drawn"\n href="#chart-control" data-toggle="tab" >Chart Controls</a>\n </li>\n \n <li class="disabled">\n <a title="This tab will display the chart"\n href="#chart-display" data-toggle="tab">Chart</a>\n </li>\n </ul>\n\n \n <div class="tab-content">\n \n <div id="data-control" class="scatterplot-config-control tab-pane active">\n \n </div>\n \n \n <div id="chart-control" class="scatterplot-config-control tab-pane">\n \n </div>\n\n \n <div id="chart-display" class="scatterplot-display tab-pane"></div>\n\n </div>\n</div>\n'});var ScatterplotConfigEditor=Backbone.View.extend(LoggableMixin).extend({className:"scatterplot-control-form",initialize:function(a){if(this.model||(this.model=new Visualization({type:"scatterplot"})),console.log(this+".initialize, attributes:",a),!a||!a.dataset)throw new Error("ScatterplotConfigEditor requires a dataset");this.dataset=a.dataset,console.log("dataset:",this.dataset),this.plotView=new ScatterplotView({dataset:a.dataset,model:this.model})},render:function(){return this.$el.append(ScatterplotConfigEditor.templates.mainLayout({})),this.$el.find("#data-control").append(this._render_dataControl()),this._render_chartControls(this.$el.find("#chart-control")),this._render_chartDisplay(),this.$el.find("[title]").tooltip(),this},_render_dataControl:function(){var a=this.dataset,b=_.map(a.metadata_column_types,function(b,c){var d={index:c,type:b,name:"column "+(c+1)};return a.metadata_column_names&&a.metadata_column_names[c]&&(d.name=a.metadata_column_names[c]),d}),c=_.filter(b,function(a){return"int"===a.type||"float"===a.type});2>c&&(c=b);var d=this.$el.find(".tab-pane#data-control");return d.html(ScatterplotConfigEditor.templates.dataControl({allColumns:b,numericColumns:c})),d.find('[name="xColumn"]').val(this.plotView.config.xColumn||c[0].index),d.find('[name="yColumn"]').val(this.plotView.config.yColumn||c[1].index),void 0!==this.plotView.config.idColumn&&(d.find("#include-id-checkbox").prop("checked",!0).trigger("change"),d.find('select[name="idColumn"]').val(this.plotView.config.idColumn)),d},_render_chartControls:function(a){function b(){var a=$(this);a.siblings(".slider-output").text(a.slider("value"))}a.html(ScatterplotConfigEditor.templates.chartControl(this.plotView.config));var c=this,d={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};return a.find(".numeric-slider-input").each(function(){var a=$(this),e=a.attr("data-config-key"),f=_.extend(d[e],{value:c.plotView.config[e],change:b,slide:b});a.find(".slider").slider(f)}),this.dataset.metadata_column_names,a},_render_chartDisplay:function(){var a=this.$el.find(".tab-pane#chart-display");return this.plotView.setElement(a),this.plotView.render(),a},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-control .render-button":"renderChart","click #chart-control .render-button":"renderChart"},toggleThirdColumnSelector:function(){this.$el.find('select[name="idColumn"]').parent().toggle()},renderChart:function(){this.$el.find(".nav li.disabled").removeClass("disabled"),this.updateConfigWithDataSettings(),this.updateConfigWithChartSettings(),this.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show"),this.plotView.fetchData()},updateConfigWithDataSettings:function(){var a=this.$el.find("#data-control"),b={xColumn:Number(a.find('[name="xColumn"]').val()),yColumn:Number(a.find('[name="yColumn"]').val())};return a.find("#include-id-checkbox").prop("checked")&&(b.idColumn=a.find('[name="idColumn"]').val()),_.extend(this.plotView.config,b)},updateConfigWithChartSettings:function(){var a=this.plotView,b=this.$el.find("#chart-control");return["datapointSize","width","height"].forEach(function(c){a.config[c]=b.find('.numeric-slider-input[data-config-key="'+c+'"]').find(".slider").slider("value")}),a.config.x.label=b.find('input[name="X-axis-label"]').val(),a.config.y.label=b.find('input[name="Y-axis-label"]').val(),a.config},toString:function(){return"ScatterplotConfigEditor("+(this.dataset?this.dataset.id:"")+")"}});ScatterplotConfigEditor.templates={mainLayout:scatterplot.editor,dataControl:scatterplot.datacontrol,chartControl:scatterplot.chartcontrol};var ScatterplotView=Backbone.View.extend({defaults:{metadata:{dataLines:void 0},pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500},initialize:function(a){this.config=_.extend(_.clone(this.defaults),a.config||{}),this.dataset=a.dataset},updateConfig:function(a){this.config=this.config||{},_.extend(this.config,a)},fetchData:function(){this.showLoadingIndicator("getting data");var a=this;return xhr=jQuery.getJSON("/api/datasets/"+this.dataset.id,{data_type:"raw_data",provider:"dataset-column",limit:this.config.pagination.perPage,offset:this.config.pagination.currPage*this.config.pagination.perPage}),xhr.done(function(b){a.renderData(b.data)}),xhr.fail(function(a,b,c){alert("Error loading data:\n"+a.responseText),console.error(a,b,c)}),xhr.always(function(){a.hideLoadingIndicator()}),xhr},render:function(a){return this.$el.addClass("scatterplot-display").html(['<div class="controls clear"></div>','<div class="loading-indicator">','<span class="fa fa-spinner fa-spin"></span>','<span class="loading-indicator-message"></span>',"</div>","<svg/>",'<div class="stats-display"></div>'].join("")),this.$el.children().hide(),a&&this.renderData(a),this},showLoadingIndicator:function(a,b){a=a||"",b=b||"fast";var c=this.$el.find(".loading-indicator");a&&c.find(".loading-indicator-message").text(a),c.is(":visible")||(this.toggleStats(!1),c.css({left:this.config.width/2,top:this.config.height/2}).show())},hideLoadingIndicator:function(a){a=a||"fast",this.$el.find(".loading-indicator").hide()},renderData:function(a){this.$el.find(".controls").empty().append(this.renderControls(a)).show(),this.renderPlot(a),this.getStats(a)},renderControls:function(a){var b=this,c=$('<div class="left"></div>'),d=$('<div class="right"></div>');return c.append([this.renderPrevNext(a),this.renderPagination(a)]),d.append([this.renderLineInfo(a),$("<button>Stats</button>").addClass("stats-toggle-btn").click(function(){b.toggleStats()}),$("<button>Redraw</button>").addClass("rerender-btn").click(function(){b.renderPlot(a)})]),[c,d]},renderLineInfo:function(a){var b=this.dataset.metadata_data_lines||"an unknown number of",c=this.config.pagination.currPage*this.config.pagination.perPage,d=c+a.length;return $("<p/>").addClass("scatterplot-data-info").text(["Displaying lines",c+1,"to",d,"of",b,"lines"].join(" "))},renderPrevNext:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;var c=this,d=this.dataset.metadata_data_lines,e=d?Math.ceil(d/this.config.pagination.perPage):void 0,f=b("Prev").click(function(){c.config.pagination.currPage>0&&(c.config.pagination.currPage-=1,c.fetchData())}),g=b("Next").click(function(){(!e||c.config.pagination.currPage<e-1)&&(c.config.pagination.currPage+=1,c.fetchData())}),h=$("<ul/>").addClass("pagination data-prev-next").append([f,g]);return 0===c.config.pagination.currPage&&f.addClass("disabled"),e&&c.config.pagination.currPage===e-1&&g.addClass("disabled"),h},renderPagination:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}function c(){d.config.pagination.currPage=$(this).data("page"),d.fetchData()}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;for(var d=this,e=this.dataset.metadata_data_lines,f=e?Math.ceil(e/this.config.pagination.perPage):void 0,g=$("<ul/>").addClass("pagination data-pages"),h=0;f>h;h+=1){var i=b(h+1).attr("data-page",h).click(c);h===this.config.pagination.currPage&&i.addClass("active"),g.append(i)}return g},renderPlot:function(a){this.toggleStats(!1);var b=this.$el.find("svg");b.off().empty().show(),scatterplot(b.get(0),this.config,a)},getStats:function(a){var b=this;meanWorker=new Worker("/plugins/visualizations/scatterplot/static/worker-stats.js"),meanWorker.postMessage({data:a,keys:[this.config.xColumn,this.config.yColumn]}),meanWorker.onerror=function(){meanWorker.terminate()},meanWorker.onmessage=function(a){b.renderStats(a.data)}},renderStats:function(a){var b=this.$el.find(".stats-display"),c=this.config.x.label,d=this.config.y.label,e=$("<table/>").addClass("table").append(["<thead><th></th><th>",c,"</th><th>",d,"</th></thead>"].join("")).append(_.map(a,function(a,b){return $(["<tr><td>",b,"</td><td>",a[0],"</td><td>",a[1],"</td></tr>"].join(""))}));b.empty().append(e)},toggleStats:function(a){var b=this.$el.find(".stats-display");a=void 0===a?b.is(":hidden"):a,a?(this.$el.find("svg").hide(),b.show(),this.$el.find(".controls .stats-toggle-btn").text("Plot")):(b.hide(),this.$el.find("svg").show(),this.$el.find(".controls .stats-toggle-btn").text("Stats"))},toString:function(){return"ScatterplotView()"}}),ScatterplotModel=Visualization.extend({defaults:{type:"scatterplot",config:{metadata:{dataLines:void 0},pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500}}});
\ No newline at end of file
+function scatterplot(a,b,c){function d(){var a={v:{},h:{}};return a.v.lines=p.selectAll("line.v-grid-line").data(m.x.ticks(q.x.fn.ticks()[0])),a.v.lines.enter().append("svg:line").classed("grid-line v-grid-line",!0),a.v.lines.attr("x1",m.x).attr("x2",m.x).attr("y1",0).attr("y2",b.height),a.v.lines.exit().remove(),a.h.lines=p.selectAll("line.h-grid-line").data(m.y.ticks(q.y.fn.ticks()[0])),a.h.lines.enter().append("svg:line").classed("grid-line h-grid-line",!0),a.h.lines.attr("x1",0).attr("x2",b.width).attr("y1",m.y).attr("y2",m.y),a.h.lines.exit().remove(),a}function e(){return t.attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",function(a,b){return m.y(k(a,b))}).style("display","block").filter(function(){var a=d3.select(this).attr("cx"),c=d3.select(this).attr("cy");return 0>a||a>b.width?!0:0>c||c>b.height?!0:!1}).style("display","none")}function f(){$(".chart-info-box").remove(),q.redraw(),e(),s=d(),$(o.node()).trigger("zoom.scatterplot",{scale:n.scale(),translate:n.translate()})}function g(a,c,d){return c+=8,$(['<div class="chart-info-box" style="position: absolute">',void 0!==b.idColumn?"<div>"+d[b.idColumn]+"</div>":"","<div>",j(d),"</div>","<div>",k(d),"</div>","</div>"].join("")).css({top:a,left:c,"z-index":2})}var h=function(a,b){return"translate("+a+","+b+")"},i=function(a,b,c){return"rotate("+a+","+b+","+c+")"},j=function(a){return a[b.xColumn]},k=function(a){return a[b.yColumn]},l={x:{extent:d3.extent(c,j)},y:{extent:d3.extent(c,k)}},m={x:d3.scale.linear().domain(l.x.extent).range([0,b.width]),y:d3.scale.linear().domain(l.y.extent).range([b.height,0])},n=d3.behavior.zoom().x(m.x).y(m.y).scaleExtent([1,30]).scale(b.scale||1).translate(b.translate||[0,0]),o=d3.select(a).attr("class","scatterplot").attr("width","100%").attr("height",b.height+(b.margin.top+b.margin.bottom)),p=o.append("g").attr("class","content").attr("transform",h(b.margin.left,b.margin.top)).call(n);p.append("rect").attr("class","zoom-rect").attr("width",b.width).attr("height",b.height).style("fill","transparent");var q={x:{},y:{}};q.x.fn=d3.svg.axis().orient("bottom").scale(m.x).ticks(b.x.ticks).tickFormat(d3.format("s")),q.y.fn=d3.svg.axis().orient("left").scale(m.y).ticks(b.y.ticks).tickFormat(d3.format("s")),q.x.g=p.append("g").attr("class","x axis").attr("transform",h(0,b.height)).call(q.x.fn),q.y.g=p.append("g").attr("class","y axis").call(q.y.fn);var r=6;q.x.label=o.append("text").attr("class","axis-label").text(b.x.label).attr("text-anchor","middle").attr("dominant-baseline","text-after-edge").attr("x",b.width/2+b.margin.left).attr("y",b.height+b.margin.bottom+b.margin.top-r),q.y.label=o.append("text").attr("class","axis-label").text(b.y.label).attr("text-anchor","middle").attr("dominant-baseline","text-before-edge").attr("x",r).attr("y",b.height/2).attr("transform",i(-90,r,b.height/2)),q.redraw=function(){o.select(".x.axis").call(q.x.fn),o.select(".y.axis").call(q.y.fn)};var s=d(),t=p.selectAll(".glyph").data(c).enter().append("svg:circle").classed("glyph",!0).attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",function(a,b){return m.y(k(a,b))}).attr("r",0);t.transition().duration(b.animDuration).attr("r",b.datapointSize),e(),n.on("zoom",f),t.on("mouseover",function(a,c){var d=d3.select(this);d.style("fill","red").style("fill-opacity",1),p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")-b.datapointSize).attr("y1",d.attr("cy")).attr("x2",0).attr("y2",d.attr("cy")).classed("hoverline",!0),d.attr("cy")<b.height&&p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")).attr("y1",+d.attr("cy")+b.datapointSize).attr("x2",d.attr("cx")).attr("y2",b.height).classed("hoverline",!0);var e=this.getBoundingClientRect();$("body").append(g(e.top,e.right,a)),$(o.node()).trigger("mouseover-datapoint.scatterplot",[this,a,c])}),t.on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",.2),p.selectAll(".hoverline").remove(),$(".chart-info-box").remove()})}this.scatterplot=this.scatterplot||{},this.scatterplot.chartcontrol=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f,g="",h="function",i=this.escapeExpression;return g+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n<div data-config-key="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">',(f=c.datapointSize)?f=f.call(b,{hash:{},data:e}):(f=b.datapointSize,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n</div>\n\n<div data-config-key="width" class="form-input numeric-slider-input">\n <label for="width">Chart width: </label>\n <div class="slider-output">',(f=c.width)?f=f.call(b,{hash:{},data:e}):(f=b.width,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="height" class="form-input numeric-slider-input">\n <label for="height">Chart height: </label>\n <div class="slider-output">',(f=c.height)?f=f.call(b,{hash:{},data:e}):(f=b.height,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="'+i((f=b.x,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<div data-config-key="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="'+i((f=b.y,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.scatterplot.datacontrol=Handlebars.template(function(a,b,c,d,e){function f(a,b){var d,e="";return e+='\n <option value="',(d=c.index)?d=d.call(a,{hash:{},data:b}):(d=a.index,d=typeof d===j?d.apply(a):d),e+=k(d)+'">',(d=c.name)?d=d.call(a,{hash:{},data:b}):(d=a.name,d=typeof d===j?d.apply(a):d),e+=k(d)+"</option>\n "}function g(){return'checked="true"'}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var h,i="",j="function",k=this.escapeExpression,l=this;return i+='<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\n<div class="column-select">\n <label>Data column for X: </label>\n <select name="xColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n<div class="column-select">\n <label>Data column for Y: </label>\n <select name="yColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\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="idColumn">\n ',h=c.each.call(b,b.allColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="first-line-header" style="display: none;">\n <p>Possible headers: ',(h=c.possibleHeaders)?h=h.call(b,{hash:{},data:e}):(h=b.possibleHeaders,h=typeof h===j?h.apply(b):h),i+=k(h)+'\n </p>\n <label for="first-line-header-checkbox">Use the above as column headers?</label>\n <input type="checkbox" name="include-id" id="first-line-header-checkbox"\n ',h=c["if"].call(b,b.usePossibleHeaders,{hash:{},inverse:l.noop,fn:l.program(3,g,e),data:e}),(h||0===h)&&(i+=h),i+='/>\n <p class="help-text-small">\n It looks like Galaxy couldn\'t get proper column headers for this data.\n Would you like to use the column headers above as column names to select columns?\n </p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.scatterplot.editor=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f="";return f+='<div class="scatterplot-editor tabbable tabs-left">\n \n <ul class="nav nav-tabs">\n \n <li class="active">\n <a title="Use this tab to change which data are used"\n href="#data-control" data-toggle="tab">Data Controls</a>\n </li>\n <li>\n <a title="Use this tab to change how the chart is drawn"\n href="#chart-control" data-toggle="tab" >Chart Controls</a>\n </li>\n \n <li class="disabled">\n <a title="This tab will display the chart"\n href="#chart-display" data-toggle="tab">Chart</a>\n </li>\n \n <li class="file-controls">\n<!-- <button class="copy-btn btn btn-default"\n title="Save this as a new visualization">Save to new</button>-->\n <button class="save-btn btn btn-default">Save</button>\n </li>\n </ul>\n\n \n <div class="tab-content">\n \n <div id="data-control" class="scatterplot-config-control tab-pane active">\n \n </div>\n \n \n <div id="chart-control" class="scatterplot-config-control tab-pane">\n \n </div>\n\n \n <div id="chart-display" class="scatterplot-display tab-pane"></div>\n\n </div>\n</div>\n'});var ScatterplotConfigEditor=Backbone.View.extend(LoggableMixin).extend({className:"scatterplot-control-form",initialize:function(a){if(this.model||(this.model=new Visualization({type:"scatterplot"})),this.log(this+".initialize, attributes:",a),!a||!a.dataset)throw new Error("ScatterplotConfigEditor requires a dataset");this.dataset=a.dataset,this.log("dataset:",this.dataset),this.display=new ScatterplotDisplay({dataset:a.dataset,model:this.model})},render:function(){this.$el.empty().append(ScatterplotConfigEditor.templates.mainLayout({})),this.model.id&&(this.$el.find(".copy-btn").show(),this.$el.find(".save-btn").text("Update saved")),this.$el.find("[title]").tooltip(),this._render_dataControl(),this._render_chartControls(),this._render_chartDisplay();var a=this.model.get("config");return this.model.id&&_.isFinite(a.xColumn)&&_.isFinite(a.yColumn)&&this.renderChart(),this},_render_dataControl:function(a){a=a||this.$el;var b=this,c=this.dataset,d=c.metadata_column_names||[],e=this.model.get("config"),f=[],g=_.map(c.metadata_column_types,function(a,b){var c={index:b,type:a,name:d[b]||"column "+(b+1)};return("int"===c.type||"float"===c.type)&&f.push(c),c});f.length<2&&(f=g);var h=a.find(".tab-pane#data-control");h.html(ScatterplotConfigEditor.templates.dataControl({allColumns:g,numericColumns:f}));var i={xColumn:_.isFinite(e.xColumn)?e.xColumn:f[0].index,yColumn:_.isFinite(e.yColumn)?e.yColumn:f[1].index,idColumn:g[0].index};if(_.isFinite(e.idColumn))i.idColumn=e.idColumn;else if(g.length>2){var j=_.find(g,function(a,b){return b!==i.xColumn&&b!==i.yColumn});i.idColumn=j.index}return e=this.model.set("config",i,{silent:!0}).get("config"),h.find('[name="xColumn"]').val(e.xColumn).on("change",function(){b.model.set("config",{xColumn:Number($(this).val())})}),h.find('[name="yColumn"]').val(e.yColumn).on("change",function(){b.model.set("config",{yColumn:Number($(this).val())})}),h.find('select[name="idColumn"]').val(e.idColumn).on("change",function(){b.model.set("config",{idColumn:Number($(this).val())})}),void 0!==e.idColumn&&h.find("#include-id-checkbox").prop("checked",!0).trigger("change"),h.find("[title]").tooltip(),h},_render_chartControls:function(a){function b(){var a=$(this),b=a.slider("value");c.model.set("config",_.object([[a.parent().data("config-key"),b]])),a.siblings(".slider-output").text(b)}a=a||this.$el;var c=this,d=this.model.get("config"),e=a.find("#chart-control");e.html(ScatterplotConfigEditor.templates.chartControl(d));var f={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};e.find(".numeric-slider-input").each(function(){var a=$(this),c=a.attr("data-config-key"),e=_.extend(f[c],{value:d[c],change:b,slide:b});a.find(".slider").slider(e),a.children(".slider-output").text(d[c])});var g=this.dataset.metadata_column_names||[],h=d.xLabel||g[d.xColumn]||"X",i=d.yLabel||g[d.yColumn]||"Y";return e.find('input[name="X-axis-label"]').val(h).on("change",function(){c.model.set("config",{xLabel:$(this).val()})}),e.find('input[name="Y-axis-label"]').val(i).on("change",function(){c.model.set("config",{yLabel:$(this).val()})}),e.find("[title]").tooltip(),e},_render_chartDisplay:function(a){a=a||this.$el;var b=a.find(".tab-pane#chart-display");return this.display.setElement(b),this.display.render(),b.find("[title]").tooltip(),b},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-control .render-button":"renderChart","click #chart-control .render-button":"renderChart","click .save-btn":"saveVisualization"},saveVisualization:function(){var a=this;this.model.save().fail(function(b,c,d){console.error(b,c,d),a.trigger("save:error",view),alert("Error loading data:\n"+b.responseText)}).then(function(){a.render()})},toggleThirdColumnSelector:function(){this.$el.find('select[name="idColumn"]').parent().toggle()},renderChart:function(){this.$el.find(".nav li.disabled").removeClass("disabled"),this.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show"),this.display.fetchData()},toString:function(){return"ScatterplotConfigEditor("+(this.dataset?this.dataset.id:"")+")"}});ScatterplotConfigEditor.templates={mainLayout:scatterplot.editor,dataControl:scatterplot.datacontrol,chartControl:scatterplot.chartcontrol};var ScatterplotDisplay=Backbone.View.extend({initialize:function(a){this.data=null,this.dataset=a.dataset,this.calcNumPages()},calcNumPages:function(){var a=this.model.get("config");this.lineCount=this.dataset.metadata_data_lines,this.numPages=this.lineCount?Math.ceil(this.lineCount/a.pagination.perPage):void 0,this.lineCount&&void 0!==this.numPages||console.warn("no data total found")},fetchData:function(){this.showLoadingIndicator("getting data");var a=this,b=this.model.get("config"),c=jQuery.getJSON("/api/datasets/"+this.dataset.id,{data_type:"raw_data",provider:"dataset-column",limit:b.pagination.perPage,offset:b.pagination.currPage*b.pagination.perPage});return c.done(function(b){a.data=b.data,a.trigger("data:fetched",a),a.renderData()}),c.fail(function(b,c,d){console.error(b,c,d),a.trigger("data:error",a),alert("Error loading data:\n"+b.responseText)}),c},showLoadingIndicator:function(){this.$el.find(".scatterplot-data-info").html(['<div class="loading-indicator">','<span class="fa fa-spinner fa-spin"></span>','<span class="loading-indicator-message">loading...</span>',"</div>"].join(""))},template:function(){var a=['<div class="controls clear">','<div class="left">',"</div>",'<div class="right">','<p class="scatterplot-data-info"></p>','<button class="stats-toggle-btn">Stats</button>','<button class="rerender-btn">Redraw</button>',"</div>","</div>","<svg/>",'<div class="stats-display"></div>'].join("");return a},render:function(){return this.$el.addClass("scatterplot-display").html(this.template()),this.data&&this.renderData(),this},renderData:function(){this.renderLeftControls(),this.renderRightControls(),this.renderPlot(this.data),this.getStats()},renderLeftControls:function(){return this.lineCount?this.$el.find(".controls .left").empty().append(this.renderPagination()):this.$el.find(".controls .left").empty().append(this.renderPrevNext()),this},renderRightControls:function(){var a=this;this.setLineInfo(this.data),this.$el.find(".stats-toggle-btn").off().click(function(){a.toggleStats()}),this.$el.find(".rerender-btn").off().click(function(){a.resetZoom(),a.renderPlot(this.data)})},renderPlot:function(){var a=this,b=this.$el.find("svg");this.toggleStats(!1),b.off().empty().show().on("zoom.scatterplot",function(b,c){a.model.set("config",c)}),scatterplot(b.get(0),this.model.get("config"),this.data)},setLineInfo:function(a,b){if(a){var c=this.model.get("config"),d=this.lineCount||"an unknown total",e=c.pagination.currPage*c.pagination.perPage,f=e+a.length;this.$el.find(".controls p.scatterplot-data-info").text([e+1,"to",f,"of",d].join(" "))}else this.$el.find(".controls p.scatterplot-data-info").html(b||"");return this},resetZoom:function(a,b){return a=void 0!==a?a:1,b=void 0!==b?b:[0,0],this.model.set("config",{scale:a,translate:b}),this},goToPage:function(a){var b=this.model.get("config").pagination;return 0>=a&&(a=0),this.numPages&&a>=this.numPages&&(a=this.numPages-1),a===b.currPage?this:(b.currPage=a,this.model.set("config",{pagination:b}),this.resetZoom(),this.fetchData(),this)},nextPage:function(){var a=this.model.get("config").pagination.currPage;return this.goToPage(a+1)},prevPage:function(){var a=this.model.get("config").pagination.currPage;return this.goToPage(a-1)},renderPrevNext:function(){var a=this.model.get("config");if(!this.data)return null;if(0===a.pagination.currPage&&this.data.length<a.pagination.perPage)return null;var b=this,c=$('<li><a href="javascript:void(0);">Prev</a></li>').click(function(){b.prevPage()}),d=$('<li><a href="javascript:void(0);">Next</a></li>').click(function(){b.nextPage()});return 0===a.pagination.currPage&&c.addClass("disabled"),this.numPages&&a.pagination.currPage===this.numPages-1&&d.addClass("disabled"),$("<ul/>").addClass("pagination data-prev-next").append([c,d])},renderPagination:function(){var a=this.model.get("config");if(!this.data)return null;if(!this.numPages)return null;if(0===a.pagination.currPage&&this.data.length<a.pagination.perPage)return null;var b=this,c=$("<ul/>").addClass("pagination data-pages");pageNumClick=function(){b.goToPage($(this).data("page"))};for(var d=0;d<this.numPages;d+=1){var e=$(['<li><a href="javascript:void(0);">',d+1,"</a></li>"].join("")).attr("data-page",d).click(pageNumClick);d===a.pagination.currPage&&e.addClass("active"),c.append(e)}return c},getStats:function(){if(this.data){var a=this,b=this.model.get("config"),c=new Worker("/plugins/visualizations/scatterplot/static/worker-stats.js");c.postMessage({data:this.data,keys:[b.xColumn,b.yColumn]}),c.onerror=function(){c.terminate()},c.onmessage=function(b){a.renderStats(b.data)}}},renderStats:function(a){var b=this.model.get("config"),c=this.$el.find(".stats-display"),d=b.x.label,e=b.y.label,f=$("<table/>").addClass("table").append(["<thead><th></th><th>",d,"</th><th>",e,"</th></thead>"].join("")).append(_.map(a,function(a,b){return $(["<tr><td>",b,"</td><td>",a[0],"</td><td>",a[1],"</td></tr>"].join(""))}));c.empty().append(f)},toggleStats:function(a){var b=this.$el.find(".stats-display");a=void 0===a?b.is(":hidden"):a,a?(this.$el.find("svg").hide(),b.show(),this.$el.find(".controls .stats-toggle-btn").text("Plot")):(b.hide(),this.$el.find("svg").show(),this.$el.find(".controls .stats-toggle-btn").text("Stats"))},toString:function(){return"ScatterplotView()"}}),ScatterplotModel=Visualization.extend({defaults:{type:"scatterplot",config:{pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500,scale:1,translate:[0,0]}}});
\ No newline at end of file
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/static/scatterplot.css
--- a/config/plugins/visualizations/scatterplot/static/scatterplot.css
+++ b/config/plugins/visualizations/scatterplot/static/scatterplot.css
@@ -39,6 +39,22 @@
font-size: smaller;
}
+.scatterplot-editor .file-controls {
+ float: right;
+ /*margin-right: 16px;*/
+}
+
+.file-controls .btn {
+ height: 24px;
+ padding: 0px 10px 0px 10px;
+ line-height: 24px;
+}
+
+.file-controls .copy-btn {
+ display: none;
+}
+
+
/* ============================================ config controls */
.scatterplot-config-control {
max-width: 768px;
@@ -84,8 +100,6 @@
/* ============================================ plot display */
/* -------------------------------------------- load indicators */
.scatterplot-display .loading-indicator {
- position: absolute;
- margin: 10px 0px 0px 10px;
color: grey;
}
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/scatterplot/templates/scatterplot.mako
--- a/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
+++ b/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
@@ -1,18 +1,8 @@
<%
- hda_dict = trans.security.encode_dict_ids( hda.to_dict() )
-
- config = query_args
- title = "Scatterplot of '" + hda.name + "'"
- info = hda.info
-
- visualization = context.get( 'visualization' )
- if visualization is not None:
- config = visualization.latest_revision.config
- config.update( query_args )
- title = visualization.title
- info = config.get( 'description', info )
-
- config[ 'type' ] = 'scatterplot'
+ default_title = "Scatterplot of '" + hda.name + "'"
+ info = hda.name
+ if hda.info:
+ info += ' : ' + hda.info
# optionally bootstrap data from dprov
##data = list( hda.datatype.dataset_column_dataprovider( hda, limit=10000 ) )
@@ -23,7 +13,7 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>${hda.name} | ${visualization_name}</title>
+<title>${title or default_title} | ${visualization_display_name}</title>
## ----------------------------------------------------------------------------
<link type="text/css" rel="Stylesheet" media="screen" href="/static/style/base.css">
@@ -52,23 +42,29 @@
%if not embedded:
## dataset info: only show if on own page
<div class="chart-header">
- <h2>${title}</h2>
+ <h2>${title or default_title}</h2><p>${info}</p></div><div class="scatterplot-editor"></div><script type="text/javascript">
$(function(){
- var model = new ScatterplotModel( ${h.to_json_string( config )} ),
- hdaJson = ${h.to_json_string( hda_dict )},
+ var model = new ScatterplotModel({
+ id : ${h.to_json_string( visualization_id )} || undefined,
+ title : "${title or default_title}",
+ config : ${h.to_json_string( config, indent=2 )}
+ }),
+ hdaJson = ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )},
editor = new ScatterplotConfigEditor({
el : $( '.scatterplot-editor' ).attr( 'id', 'scatterplot-editor-hda-' + hdaJson.id ),
model : model,
dataset : hdaJson
}).render();
window.editor = editor;
- // uncomment to auto render for development
- //$( '.render-button:visible' ).click();
+
+ model.on( 'change:title', function(){
+ $( '.chart-header h2' ).text( model.get( 'title' ) );
+ })
});
</script>
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b config/plugins/visualizations/visualization_base.mako
--- a/config/plugins/visualizations/visualization_base.mako
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding: utf-8 -*-
-<% _=n_ %>
-
-%if embedded:
- ${self.as_embedded()}
-%else:
- ${self.as_page()}
-%endif
-
-## render this inside another page or via ajax
-<%def name="as_embedded()">
- ${self.stylesheets()}
- ${self.javascripts()}
- ${self.get_body()}
-</%def>
-
-## render this as it's own page
-<%def name="as_page()">
-<!DOCTYPE HTML>
-<html>
- <head>
- <title>${self.title()}</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- ${self.metas()}
- ${self.stylesheets()}
- ${self.javascripts()}
- </head>
- <body>
- ${self.get_body()}
- </body>
-</html>
-</%def>
-##TODO: late_javascripts
-
-## Default body
-<%def name="get_body()"></%def>
-
-## Default title
-<%def name="title()">${visualization_name}</%def>
-
-## Additional metas can be defined by templates inheriting from this one.
-<%def name="metas()"></%def>
-
-## Default stylesheets
-<%def name="stylesheets()">
-${h.css('base')}
-</%def>
-
-## Default javascripts
-<%def name="javascripts()">
-${h.js(
- "libs/jquery/jquery",
- "libs/jquery/jquery.migrate"
-)}
-
-<script type="text/javascript">
- // console protection
- window.console = window.console || {
- log : function(){},
- debug : function(){},
- info : function(){},
- warn : function(){},
- error : function(){},
- assert : function(){}
- };
-</script>
-</%def>
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -223,7 +223,7 @@
def is_object_applicable( self, trans, target_object, data_source_tests ):
"""
Run a visualization's data_source tests to find out if
- it be applied to the target_object.
+ it can be applied to the target_object.
"""
#log.debug( 'is_object_applicable( self, trans, %s, %s )', target_object, data_source_tests )
for test in data_source_tests:
@@ -306,9 +306,9 @@
Both `params` and `param_modifiers` default to an empty dictionary.
"""
- visualization = self.plugins.get( visualization_name )
- expected_params = visualization.config.get( 'params', {} )
- param_modifiers = visualization.config.get( 'param_modifiers', {} )
+ plugin = self.plugins.get( visualization_name )
+ expected_params = plugin.config.get( 'params', {} )
+ param_modifiers = plugin.config.get( 'param_modifiers', {} )
return ( expected_params, param_modifiers )
def query_dict_to_resources( self, trans, controller, visualization_name, query_dict ):
@@ -322,6 +322,16 @@
trans, controller, param_confs, query_dict, param_modifiers )
return resources
+ def query_dict_to_config( self, trans, controller, visualization_name, query_dict ):
+ """
+ Given a query string dict (i.e. kwargs) from a controller action, parse
+ and return any key/value pairs found in the plugin's `params` section.
+ """
+ plugin = self.plugins.get( visualization_name )
+ param_confs = plugin.config.get( 'params', {} )
+ config = self.resource_parser.parse_config( trans, controller, param_confs, query_dict )
+ return config
+
# ------------------------------------------------------------------- parsing the config file
class ParsingException( ValueError ):
@@ -559,37 +569,38 @@
for test_elem in xml_tree_list:
test_type = test_elem.get( 'type', 'eq' )
- test_result = test_elem.text
+ test_result = test_elem.text.strip() if test_elem.text else None
if not test_type or not test_result:
log.warn( 'Skipping test. Needs both type attribute and text node to be parsed: '
+ '%s, %s' %( test_type, test_elem.text ) )
continue
+ test_result = test_result.strip()
# test_attr can be a dot separated chain of object attributes (e.g. dataset.datatype) - convert to list
#TODO: too dangerous - constrain these to some allowed list
#TODO: does this err if no test_attr - it should...
test_attr = test_elem.get( 'test_attr' )
test_attr = test_attr.split( self.ATTRIBUTE_SPLIT_CHAR ) if isinstance( test_attr, str ) else []
+ #log.debug( 'test_type: %s, test_attr: %s, test_result: %s', test_type, test_attr, test_result )
+
# build a lambda function that gets the desired attribute to test
getter = self._build_getattr_lambda( test_attr )
-
# result type should tell the registry how to convert the result before the test
test_result_type = test_elem.get( 'result_type', 'string' )
# test functions should be sent an object to test, and the parsed result expected from the test
-
- # is test_attr attribute an instance of result
if test_type == 'isinstance':
+ # is test_attr attribute an instance of result
#TODO: wish we could take this further but it would mean passing in the datatypes_registry
test_fn = lambda o, result: isinstance( getter( o ), result )
- # does the object itself have a datatype attr and does that datatype have the given dataprovider
elif test_type == 'has_dataprovider':
+ # does the object itself have a datatype attr and does that datatype have the given dataprovider
test_fn = lambda o, result: ( hasattr( getter( o ), 'has_dataprovider' )
and getter( o ).has_dataprovider( result ) )
- # default to simple (string) equilavance (coercing the test_attr to a string)
else:
+ # default to simple (string) equilavance (coercing the test_attr to a string)
test_fn = lambda o, result: str( getter( o ) ) == result
tests.append({
@@ -737,6 +748,16 @@
The keys used to store the new values can optionally be re-mapped to
new keys (e.g. dataset_id="NNN" -> hda=<HistoryDatasetAsscoation>).
"""
+ primitive_parsers = {
+ 'str' : lambda param: galaxy.util.sanitize_html.sanitize_html( param, 'utf-8' ),
+ 'bool' : lambda param: galaxy.util.string_as_bool( param ),
+ 'int' : lambda param: int( param ),
+ 'float' : lambda param: float( param ),
+ #'date' : lambda param: ,
+ 'json' : ( lambda param: galaxy.util.json.from_json_string(
+ galaxy.util.sanitize_html.sanitize_html( param ) ) ),
+ }
+
#TODO: kinda torn as to whether this belongs here or in controllers.visualization
# taking the (questionable) design path of passing a controller in
# (which is the responsible party for getting model, etc. resources )
@@ -749,8 +770,6 @@
If param is required and not present, raises a `KeyError`.
"""
#log.debug( 'parse_parameter_dictionary, query_params:\n%s', query_params )
- # first parse any params from any visualizations that were passed
- query_params = self.get_params_from_visualization_param( trans, controller, param_config_dict, query_params )
# parse the modifiers first since they modify the params coming next
#TODO: this is all really for hda_ldda - which we could replace with model polymorphism
@@ -782,12 +801,43 @@
if resource == None:
if param_config[ 'required' ]:
raise KeyError( 'required param %s not found in URL' %( param_name ) )
- resource = self.parse_parameter_default( trans, param_config )
+ resource = self.parse_parameter_default( trans, controller, param_config )
resources[ var_name_in_template ] = resource
return resources
+ def parse_config( self, trans, controller, param_config_dict, query_params ):
+ """
+ Return `query_params` dict parsing only JSON serializable params.
+ Complex params such as models, etc. are left as the original query value.
+ Keys in `query_params` not found in the `param_config_dict` will not be
+ returned.
+ """
+ #log.debug( 'parse_config, query_params:\n%s', query_params )
+ config = {}
+ for param_name, param_config in param_config_dict.items():
+ config_val = query_params.get( param_name, None )
+ if config_val is not None and param_config[ 'type' ] in self.primitive_parsers:
+ try:
+ config_val = self.parse_parameter( trans, controller, param_config, config_val )
+
+ except Exception, exception:
+ log.warn( 'Exception parsing visualization param from query: '
+ + '%s, %s, (%s) %s' %( param_name, config_val, str( type( exception ) ), str( exception ) ))
+ config_val = None
+
+ # here - we've either had no value in the query_params or there was a failure to parse
+ # so: if there's a default and it's not None, add it to the config
+ if config_val is None:
+ if param_config.get( 'default', None ) is None:
+ continue
+ config_val = self.parse_parameter_default( trans, controller, param_config )
+
+ config[ param_name ] = config_val
+
+ return config
+
#TODO: I would LOVE to rip modifiers out completely
def parse_parameter_modifiers( self, trans, controller, param_modifiers, query_params ):
"""
@@ -811,11 +861,11 @@
target_modifiers[ modifier_name ] = modifier
else:
#TODO: required attr?
- target_modifiers[ modifier_name ] = self.parse_parameter_default( trans, modifier_config )
+ target_modifiers[ modifier_name ] = self.parse_parameter_default( trans, controller, modifier_config )
return parsed_modifiers
- def parse_parameter_default( self, trans, param_config ):
+ def parse_parameter_default( self, trans, controller, param_config ):
"""
Parse any default values for the given param, defaulting the default
to `None`.
@@ -828,46 +878,8 @@
# otherwise, parse (currently param_config['default'] is a string just like query param and needs to be parsed)
# this saves us the trouble of parsing the default when the config file is read
# (and adding this code to the xml parser)
- return self.parse_parameter( trans, param_config, default )
+ return self.parse_parameter( trans, controller, param_config, default )
- def get_params_from_visualization_param( self, trans, controller, param_config_dict, query_params ):
- #log.debug( 'parse_visualization_params: %s', param_config_dict )
- #log.debug( ' : %s', query_params )
-
- # first, find the visualization in the parameters if any
- visualization = None
- #precondition: assume one visualization
- for param_name, param_config in param_config_dict.items():
- if param_config.get( 'type' ) == 'visualization':
- query_val = query_params.get( param_name )
- if query_val is None:
- continue
-
- #log.debug( 'found visualization param: %s, %s', param_name, query_val )
- visualization = self.parse_parameter( trans, controller, param_config, query_val )
- if visualization:
- break
-
- # if no vis is found, can't get any new params from it: return the original query_params
- if not visualization:
- #log.debug( 'visualization not found' )
- return query_params
- #log.debug( 'found visualization: %s', visualization )
-
- # next, attempt to copy any params from the visualizations config
- visualization_config = visualization.latest_revision.config
- #log.debug( '\t config: %s', visualization_config )
- params_from_visualization = {}
- for param_name, param_config in param_config_dict.items():
- if param_name in visualization_config:
- params_from_visualization[ param_name ] = visualization_config[ param_name ]
- #log.debug( 'params_from_visualization: %s', params_from_visualization )
-
- # layer the query_params over the params from the visualization, returning the combined
- params_from_visualization.update( query_params )
- return params_from_visualization
-
-#TODO: make parse_visualization separate
def parse_parameter( self, trans, controller, expected_param_data, query_param,
recurse=True, param_modifiers=None ):
"""
@@ -892,24 +904,11 @@
parsed_param.append( self._parse_param( trans, expected_param_data, query_param, recurse=False ) )
return parsed_param
- primitive_parsers = {
- 'str' : lambda param: galaxy.util.sanitize_html.sanitize_html( param, 'utf-8' ),
- 'bool' : lambda param: galaxy.util.string_as_bool( param ),
- 'int' : lambda param: int( param ),
- 'float' : lambda param: float( param ),
- #'date' : lambda param: ,
- 'json' : ( lambda param: galaxy.util.json.from_json_string(
- galaxy.util.sanitize_html.sanitize_html( param ) ) ),
- }
- parser = primitive_parsers.get( param_type, None )
- if parser:
+ if param_type in self.primitive_parsers:
#TODO: what about param modifiers on primitives?
- parsed_param = parser( query_param )
+ parsed_param = self.primitive_parsers[ param_type ]( query_param )
- #TODO: constrain_to
- # this gets complicated - for strings - relatively simple but still requires splitting and using in
- # for more complicated cases (ints, json) this gets weird quick
- #TODO:?? remove?
+ #TODO: constrain_to: this gets complicated - remove?
# db models
#TODO: subclass here?
diff -r a11c52513e4472237c9070a06ff11f123af83c06 -r a253d56a0dd6be3816581a0c7ed0ada191a1693b lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -1,9 +1,10 @@
from __future__ import absolute_import
import os
+import copy
from sqlalchemy import desc, or_, and_
-from paste.httpexceptions import HTTPNotFound
+from paste.httpexceptions import HTTPNotFound, HTTPBadRequest
from galaxy import model, web
from galaxy.model.item_attrs import UsesAnnotations, UsesItemRatings
@@ -13,6 +14,9 @@
from galaxy.datatypes.interval import Bed
from galaxy.util.json import from_json_string
from galaxy.util.sanitize_html import sanitize_html
+from galaxy.util import bunch
+from galaxy import util
+from galaxy.visualization import registry
from galaxy.visualization.genomes import decode_dbkey
from galaxy.visualization.data_providers.phyloviz import PhylovizDataProvider
from galaxy.visualization.genomes import GenomeRegion
@@ -22,6 +26,27 @@
import logging
log = logging.getLogger( __name__ )
+# -- Misc.
+class OpenObject( dict ):
+ #TODO: move to util.data_structures
+ """
+ A dict that allows assignment and attribute retrieval using the dot
+ operator.
+
+ If an attribute isn't contained in the dict `None` is returned (no
+ KeyError).
+ JSON-serializable.
+ """
+ def __getitem__( self, key ):
+ if key not in self:
+ return None
+ return super( OpenObject, self ).__getitem__( key )
+
+ def __getattr__( self, key ):
+ return self.__getitem__( key )
+
+
+
#
# -- Grids --
#
@@ -168,9 +193,14 @@
"""
Returns dictionary used to create item link.
"""
- controller = "visualization"
- action = item.type
- return dict( controller=controller, action=action, id=item.id )
+ url_kwargs = dict( controller='visualization', id=item.id )
+ #TODO: hack to build link to saved visualization - need trans in this function instead in order to do
+ #link_data = trans.app.visualizations_registry.get_visualizations( trans, item )
+ if item.type in registry.VisualizationsRegistry.BUILT_IN_VISUALIZATIONS:
+ url_kwargs[ 'action' ] = item.type
+ else:
+ url_kwargs[ 'action' ] = 'saved'
+ return url_kwargs
# Grid definition
title = "Saved Visualizations"
@@ -179,6 +209,7 @@
default_filter = dict( title="All", deleted="False", tags="All", sharing="All" )
columns = [
grids.TextColumn( "Title", key="title", attach_popup=True, link=get_url_args ),
+ #TODO: should use display name when available
grids.TextColumn( "Type", key="type" ),
grids.TextColumn( "Dbkey", key="dbkey" ),
grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
@@ -623,7 +654,6 @@
Save a visualization; if visualization does not have an ID, a new
visualization is created. Returns JSON of visualization.
"""
-
# Get visualization attributes from kwargs or from config.
vis_config = from_json_string( vis_json )
vis_type = type or vis_config[ 'type' ]
@@ -686,10 +716,45 @@
#
# Visualizations.
#
+ @web.expose
+ @web.require_login( "use Galaxy visualizations", use_panels=True )
+ def saved( self, trans, id=None, revision=None, type=None, config=None, title=None, **kwargs ):
+ """
+ """
+ DEFAULT_VISUALIZATION_NAME = 'Unnamed Visualization'
+
+ # post to saved in order to save a visualization
+ #TODO: re-route this one to clear up signature
+ if trans.request.method == 'POST':
+ if type is None or config is None:
+ return HTTPBadRequest( 'A visualization type and config are required to save a visualization' )
+ if isinstance( config, basestring ):
+ config = from_json_string( config )
+ title = title or DEFAULT_VISUALIZATION_NAME
+ #TODO: allow saving to (updating) a specific revision - should be part of UsesVisualization
+ #TODO: would be easier if this returned the visualization directly
+ returned = self.save_visualization( trans, config, type, id, title )
+
+ # redirect to GET to prevent annoying 'Do you want to post again?' dialog on page reload
+ render_url = web.url_for( controller='visualization', action='saved', id=returned.get( 'vis_id' ) )
+ return trans.response.send_redirect( render_url )
+
+ if id is None:
+ return HTTPBadRequest( 'A valid visualization id is required to load a visualization' )
+
+ # render the saved visualization by passing to render, sending latest revision config
+ #TODO: allow loading a specific revision - should be part of UsesVisualization
+ visualization = self.get_visualization( trans, id, check_ownership=True, check_accessible=False )
+ config = copy.copy( visualization.latest_revision.config )
+
+ # re-add title to kwargs for passing to render
+ if title:
+ kwargs[ 'title' ] = title
+ return self.render( trans, visualization.type, visualization, config=config, **kwargs )
@web.expose
@web.require_login( "use Galaxy visualizations", use_panels=True )
- def render( self, trans, visualization_name, embedded=None, **kwargs ):
+ def render( self, trans, visualization_name, visualization=None, config=None, embedded=None, **kwargs ):
"""
Render the appropriate visualization template, parsing the `kwargs`
into appropriate variables and resources (such as ORM models)
@@ -697,6 +762,8 @@
URL: /visualization/show/{visualization_name}
"""
+ config = config or {}
+
# validate name vs. registry
registry = trans.app.visualizations_registry
if not registry:
@@ -708,20 +775,32 @@
returned = None
try:
- # convert query string to resources for template based on registry config
- #NOTE: passing in controller to keep resource lookup within the controller's responsibilities
- # (and not the ResourceParser)
- resources = registry.query_dict_to_resources( trans, self, visualization_name, kwargs )
+ # get the config for passing to the template from the kwargs dict, parsed using the plugin's params setting
+ config_from_kwargs = registry.query_dict_to_config( trans, self, visualization_name, kwargs )
+ config.update( config_from_kwargs )
+ config = OpenObject( **config )
+ # further parse config to resources (models, etc.) used in template based on registry config
+ resources = registry.query_dict_to_resources( trans, self, visualization_name, config )
+
+ # if a saved visualization, pass in the encoded visualization id or None if a new render
+ encoded_visualization_id = None
+ if visualization:
+ encoded_visualization_id = trans.security.encode_id( visualization.id )
+
+ visualization_display_name = plugin.config[ 'name' ]
+ title = visualization.latest_revision.title if visualization else kwargs.get( 'title', None )
# look up template and render
template_path = plugin.config[ 'template' ]
returned = registry.fill_template( trans, plugin, template_path,
- visualization_name=visualization_name, query_args=kwargs,
- embedded=embedded, shared_vars={}, **resources )
- #NOTE: passing *unparsed* kwargs as query_args
- #NOTE: shared_vars is a dictionary for shared data in the template
+ visualization_name=visualization_name, visualization_display_name=visualization_display_name,
+ title=title, saved_visualization=visualization, visualization_id=encoded_visualization_id,
+ embedded=embedded, query=kwargs, vars={}, config=config, **resources )
+ #NOTE: passing *unparsed* kwargs as query
+ #NOTE: vars is a dictionary for shared data in the template
# this feels hacky to me but it's what mako recommends:
# http://docs.makotemplates.org/en/latest/runtime.html
+ #TODO: should vars contain all the passed in arguments? is that even necessary?
#TODO: embedded
except Exception, exception:
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
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a11c52513e44/
Changeset: a11c52513e44
User: dan
Date: 2014-02-07 16:11:28
Summary: merge next-stable
Affected #: 0 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/aea2ff5acd68/
Changeset: aea2ff5acd68
Branch: next-stable
User: dan
Date: 2014-02-07 16:10:27
Summary: Generate tool_runner url using keywords in data_manager/index.mako.
Affected #: 1 file
diff -r aefe5cf99f92eaa3a401f3f7a9edf9dce4027ed1 -r aea2ff5acd6805ad10db0442cc159f7e4e67a541 templates/webapps/galaxy/data_manager/index.mako
--- a/templates/webapps/galaxy/data_manager/index.mako
+++ b/templates/webapps/galaxy/data_manager/index.mako
@@ -19,7 +19,7 @@
<ul>
%for data_manager_id, data_manager in data_managers.data_managers.iteritems():
<li>
- <a href="${ h.url_for( 'tool_runner?tool_id=%s' % ( data_manager.tool.id ) ) }"><strong>${ data_manager.name | h }</strong></a> - ${ data_manager.description | h }
+ <a href="${ h.url_for( controller='tool_runner', action='index', tool_id=data_manager.tool.id ) }"><strong>${ data_manager.name | h }</strong></a> - ${ data_manager.description | h }
</li><p/>
%endfor
https://bitbucket.org/galaxy/galaxy-central/commits/5641ce15708a/
Changeset: 5641ce15708a
User: dan
Date: 2014-02-07 16:10:27
Summary: Generate tool_runner url using keywords in data_manager/index.mako.
Affected #: 1 file
diff -r c162bff2090eb4a986e9059b45109fac172239dd -r 5641ce15708a6af203fcbfa0b99c37df9c18dbf3 templates/webapps/galaxy/data_manager/index.mako
--- a/templates/webapps/galaxy/data_manager/index.mako
+++ b/templates/webapps/galaxy/data_manager/index.mako
@@ -19,7 +19,7 @@
<ul>
%for data_manager_id, data_manager in data_managers.data_managers.iteritems():
<li>
- <a href="${ h.url_for( 'tool_runner?tool_id=%s' % ( data_manager.tool.id ) ) }"><strong>${ data_manager.name | h }</strong></a> - ${ data_manager.description | h }
+ <a href="${ h.url_for( controller='tool_runner', action='index', tool_id=data_manager.tool.id ) }"><strong>${ data_manager.name | h }</strong></a> - ${ data_manager.description | h }
</li><p/>
%endfor
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Add README to static/style to document requirements for building galaxy styles.
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c162bff2090e/
Changeset: c162bff2090e
User: dannon
Date: 2014-02-07 15:43:14
Summary: Add README to static/style to document requirements for building galaxy styles.
Affected #: 1 file
diff -r 5e2a4255cf09e7423d8fc41c99a9386bca9e0851 -r c162bff2090eb4a986e9059b45109fac172239dd static/style/README
--- /dev/null
+++ b/static/style/README
@@ -0,0 +1,26 @@
+GALAXY STYLE BUILDING
+
+Requirements:
+node.js http://nodejs.org
+grunt http://gruntjs.com
+phantomjs http://phantomjs.org
+ *phantomjs can be replaced with other libraries if you know what you're
+ doing (it's used as an engine for sprite building), but it's the easiest to
+ get up and running.
+
+After node, grunt, and phantomjs are all installed (and on your path):
+
+ 1: navigate to the <galaxy>/static/style directory (where this file is)
+ 2: execute 'npm install'
+ 3: execute 'grunt'
+
+The 'npm install' command will install the required modules for building galaxy
+into the node_modules directory here. If phantomjs isn't correctly installed
+and on your path prior to running 'npm install', you'll see this error message:
+
+ Warning: Sorry, no spritesmith engine could be loaded for your machine.
+ Please be sure you have installed canvas or gm. Use --force to continue.
+
+If this happens, you'll need to rerun 'npm install' after 1) ensuring phantomjs
+is on your path and 2) removing the local node_modules directory (rm -rf
+node_modules).
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/aefe5cf99f92/
Changeset: aefe5cf99f92
Branch: next-stable
User: abretaud
Date: 2014-02-07 11:51:41
Summary: Fix crash when recovering jobs of a removed tool
Affected #: 1 file
diff -r deea87095946ea32d28491b44a120bbc94683150 -r aefe5cf99f92eaa3a401f3f7a9edf9dce4027ed1 lib/galaxy/jobs/handler.py
--- a/lib/galaxy/jobs/handler.py
+++ b/lib/galaxy/jobs/handler.py
@@ -107,7 +107,7 @@
if job.tool_id not in self.app.toolbox.tools_by_id:
log.warning( "(%s) Tool '%s' removed from tool config, unable to recover job" % ( job.id, job.tool_id ) )
JobWrapper( job, self ).fail( 'This tool was disabled before the job completed. Please contact your Galaxy administrator.' )
- if job.job_runner_name is not None and job.job_runner_external_id is None:
+ elif job.job_runner_name is not None and job.job_runner_external_id is None:
# This could happen during certain revisions of Galaxy where a runner URL was persisted before the job was dispatched to a runner.
log.debug( "(%s) Job runner assigned but no external ID recorded, adding to the job handler queue" % job.id )
job.job_runner_name = None
https://bitbucket.org/galaxy/galaxy-central/commits/5e2a4255cf09/
Changeset: 5e2a4255cf09
User: natefoo
Date: 2014-02-07 15:27:14
Summary: merge.
Affected #: 0 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: abretaud: Fix crash when recovering jobs of a removed tool
by commits-noreply@bitbucket.org 07 Feb '14
by commits-noreply@bitbucket.org 07 Feb '14
07 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f6f6529b8ca1/
Changeset: f6f6529b8ca1
User: abretaud
Date: 2014-02-07 11:51:41
Summary: Fix crash when recovering jobs of a removed tool
Affected #: 1 file
diff -r 086e594d372cc58a823f061c3a008a60c0c33472 -r f6f6529b8ca14267bdd3c4ab1fcd2343dffc08dd lib/galaxy/jobs/handler.py
--- a/lib/galaxy/jobs/handler.py
+++ b/lib/galaxy/jobs/handler.py
@@ -107,7 +107,7 @@
if job.tool_id not in self.app.toolbox.tools_by_id:
log.warning( "(%s) Tool '%s' removed from tool config, unable to recover job" % ( job.id, job.tool_id ) )
JobWrapper( job, self ).fail( 'This tool was disabled before the job completed. Please contact your Galaxy administrator.' )
- if job.job_runner_name is not None and job.job_runner_external_id is None:
+ elif job.job_runner_name is not None and job.job_runner_external_id is None:
# This could happen during certain revisions of Galaxy where a runner URL was persisted before the job was dispatched to a runner.
log.debug( "(%s) Job runner assigned but no external ID recorded, adding to the job handler queue" % job.id )
job.job_runner_name = None
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