galaxy-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: greg: Back out the changes in 41bb600 that resulted in changes to the way the Tool Shed's package installation framework handled dependencies that are contained in the same repository as tools that require them.
by commits-noreply@bitbucket.org 06 May '14
by commits-noreply@bitbucket.org 06 May '14
06 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9e0362d990f8/
Changeset: 9e0362d990f8
User: greg
Date: 2014-05-06 15:24:36
Summary: Back out the changes in 41bb600 that resulted in changes to the way the Tool Shed's package installation framework handled dependencies that are contained in the same repository as tools that require them.
Affected #: 2 files
diff -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b -r 9e0362d990f88502b77211d2d3f7f5459123f52c lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -289,55 +289,6 @@
raise Exception( message )
return handled_tool_dependencies
-def handle_env_vars_for_set_environment_tool_dependency( app, tool_shed_repository, tool_shed_repository_install_dir ):
- env_var_name = 'PATH'
- install_dir = \
- tool_dependency_util.get_tool_dependency_install_dir( app=app,
- repository_name=tool_shed_repository.name,
- repository_owner=tool_shed_repository.owner,
- repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dependency_type='set_environment',
- tool_dependency_name=env_var_name,
- tool_dependency_version=None )
- env_var_dict = dict( name=env_var_name, action='prepend_to', value=tool_shed_repository_install_dir )
- if not os.path.exists( install_dir ):
- os.makedirs( install_dir )
- status = app.install_model.ToolDependency.installation_status.INSTALLING
- tool_dependency = \
- tool_dependency_util.create_or_update_tool_dependency( app=app,
- tool_shed_repository=tool_shed_repository,
- name=env_var_name,
- version=None,
- type='set_environment',
- status=status,
- set_status=True )
- env_file_builder = EnvFileBuilder( install_dir )
- return_code = env_file_builder.append_line( make_executable=True, **env_var_dict )
- if return_code:
- error_message = 'Error creating env.sh file for tool dependency %s, return_code: %s' % \
- ( str( tool_dependency.name ), str( return_code ) )
- log.debug( error_message )
- status = app.install_model.ToolDependency.installation_status.ERROR
- tool_dependency = \
- tool_dependency_util.set_tool_dependency_attributes( app,
- tool_dependency=tool_dependency,
- status=status,
- error_message=error_message,
- remove_from_disk=False )
- else:
- if tool_dependency.status not in [ app.install_model.ToolDependency.installation_status.ERROR,
- app.install_model.ToolDependency.installation_status.INSTALLED ]:
- status = app.install_model.ToolDependency.installation_status.INSTALLED
- tool_dependency = \
- tool_dependency_util.set_tool_dependency_attributes( app,
- tool_dependency=tool_dependency,
- status=status,
- error_message=None,
- remove_from_disk=False )
- log.debug( 'Environment variable %s set in %s for tool dependency %s.' % \
- ( str( env_var_name ), str( install_dir ), str( tool_dependency.name ) ) )
- return tool_dependency
-
def install_and_build_package_via_fabric( app, tool_shed_repository, tool_dependency, actions_dict ):
sa_session = app.install_model.context
try:
@@ -700,7 +651,6 @@
tool_dependencies = []
env_var_version = elem.get( 'version', '1.0' )
tool_shed_repository_install_dir = fabric_util.get_tool_shed_repository_install_dir( app, tool_shed_repository )
- tool_shed_repository_install_dir_added_to_path = False
for env_var_elem in elem:
# Althoug we're in a loop here, this method will always return only a single ToolDependency or None.
env_var_name = env_var_elem.get( 'name', None )
@@ -771,16 +721,6 @@
status=status,
error_message=error_message,
remove_from_disk=False )
- if tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
- if env_var_dict[ 'name' ] == 'PATH' and \
- env_var_dict[ 'action' ] in [ 'prepend_to', 'set_to', 'append_to' ] and \
- env_var_dict[ 'value' ] == install_environment.tool_shed_repository_install_dir:
- tool_shed_repository_install_dir_added_to_path = True
- tool_dependencies.append( tool_dependency )
- if not tool_shed_repository_install_dir_added_to_path:
- tool_dependency = handle_env_vars_for_set_environment_tool_dependency( app,
- tool_shed_repository,
- tool_shed_repository_install_dir )
tool_dependencies.append( tool_dependency )
return tool_dependencies
diff -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b -r 9e0362d990f88502b77211d2d3f7f5459123f52c lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -23,7 +23,6 @@
from tool_shed.galaxy_install.tool_dependencies import install_util
from tool_shed.galaxy_install.tool_dependencies import td_common_util
import tool_shed.repository_types.util as rt_util
-from xml.etree import ElementTree as XmlET
eggs.require( 'mercurial' )
@@ -922,28 +921,8 @@
invalid_tool_dependencies_dict = {}
valid_repository_dependency_tups = []
invalid_repository_dependency_tups = []
- needs_set_environment_tool_dependency_for_path = False
tools_metadata = metadata_dict.get( 'tools', None )
- if tools_metadata is not None:
- for tools_dict in tools_metadata:
- requirements = tools_dict.get( 'requirements', None )
- if requirements is not None:
- for requirements_dict in requirements:
- if requirements_dict[ 'type' ] == 'set_environment' and requirements_dict[ 'name' ] == 'PATH':
- needs_set_environment_tool_dependency_for_path = True
- break
description = root.get( 'description' )
- if needs_set_environment_tool_dependency_for_path:
- # Add this to the in-memory XML tree that is parsed to determine the database tool dependency records. This will not
- # modify the on-disk tool dependency definitions, but is needed in order for the tool to correctly source the env.sh
- # file that was generated for the PATH variable.
- # <set_environment version="1.0">
- # <environment_variable action="prepend_to" name="PATH">$REPOSITORY_INSTALL_DIR</environment_variable>
- # </set_environment>
- env_var_elem_attributes = dict( name='PATH', action='prepend_to' )
- set_environment_elem = xml_util.create_element( 'set_environment', attributes=dict( version='1.0' ) )
- XmlET.SubElement( set_environment_elem, 'environment_variable', attrib=env_var_elem_attributes )
- root.append( set_environment_elem )
for elem in root:
if elem.tag == 'package':
valid_tool_dependencies_dict, invalid_tool_dependencies_dict, repository_dependency_tup, repository_dependency_is_valid, message = \
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: Merged in jmchilton/galaxy-central-fork-1 (pull request #356)
by commits-noreply@bitbucket.org 06 May '14
by commits-noreply@bitbucket.org 06 May '14
06 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8e6cda4c1b3d/
Changeset: 8e6cda4c1b3d
User: jmchilton
Date: 2014-05-06 15:13:29
Summary: Merged in jmchilton/galaxy-central-fork-1 (pull request #356)
Enhancements for Runtime Discovered (Collected Primary) Datasets
Affected #: 13 files
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -42,6 +42,7 @@
from galaxy.tools.deps import build_dependency_manager
from galaxy.tools.deps.requirements import parse_requirements_from_xml
from galaxy.tools.parameters import check_param, params_from_strings, params_to_strings
+from galaxy.tools.parameters import output_collect
from galaxy.tools.parameters.basic import (BaseURLToolParameter,
DataToolParameter, HiddenToolParameter, LibraryDatasetToolParameter,
SelectToolParameter, ToolParameter, UnvalidatedValue,
@@ -1452,6 +1453,7 @@
output.hidden = string_as_bool( data_elem.get("hidden", "") )
output.tool = self
output.actions = ToolOutputActionGroup( output, data_elem.find( 'actions' ) )
+ output.dataset_collectors = output_collect.dataset_collectors_from_elem( data_elem )
self.outputs[ output.name ] = output
# TODO: Include the tool's name in any parsing warnings.
@@ -2800,94 +2802,7 @@
Find any additional datasets generated by a tool and attach (for
cases where number of outputs is not known in advance).
"""
- new_primary_datasets = {}
- try:
- json_file = open( os.path.join( job_working_directory, jobs.TOOL_PROVIDED_JOB_METADATA_FILE ), 'r' )
- for line in json_file:
- line = json.loads( line )
- if line.get( 'type' ) == 'new_primary_dataset':
- new_primary_datasets[ os.path.split( line.get( 'filename' ) )[-1] ] = line
- except Exception:
- # This should not be considered an error or warning condition, this file is optional
- pass
- # Loop through output file names, looking for generated primary
- # datasets in form of:
- # 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
- primary_datasets = {}
- for name, outdata in output.items():
- filenames = []
- if 'new_file_path' in self.app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(self.app.config.new_file_path, "primary_%i_*" % outdata.id) ) )
- if 'job_working_directory' in self.app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(job_working_directory, "primary_%i_*" % outdata.id) ) )
- for filename in filenames:
- if not name in primary_datasets:
- primary_datasets[name] = {}
- fields = os.path.basename(filename).split("_")
- fields.pop(0)
- parent_id = int(fields.pop(0))
- designation = fields.pop(0)
- visible = fields.pop(0).lower()
- if visible == "visible":
- visible = True
- else:
- visible = False
- ext = fields.pop(0).lower()
- dbkey = outdata.dbkey
- if fields:
- dbkey = fields[ 0 ]
- # Create new primary dataset
- primary_data = self.app.model.HistoryDatasetAssociation( extension=ext,
- designation=designation,
- visible=visible,
- dbkey=dbkey,
- create_dataset=True,
- sa_session=self.sa_session )
- self.app.security_agent.copy_dataset_permissions( outdata.dataset, primary_data.dataset )
- self.sa_session.add( primary_data )
- self.sa_session.flush()
- # Move data from temp location to dataset location
- self.app.object_store.update_from_file(primary_data.dataset, file_name=filename, create=True)
- primary_data.set_size()
- primary_data.name = "%s (%s)" % ( outdata.name, designation )
- primary_data.info = outdata.info
- primary_data.init_meta( copy_from=outdata )
- primary_data.dbkey = dbkey
- # Associate new dataset with job
- job = None
- for assoc in outdata.creating_job_associations:
- job = assoc.job
- break
- if job:
- assoc = self.app.model.JobToOutputDatasetAssociation( '__new_primary_file_%s|%s__' % ( name, designation ), primary_data )
- assoc.job = job
- self.sa_session.add( assoc )
- self.sa_session.flush()
- primary_data.state = outdata.state
- #add tool/metadata provided information
- new_primary_datasets_attributes = new_primary_datasets.get( os.path.split( filename )[-1] )
- if new_primary_datasets_attributes:
- dataset_att_by_name = dict( ext='extension' )
- for att_set in [ 'name', 'info', 'ext', 'dbkey' ]:
- dataset_att_name = dataset_att_by_name.get( att_set, att_set )
- setattr( primary_data, dataset_att_name, new_primary_datasets_attributes.get( att_set, getattr( primary_data, dataset_att_name ) ) )
- primary_data.set_meta()
- primary_data.set_peek()
- self.sa_session.add( primary_data )
- self.sa_session.flush()
- outdata.history.add_dataset( primary_data )
- # Add dataset to return dict
- primary_datasets[name][designation] = primary_data
- # Need to update all associated output hdas, i.e. history was
- # shared with job running
- for dataset in outdata.dataset.history_associations:
- if outdata == dataset:
- continue
- new_data = primary_data.copy()
- dataset.history.add_dataset( new_data )
- self.sa_session.add( new_data )
- self.sa_session.flush()
- return primary_datasets
+ return output_collect.collect_primary_datatasets( self, output, job_working_directory )
def to_dict( self, trans, link_details=False, io_details=False ):
""" Returns dict of tool. """
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/tools/parameters/output_collect.py
--- /dev/null
+++ b/lib/galaxy/tools/parameters/output_collect.py
@@ -0,0 +1,219 @@
+""" Code allowing tools to define extra files associated with an output datset.
+"""
+import os
+import re
+import glob
+import json
+
+
+from galaxy import jobs
+from galaxy import util
+from galaxy.util import odict
+
+DATASET_ID_TOKEN = "DATASET_ID"
+DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P<designation>[^_]+)_(?P<visible>[^_]+)_(?P<ext>[^_]+)(_(?P<dbkey>[^_]+))?"
+
+
+def collect_primary_datatasets( tool, output, job_working_directory ):
+ app = tool.app
+ sa_session = tool.sa_session
+ new_primary_datasets = {}
+ try:
+ json_file = open( os.path.join( job_working_directory, jobs.TOOL_PROVIDED_JOB_METADATA_FILE ), 'r' )
+ for line in json_file:
+ line = json.loads( line )
+ if line.get( 'type' ) == 'new_primary_dataset':
+ new_primary_datasets[ os.path.split( line.get( 'filename' ) )[-1] ] = line
+ except Exception:
+ # This should not be considered an error or warning condition, this file is optional
+ pass
+ # Loop through output file names, looking for generated primary
+ # datasets in form of:
+ # 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
+ primary_datasets = {}
+ for name, outdata in output.items():
+ dataset_collectors = tool.outputs[ name ].dataset_collectors if name in tool.outputs else [ DEFAULT_DATASET_COLLECTOR ]
+ filenames = odict.odict()
+ if 'new_file_path' in app.config.collect_outputs_from:
+ if DEFAULT_DATASET_COLLECTOR in dataset_collectors:
+ # 'new_file_path' collection should be considered deprecated,
+ # only use old-style matching (glob instead of regex and only
+ # using default collector - if enabled).
+ for filename in glob.glob(os.path.join(app.config.new_file_path, "primary_%i_*" % outdata.id) ):
+ filenames[ filename ] = DEFAULT_DATASET_COLLECTOR
+ if 'job_working_directory' in app.config.collect_outputs_from:
+ for extra_file_collector in dataset_collectors:
+ directory = job_working_directory
+ if extra_file_collector.directory:
+ directory = os.path.join( directory, extra_file_collector.directory )
+ if not util.in_directory( directory, job_working_directory ):
+ raise Exception( "Problem with tool configuration, attempting to pull in datasets from outside working directory." )
+ if not os.path.isdir( directory ):
+ continue
+ for filename in os.listdir( directory ):
+ path = os.path.join( directory, filename )
+ if not os.path.isfile( path ):
+ continue
+ if extra_file_collector.match( outdata, filename ):
+ filenames[ path ] = extra_file_collector
+ for filename, extra_file_collector in filenames.iteritems():
+ if not name in primary_datasets:
+ primary_datasets[name] = {}
+ fields_match = extra_file_collector.match( outdata, os.path.basename( filename ) )
+ if not fields_match:
+ # Before I guess pop() would just have thrown an IndexError
+ raise Exception( "Problem parsing metadata fields for file %s" % filename )
+ designation = fields_match.designation
+ visible = fields_match.visible
+ ext = fields_match.ext
+ dbkey = fields_match.dbkey
+ # Create new primary dataset
+ primary_data = app.model.HistoryDatasetAssociation( extension=ext,
+ designation=designation,
+ visible=visible,
+ dbkey=dbkey,
+ create_dataset=True,
+ sa_session=sa_session )
+ app.security_agent.copy_dataset_permissions( outdata.dataset, primary_data.dataset )
+ sa_session.add( primary_data )
+ sa_session.flush()
+ # Move data from temp location to dataset location
+ app.object_store.update_from_file(primary_data.dataset, file_name=filename, create=True)
+ primary_data.set_size()
+ # If match specified a name use otherwise generate one from
+ # designation.
+ primary_data.name = fields_match.name or "%s (%s)" % ( outdata.name, designation )
+ primary_data.info = outdata.info
+ primary_data.init_meta( copy_from=outdata )
+ primary_data.dbkey = dbkey
+ # Associate new dataset with job
+ job = None
+ for assoc in outdata.creating_job_associations:
+ job = assoc.job
+ break
+ if job:
+ assoc = app.model.JobToOutputDatasetAssociation( '__new_primary_file_%s|%s__' % ( name, designation ), primary_data )
+ assoc.job = job
+ sa_session.add( assoc )
+ sa_session.flush()
+ primary_data.state = outdata.state
+ #add tool/metadata provided information
+ new_primary_datasets_attributes = new_primary_datasets.get( os.path.split( filename )[-1] )
+ if new_primary_datasets_attributes:
+ dataset_att_by_name = dict( ext='extension' )
+ for att_set in [ 'name', 'info', 'ext', 'dbkey' ]:
+ dataset_att_name = dataset_att_by_name.get( att_set, att_set )
+ setattr( primary_data, dataset_att_name, new_primary_datasets_attributes.get( att_set, getattr( primary_data, dataset_att_name ) ) )
+ primary_data.set_meta()
+ primary_data.set_peek()
+ sa_session.add( primary_data )
+ sa_session.flush()
+ outdata.history.add_dataset( primary_data )
+ # Add dataset to return dict
+ primary_datasets[name][designation] = primary_data
+ # Need to update all associated output hdas, i.e. history was
+ # shared with job running
+ for dataset in outdata.dataset.history_associations:
+ if outdata == dataset:
+ continue
+ new_data = primary_data.copy()
+ dataset.history.add_dataset( new_data )
+ sa_session.add( new_data )
+ sa_session.flush()
+ return primary_datasets
+
+
+# XML can describe custom patterns, but these literals describe named
+# patterns that will be replaced.
+NAMED_PATTERNS = {
+ "__default__": DEFAULT_EXTRA_FILENAME_PATTERN,
+ "__name__": r"(?P<name>.*)",
+ "__designation__": r"(?P<designation>.*)",
+ "__name_and_ext__": r"(?P<name>.*)\.(?P<ext>[^\.]+)?",
+ "__designation_and_ext__": r"(?P<designation>.*)\.(?P<ext>[^\._]+)?",
+}
+
+
+def dataset_collectors_from_elem( elem ):
+ primary_dataset_elems = elem.findall( "discover_datasets" )
+ if not primary_dataset_elems:
+ return [ DEFAULT_DATASET_COLLECTOR ]
+ else:
+ return map( lambda elem: DatasetCollector( **elem.attrib ), primary_dataset_elems )
+
+
+class DatasetCollector( object ):
+
+ def __init__( self, **kwargs ):
+ pattern = kwargs.get( "pattern", "__default__" )
+ if pattern in NAMED_PATTERNS:
+ pattern = NAMED_PATTERNS.get( pattern )
+ self.pattern = pattern
+ self.default_dbkey = kwargs.get( "dbkey", None )
+ self.default_ext = kwargs.get( "ext", None )
+ self.default_visible = util.asbool( kwargs.get( "visible", None ) )
+ self.directory = kwargs.get( "directory", None )
+
+ def pattern_for_dataset( self, dataset_instance=None ):
+ token_replacement = r'\d+'
+ if dataset_instance:
+ token_replacement = str( dataset_instance.id )
+ return self.pattern.replace( DATASET_ID_TOKEN, token_replacement )
+
+ def match( self, dataset_instance, filename ):
+ re_match = re.match( self.pattern_for_dataset( dataset_instance ), filename )
+ match_object = None
+ if re_match:
+ match_object = CollectedDatasetMatch( re_match, self )
+ return match_object
+
+
+class CollectedDatasetMatch( object ):
+
+ def __init__( self, re_match, collector ):
+ self.re_match = re_match
+ self.collector = collector
+
+ @property
+ def designation( self ):
+ re_match = self.re_match
+ if "designation" in re_match.groupdict():
+ return re_match.group( "designation" )
+ elif "name" in re_match.groupdict():
+ return re_match.group( "name" )
+ else:
+ return None
+
+ @property
+ def name( self ):
+ """ Return name or None if not defined by the discovery pattern.
+ """
+ re_match = self.re_match
+ name = None
+ if "name" in re_match.groupdict():
+ name = re_match.group( "name" )
+ return name
+
+ @property
+ def dbkey( self ):
+ try:
+ return self.re_match.group( "dbkey" )
+ except IndexError:
+ return self.collector.default_dbkey
+
+ @property
+ def ext( self ):
+ try:
+ return self.re_match.group( "ext" )
+ except IndexError:
+ return self.collector.default_ext
+
+ @property
+ def visible( self ):
+ try:
+ return self.re_match.group( "visible" ).lower() == "visible"
+ except IndexError:
+ return self.collector.default_visible
+
+
+DEFAULT_DATASET_COLLECTOR = DatasetCollector()
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -297,6 +297,19 @@
if name is None:
raise Exception( "Test output does not have a 'name'" )
+ file, attributes = __parse_test_attributes( output_elem, attrib )
+ primary_datasets = {}
+ for primary_elem in ( output_elem.findall( "discovered_dataset" ) or [] ):
+ primary_attrib = dict( primary_elem.attrib )
+ designation = primary_attrib.pop( 'designation', None )
+ if designation is None:
+ raise Exception( "Test primary dataset does not have a 'designation'" )
+ primary_datasets[ designation ] = __parse_test_attributes( primary_elem, primary_attrib )
+ attributes[ "primary_datasets" ] = primary_datasets
+ return name, file, attributes
+
+
+def __parse_test_attributes( output_elem, attrib ):
assert_list = __parse_assert_list( output_elem )
file = attrib.pop( 'file', None )
# File no longer required if an list of assertions was present.
@@ -321,7 +334,7 @@
attributes['assert_list'] = assert_list
attributes['extra_files'] = extra_files
attributes['metadata'] = metadata
- return name, file, attributes
+ return file, attributes
def __parse_assert_list( output_elem ):
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -13,6 +13,7 @@
from galaxy.web.base.controller import UsesLibraryMixinItems
from galaxy import exceptions
from galaxy import util
+from galaxy import model
import logging
log = logging.getLogger( __name__ )
@@ -91,10 +92,62 @@
:rtype: dictionary
:returns: dictionary containing full description of job data
"""
+ job = self.__get_job( trans, id )
+ return self.encode_all_ids( trans, job.to_dict( 'element' ), True )
+
+ @expose_api
+ def inputs( self, trans, id, **kwd ):
+ """
+ show( trans, id )
+ * GET /api/jobs/{job_id}/inputs
+ returns input datasets created by job
+
+ :type id: string
+ :param id: Encoded job id
+
+ :rtype: dictionary
+ :returns: dictionary containing input dataset associations
+ """
+ job = self.__get_job( trans, id )
+ return self.__dictify_associations( trans, job.input_datasets, job.input_library_datasets )
+
+ @expose_api
+ def outputs( self, trans, id, **kwd ):
+ """
+ show( trans, id )
+ * GET /api/jobs/{job_id}/outputs
+ returns output datasets created by job
+
+ :type id: string
+ :param id: Encoded job id
+
+ :rtype: dictionary
+ :returns: dictionary containing output dataset associations
+ """
+ job = self.__get_job( trans, id )
+ return self.__dictify_associations( trans, job.output_datasets, job.output_library_datasets )
+
+ def __dictify_associations( self, trans, *association_lists ):
+ rval = []
+ for association_list in association_lists:
+ rval.extend( map( lambda a: self.__dictify_association( trans, a ), association_list ) )
+ return rval
+
+ def __dictify_association( self, trans, job_dataset_association ):
+ dataset_dict = None
+ dataset = job_dataset_association.dataset
+ if dataset:
+ if isinstance( dataset, model.HistoryDatasetAssociation ):
+ dataset_dict = dict( src="hda", id=trans.security.encode_id( dataset.id ) )
+ else:
+ dataset_dict = dict( src="ldda", id=trans.security.encode_id( dataset.id ) )
+ return dict( name=job_dataset_association.name, dataset=dataset_dict )
+
+ def __get_job( self, trans, id ):
try:
- decoded_job_id = trans.security.decode_id(id)
- except:
- raise exceptions.ObjectAttributeInvalidException()
+ decoded_job_id = trans.security.decode_id( id )
+ except Exception:
+ raise exceptions.MalformedId()
query = trans.sa_session.query( trans.app.model.Job ).filter(
trans.app.model.Job.user == trans.user,
trans.app.model.Job.id == decoded_job_id
@@ -102,7 +155,7 @@
job = query.first()
if job is None:
raise exceptions.ObjectNotFound()
- return self.encode_all_ids( trans, job.to_dict( 'element' ), True )
+ return job
@expose_api
def create( self, trans, payload, **kwd ):
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/webapps/galaxy/api/provenance.py
--- a/lib/galaxy/webapps/galaxy/api/provenance.py
+++ b/lib/galaxy/webapps/galaxy/api/provenance.py
@@ -46,6 +46,7 @@
return {
"id": trans.security.encode_id(item.id),
"uuid": ( lambda uuid: str( uuid ) if uuid else None )( item.dataset.uuid),
+ "job_id": trans.security.encode_id( job.id ),
"tool_id": job.tool_id,
"parameters": self._get_job_record(trans, job, follow),
"stderr": job.stderr,
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -281,6 +281,8 @@
'jobs',
path_prefix='/api' )
webapp.mapper.connect( 'job_search', '/api/jobs/search', controller='jobs', action='search', conditions=dict( method=['POST'] ) )
+ webapp.mapper.connect( 'job_inputs', '/api/jobs/{id}/inputs', controller='jobs', action='inputs', conditions=dict( method=['GET'] ) )
+ webapp.mapper.connect( 'job_outputs', '/api/jobs/{id}/outputs', controller='jobs', action='outputs', conditions=dict( method=['GET'] ) )
# Job files controllers. Only for consumption by remote job runners.
webapp.mapper.resource( 'file',
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/base/interactor.py
--- a/test/base/interactor.py
+++ b/test/base/interactor.py
@@ -44,16 +44,44 @@
self.api_key = self.__get_user_key( twill_test_case.user_api_key, twill_test_case.master_api_key, test_user=test_user )
self.uploads = {}
- def verify_output( self, history_id, output_data, outfile, attributes, shed_tool_id, maxseconds ):
+ def verify_output( self, history_id, output_data, output_testdef, shed_tool_id, maxseconds ):
+ outfile = output_testdef.outfile
+ attributes = output_testdef.attributes
+ name = output_testdef.name
self.wait_for_history( history_id, maxseconds )
hid = self.__output_id( output_data )
fetcher = self.__dataset_fetcher( history_id )
## TODO: Twill version verifys dataset is 'ok' in here.
self.twill_test_case.verify_hid( outfile, hda_id=hid, attributes=attributes, dataset_fetcher=fetcher, shed_tool_id=shed_tool_id )
+
+ primary_datasets = attributes.get( 'primary_datasets', {} )
+ if primary_datasets:
+ job_id = self._dataset_provenance( history_id, hid )[ "job_id" ]
+ outputs = self._get( "jobs/%s/outputs" % ( job_id ) ).json()
+
+ for designation, ( primary_outfile, primary_attributes ) in primary_datasets.iteritems():
+ primary_output = None
+ for output in outputs:
+ if output[ "name" ] == '__new_primary_file_%s|%s__' % ( name, designation ):
+ primary_output = output
+ break
+
+ if not primary_output:
+ msg_template = "Failed to find primary dataset with designation [%s] for output with name [%s]"
+ msg_args = ( designation, name )
+ raise Exception( msg_template % msg_args )
+
+ primary_hda_id = primary_output[ "dataset" ][ "id" ]
+ self.twill_test_case.verify_hid( primary_outfile, hda_id=primary_hda_id, attributes=primary_attributes, dataset_fetcher=fetcher, shed_tool_id=shed_tool_id )
+ self._verify_metadata( history_id, primary_hda_id, primary_attributes )
+
+ self._verify_metadata( history_id, hid, attributes )
+
+ def _verify_metadata( self, history_id, hid, attributes ):
metadata = attributes.get( 'metadata', {} ).copy()
for key, value in metadata.copy().iteritems():
new_key = "metadata_%s" % key
- metadata[ new_key ] = metadata[ key ]
+ metadata[ new_key ] = metadata[ key ]
del metadata[ key ]
expected_file_type = attributes.get( 'ftype', None )
if expected_file_type:
@@ -319,7 +347,10 @@
def __init__( self, twill_test_case ):
self.twill_test_case = twill_test_case
- def verify_output( self, history, output_data, outfile, attributes, shed_tool_id, maxseconds ):
+ def verify_output( self, history, output_data, output_testdef, shed_tool_id, maxseconds ):
+ outfile = output_testdef.outfile
+ attributes = output_testdef.attributes
+
hid = output_data.get( 'hid' )
self.twill_test_case.verify_dataset_correctness( outfile, hid=hid, attributes=attributes, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -3,6 +3,7 @@
from base.twilltestcase import TwillTestCase
from base.interactor import build_interactor, stage_data_in_history
from galaxy.tools import DataManagerTool
+from galaxy.util import bunch
import logging
log = logging.getLogger( __name__ )
@@ -52,6 +53,7 @@
for output_index, output_tuple in enumerate(testdef.outputs):
# Get the correct hid
name, outfile, attributes = output_tuple
+ output_testdef = bunch.Bunch( name=name, outfile=outfile, attributes=attributes )
try:
output_data = data_list[ name ]
except (TypeError, KeyError):
@@ -64,7 +66,7 @@
output_data = data_list[ len(data_list) - len(testdef.outputs) + output_index ]
self.assertTrue( output_data is not None )
try:
- galaxy_interactor.verify_output( history, output_data, outfile, attributes=attributes, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
+ galaxy_interactor.verify_output( history, output_data, output_testdef=output_testdef, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
except Exception:
for stream in ['stdout', 'stderr']:
stream_output = galaxy_interactor.get_job_stream( history, output_data, stream=stream )
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/tools/multi_output.xml
--- a/test/functional/tools/multi_output.xml
+++ b/test/functional/tools/multi_output.xml
@@ -1,7 +1,7 @@
<tool id="multi_output" name="Multi_Output" description="multi_output" force_history_refresh="True" version="0.1.0"><command>
echo "Hello" > $report;
- echo "World" > '${__new_file_path__}/primary_${report.id}_moo_visible_?'
+ echo "World Contents" > '${__new_file_path__}/primary_${report.id}_world_visible_?'
</command><inputs><param name="input" type="integer" value="7" />
@@ -16,6 +16,11 @@
<assert_contents><has_line line="Hello" /></assert_contents>
+ <discovered_dataset designation="world">
+ <assert_contents>
+ <has_line line="World Contents" />
+ </assert_contents>
+ </discovered_dataset></output></test></tests>
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/tools/multi_output_configured.xml
--- /dev/null
+++ b/test/functional/tools/multi_output_configured.xml
@@ -0,0 +1,43 @@
+<tool id="multi_output_configured" name="Multi_Output_Configured" description="multi_output_configured" force_history_refresh="True" version="0.1.0">
+ <command>
+ echo "Hello" > $report;
+ mkdir subdir1;
+ echo "This" > subdir1/this.txt;
+ echo "That" > subdir1/that.txt;
+ mkdir subdir2;
+ echo "1" > subdir2/CUSTOM_1.txt;
+ echo "2" > subdir2/CUSTOM_2.tabular;
+ echo "3" > subdir2/CUSTOM_3.txt;
+ </command>
+ <inputs>
+ <param name="input" type="integer" value="7" />
+ </inputs>
+ <outputs>
+ <data format="txt" name="report">
+ <discover_datasets pattern="__designation_and_ext__" directory="subdir1" />
+ <discover_datasets pattern="CUSTOM_(?P<designation>.+)\.(?P<ext>.+)" directory="subdir2" />
+ </data>
+ </outputs>
+ <tests>
+ <test>
+ <param name="input" value="7" />
+ <output name="report">
+ <assert_contents>
+ <has_line line="Hello" />
+ </assert_contents>
+ <discovered_dataset designation="this" ftype="txt">
+ <assert_contents><has_line line="This" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="that" ftype="txt">
+ <assert_contents><has_line line="That" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="1" ftype="txt">
+ <assert_contents><has_line line="1" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="2" ftype="tabular">
+ <assert_contents><has_line line="2" /></assert_contents>
+ </discovered_dataset>
+ </output>
+ </test>
+ </tests>
+</tool>
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -8,6 +8,7 @@
<tool file="multi_page.xml"/><tool file="multi_select.xml" /><tool file="multi_output.xml" />
+ <tool file="multi_output_configured.xml" /><tool file="composite_output.xml" /><tool file="metadata.xml" /><tool file="output_order.xml" />
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/workflow.py
--- a/test/functional/workflow.py
+++ b/test/functional/workflow.py
@@ -4,6 +4,7 @@
from base.interactor import GalaxyInteractorApi, stage_data_in_history
from galaxy.util import parse_xml
+from galaxy.util import bunch
from galaxy.tools.test import parse_param_elem, require_file, test_data_iter, parse_output_elems
from json import load, dumps
@@ -66,10 +67,11 @@
for expected_output_def in workflow_test.outputs:
# Get the correct hid
name, outfile, attributes = expected_output_def
+ output_testdef = bunch.Bunch( name=name, outfile=outfile, attributes=attributes )
output_data = outputs[ int( name ) ]
try:
- galaxy_interactor.verify_output( test_history, output_data, outfile, attributes=attributes, shed_tool_id=None, maxseconds=maxseconds )
+ galaxy_interactor.verify_output( test_history, output_data, output_testdef=output_testdef, shed_tool_id=None, maxseconds=maxseconds )
except Exception:
for stream in ['stdout', 'stderr']:
stream_output = galaxy_interactor.get_job_stream( test_history, output_data, stream=stream )
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/unit/tools/test_collect_primary_datasets.py
--- a/test/unit/tools/test_collect_primary_datasets.py
+++ b/test/unit/tools/test_collect_primary_datasets.py
@@ -5,6 +5,8 @@
import tools_support
from galaxy import model
+from galaxy import util
+from galaxy.tools.parameters import output_collect
DEFAULT_TOOL_OUTPUT = "out1"
DEFAULT_EXTRA_NAME = "test1"
@@ -114,6 +116,75 @@
extra_job_assoc = filter( lambda job_assoc: job_assoc.name.startswith( "__" ), self.job.output_datasets )[ 0 ]
assert extra_job_assoc.name == "__new_primary_file_out1|test1__"
+ def test_pattern_override_designation( self ):
+ self._replace_output_collectors( '''<output><discover_datasets pattern="__designation__" directory="subdir" ext="txt" /></output>''' )
+ self._setup_extra_file( subdir="subdir", filename="foo.txt" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 1
+ created_hda = primary_outputs.values()[ 0 ]
+ assert "foo.txt" in created_hda.name
+ assert created_hda.ext == "txt"
+
+ def test_name_and_ext_pattern( self ):
+ self._replace_output_collectors( '''<output><discover_datasets pattern="__name_and_ext__" directory="subdir" /></output>''' )
+ self._setup_extra_file( subdir="subdir", filename="foo1.txt" )
+ self._setup_extra_file( subdir="subdir", filename="foo2.tabular" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 2
+ assert primary_outputs[ "foo1" ].ext == "txt"
+ assert primary_outputs[ "foo2" ].ext == "tabular"
+
+ def test_custom_pattern( self ):
+ # Hypothetical oral metagenomic classifier that populates a directory
+ # of files based on name and genome. Use custom regex pattern to grab
+ # and classify these files.
+ self._replace_output_collectors( '''<output><discover_datasets pattern="(?P<designation>.*)__(?P<dbkey>.*).fasta" directory="genome_breakdown" ext="fasta" /></output>''' )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp1__hg19.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp2__lactLact.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp3__hg19.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp4__lactPlan.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp5__fusoNucl.fasta" )
+
+ # Put a file in directory we don't care about, just to make sure
+ # it doesn't get picked up by pattern.
+ self._setup_extra_file( subdir="genome_breakdown", filename="overview.txt" )
+
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 5
+ genomes = dict( samp1="hg19", samp2="lactLact", samp3="hg19", samp4="lactPlan", samp5="fusoNucl" )
+ for key, hda in primary_outputs.iteritems():
+ assert hda.dbkey == genomes[ key ]
+
+ def test_name_versus_designation( self ):
+ """ This test demonstrates the difference between name and desgination
+ in grouping patterns and named patterns such as __designation__,
+ __name__, __designation_and_ext__, and __name_and_ext__.
+ """
+ self._replace_output_collectors( '''<output>
+ <discover_datasets pattern="__name_and_ext__" directory="subdir_for_name_discovery" />
+ <discover_datasets pattern="__designation_and_ext__" directory="subdir_for_designation_discovery" />
+ </output>''')
+ self._setup_extra_file( subdir="subdir_for_name_discovery", filename="example1.txt" )
+ self._setup_extra_file( subdir="subdir_for_designation_discovery", filename="example2.txt" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ name_output = primary_outputs[ "example1" ]
+ designation_output = primary_outputs[ "example2" ]
+ # While name is also used for designation, designation is not the name -
+ # it is used in the calculation of the name however...
+ assert name_output.name == "example1"
+ assert designation_output.name == "%s (%s)" % ( self.hda.name, "example2" )
+
+ def test_cannot_read_files_outside_job_directory( self ):
+ self._replace_output_collectors( '''<output>
+ <discover_datasets pattern="__name_and_ext__" directory="../../secrets" />
+ </output>''')
+ exception_thrown = False
+ try:
+ self._collect( )
+ except Exception:
+ exception_thrown = True
+ assert exception_thrown
+
def _collect_default_extra( self, **kwargs ):
return self._collect( **kwargs )[ DEFAULT_TOOL_OUTPUT ][ DEFAULT_EXTRA_NAME ]
@@ -122,6 +193,12 @@
job_working_directory = self.test_directory
return self.tool.collect_primary_datasets( self.outputs, job_working_directory )
+ def _replace_output_collectors( self, xml_str ):
+ # Rewrite tool as if it had been created with output containing
+ # supplied dataset_collector elem.
+ elem = util.parse_xml_string( xml_str )
+ self.tool.outputs[ DEFAULT_TOOL_OUTPUT ].dataset_collectors = output_collect.dataset_collectors_from_elem( elem )
+
def _append_job_json( self, object, output_path=None, line_type="new_primary_dataset" ):
object[ "type" ] = line_type
if output_path:
@@ -133,7 +210,8 @@
def _setup_extra_file( self, **kwargs ):
path = kwargs.get( "path", None )
- if not path:
+ filename = kwargs.get( "filename", None )
+ if not path and not filename:
name = kwargs.get( "name", DEFAULT_EXTRA_NAME )
visible = kwargs.get( "visible", "visible" )
ext = kwargs.get( "ext", "data" )
@@ -142,6 +220,13 @@
path = os.path.join( directory, "primary_%s_%s_%s_%s" % template_args )
if "dbkey" in kwargs:
path = "%s_%s" % ( path, kwargs[ "dbkey" ] )
+ if not path:
+ assert filename
+ subdir = kwargs.get( "subdir", "." )
+ path = os.path.join( self.test_directory, subdir, filename )
+ directory = os.path.dirname( path )
+ if not os.path.exists( directory ):
+ os.makedirs( directory )
contents = kwargs.get( "contents", "test contents" )
open( path, "w" ).write( contents )
return path
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/92c23f534d2f/
Changeset: 92c23f534d2f
User: jmchilton
Date: 2014-03-29 23:11:17
Summary: Include job id in dataset provenance API.
This allows linking this information with information produced by the jobs API.
Affected #: 1 file
diff -r f83f4d9965283e8dc8640698262da52080081496 -r 92c23f534d2ff322476e988c998d14672d558e31 lib/galaxy/webapps/galaxy/api/provenance.py
--- a/lib/galaxy/webapps/galaxy/api/provenance.py
+++ b/lib/galaxy/webapps/galaxy/api/provenance.py
@@ -46,6 +46,7 @@
return {
"id": trans.security.encode_id(item.id),
"uuid": ( lambda uuid: str( uuid ) if uuid else None )( item.dataset.uuid),
+ "job_id": trans.security.encode_id( job.id ),
"tool_id": job.tool_id,
"parameters": self._get_job_record(trans, job, follow),
"stderr": job.stderr,
https://bitbucket.org/galaxy/galaxy-central/commits/839a099d99a3/
Changeset: 839a099d99a3
User: jmchilton
Date: 2014-03-29 23:11:17
Summary: Allow fetching input/output dataset association information through jobs API.
This will allow tool test framework to discover runtime discovered datastes in subsequent changesets.
Affected #: 2 files
diff -r 92c23f534d2ff322476e988c998d14672d558e31 -r 839a099d99a3d1f35c35c76740087655eacfe46f lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -13,6 +13,7 @@
from galaxy.web.base.controller import UsesLibraryMixinItems
from galaxy import exceptions
from galaxy import util
+from galaxy import model
import logging
log = logging.getLogger( __name__ )
@@ -91,10 +92,62 @@
:rtype: dictionary
:returns: dictionary containing full description of job data
"""
+ job = self.__get_job( trans, id )
+ return self.encode_all_ids( trans, job.to_dict( 'element' ), True )
+
+ @expose_api
+ def inputs( self, trans, id, **kwd ):
+ """
+ show( trans, id )
+ * GET /api/jobs/{job_id}/inputs
+ returns input datasets created by job
+
+ :type id: string
+ :param id: Encoded job id
+
+ :rtype: dictionary
+ :returns: dictionary containing input dataset associations
+ """
+ job = self.__get_job( trans, id )
+ return self.__dictify_associations( trans, job.input_datasets, job.input_library_datasets )
+
+ @expose_api
+ def outputs( self, trans, id, **kwd ):
+ """
+ show( trans, id )
+ * GET /api/jobs/{job_id}/outputs
+ returns output datasets created by job
+
+ :type id: string
+ :param id: Encoded job id
+
+ :rtype: dictionary
+ :returns: dictionary containing output dataset associations
+ """
+ job = self.__get_job( trans, id )
+ return self.__dictify_associations( trans, job.output_datasets, job.output_library_datasets )
+
+ def __dictify_associations( self, trans, *association_lists ):
+ rval = []
+ for association_list in association_lists:
+ rval.extend( map( lambda a: self.__dictify_association( trans, a ), association_list ) )
+ return rval
+
+ def __dictify_association( self, trans, job_dataset_association ):
+ dataset_dict = None
+ dataset = job_dataset_association.dataset
+ if dataset:
+ if isinstance( dataset, model.HistoryDatasetAssociation ):
+ dataset_dict = dict( src="hda", id=trans.security.encode_id( dataset.id ) )
+ else:
+ dataset_dict = dict( src="ldda", id=trans.security.encode_id( dataset.id ) )
+ return dict( name=job_dataset_association.name, dataset=dataset_dict )
+
+ def __get_job( self, trans, id ):
try:
- decoded_job_id = trans.security.decode_id(id)
- except:
- raise exceptions.ObjectAttributeInvalidException()
+ decoded_job_id = trans.security.decode_id( id )
+ except Exception:
+ raise exceptions.MalformedId()
query = trans.sa_session.query( trans.app.model.Job ).filter(
trans.app.model.Job.user == trans.user,
trans.app.model.Job.id == decoded_job_id
@@ -102,7 +155,7 @@
job = query.first()
if job is None:
raise exceptions.ObjectNotFound()
- return self.encode_all_ids( trans, job.to_dict( 'element' ), True )
+ return job
@expose_api
def create( self, trans, payload, **kwd ):
diff -r 92c23f534d2ff322476e988c998d14672d558e31 -r 839a099d99a3d1f35c35c76740087655eacfe46f lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -261,6 +261,8 @@
'jobs',
path_prefix='/api' )
webapp.mapper.connect( 'job_search', '/api/jobs/search', controller='jobs', action='search', conditions=dict( method=['POST'] ) )
+ webapp.mapper.connect( 'job_inputs', '/api/jobs/{id}/inputs', controller='jobs', action='inputs', conditions=dict( method=['GET'] ) )
+ webapp.mapper.connect( 'job_outputs', '/api/jobs/{id}/outputs', controller='jobs', action='outputs', conditions=dict( method=['GET'] ) )
# Job files controllers. Only for consumption by remote job runners.
webapp.mapper.resource( 'file',
https://bitbucket.org/galaxy/galaxy-central/commits/0ce5e9eb984b/
Changeset: 0ce5e9eb984b
User: jmchilton
Date: 2014-03-29 23:11:17
Summary: Allow tools to test runtime discovered datasets.
Affected #: 5 files
diff -r 839a099d99a3d1f35c35c76740087655eacfe46f -r 0ce5e9eb984bc70f1f1c338a3f1d21ed9d6ddee4 lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -297,6 +297,19 @@
if name is None:
raise Exception( "Test output does not have a 'name'" )
+ file, attributes = __parse_test_attributes( output_elem, attrib )
+ primary_datasets = {}
+ for primary_elem in ( output_elem.findall( "discovered_dataset" ) or [] ):
+ primary_attrib = dict( primary_elem.attrib )
+ designation = primary_attrib.pop( 'designation', None )
+ if designation is None:
+ raise Exception( "Test primary dataset does not have a 'designation'" )
+ primary_datasets[ designation ] = __parse_test_attributes( primary_elem, primary_attrib )
+ attributes[ "primary_datasets" ] = primary_datasets
+ return name, file, attributes
+
+
+def __parse_test_attributes( output_elem, attrib ):
assert_list = __parse_assert_list( output_elem )
file = attrib.pop( 'file', None )
# File no longer required if an list of assertions was present.
@@ -321,7 +334,7 @@
attributes['assert_list'] = assert_list
attributes['extra_files'] = extra_files
attributes['metadata'] = metadata
- return name, file, attributes
+ return file, attributes
def __parse_assert_list( output_elem ):
diff -r 839a099d99a3d1f35c35c76740087655eacfe46f -r 0ce5e9eb984bc70f1f1c338a3f1d21ed9d6ddee4 test/base/interactor.py
--- a/test/base/interactor.py
+++ b/test/base/interactor.py
@@ -41,16 +41,44 @@
self.api_key = self.__get_user_key( twill_test_case.user_api_key, twill_test_case.master_api_key, test_user=test_user )
self.uploads = {}
- def verify_output( self, history_id, output_data, outfile, attributes, shed_tool_id, maxseconds ):
+ def verify_output( self, history_id, output_data, output_testdef, shed_tool_id, maxseconds ):
+ outfile = output_testdef.outfile
+ attributes = output_testdef.attributes
+ name = output_testdef.name
self.wait_for_history( history_id, maxseconds )
hid = self.__output_id( output_data )
fetcher = self.__dataset_fetcher( history_id )
## TODO: Twill version verifys dataset is 'ok' in here.
self.twill_test_case.verify_hid( outfile, hda_id=hid, attributes=attributes, dataset_fetcher=fetcher, shed_tool_id=shed_tool_id )
+
+ primary_datasets = attributes.get( 'primary_datasets', {} )
+ if primary_datasets:
+ job_id = self._dataset_provenance( history_id, hid )[ "job_id" ]
+ outputs = self._get( "jobs/%s/outputs" % ( job_id ) ).json()
+
+ for designation, ( primary_outfile, primary_attributes ) in primary_datasets.iteritems():
+ primary_output = None
+ for output in outputs:
+ if output[ "name" ] == '__new_primary_file_%s|%s__' % ( name, designation ):
+ primary_output = output
+ break
+
+ if not primary_output:
+ msg_template = "Failed to find primary dataset with designation [%s] for output with name [%s]"
+ msg_args = ( designation, name )
+ raise Exception( msg_template % msg_args )
+
+ primary_hda_id = primary_output[ "dataset" ][ "id" ]
+ self.twill_test_case.verify_hid( primary_outfile, hda_id=primary_hda_id, attributes=primary_attributes, dataset_fetcher=fetcher, shed_tool_id=shed_tool_id )
+ self._verify_metadata( history_id, primary_hda_id, primary_attributes )
+
+ self._verify_metadata( history_id, hid, attributes )
+
+ def _verify_metadata( self, history_id, hid, attributes ):
metadata = attributes.get( 'metadata', {} ).copy()
for key, value in metadata.copy().iteritems():
new_key = "metadata_%s" % key
- metadata[ new_key ] = metadata[ key ]
+ metadata[ new_key ] = metadata[ key ]
del metadata[ key ]
expected_file_type = attributes.get( 'ftype', None )
if expected_file_type:
@@ -316,7 +344,10 @@
def __init__( self, twill_test_case ):
self.twill_test_case = twill_test_case
- def verify_output( self, history, output_data, outfile, attributes, shed_tool_id, maxseconds ):
+ def verify_output( self, history, output_data, output_testdef, shed_tool_id, maxseconds ):
+ outfile = output_testdef.outfile
+ attributes = output_testdef.attributes
+
hid = output_data.get( 'hid' )
self.twill_test_case.verify_dataset_correctness( outfile, hid=hid, attributes=attributes, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
diff -r 839a099d99a3d1f35c35c76740087655eacfe46f -r 0ce5e9eb984bc70f1f1c338a3f1d21ed9d6ddee4 test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -3,6 +3,7 @@
from base.twilltestcase import TwillTestCase
from base.interactor import build_interactor, stage_data_in_history
from galaxy.tools import DataManagerTool
+from galaxy.util import bunch
import logging
log = logging.getLogger( __name__ )
@@ -52,6 +53,7 @@
for output_index, output_tuple in enumerate(testdef.outputs):
# Get the correct hid
name, outfile, attributes = output_tuple
+ output_testdef = bunch.Bunch( name=name, outfile=outfile, attributes=attributes )
try:
output_data = data_list[ name ]
except (TypeError, KeyError):
@@ -64,7 +66,7 @@
output_data = data_list[ len(data_list) - len(testdef.outputs) + output_index ]
self.assertTrue( output_data is not None )
try:
- galaxy_interactor.verify_output( history, output_data, outfile, attributes=attributes, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
+ galaxy_interactor.verify_output( history, output_data, output_testdef=output_testdef, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
except Exception:
for stream in ['stdout', 'stderr']:
stream_output = galaxy_interactor.get_job_stream( history, output_data, stream=stream )
diff -r 839a099d99a3d1f35c35c76740087655eacfe46f -r 0ce5e9eb984bc70f1f1c338a3f1d21ed9d6ddee4 test/functional/tools/multi_output.xml
--- a/test/functional/tools/multi_output.xml
+++ b/test/functional/tools/multi_output.xml
@@ -1,7 +1,7 @@
<tool id="multi_output" name="Multi_Output" description="multi_output" force_history_refresh="True" version="0.1.0"><command>
echo "Hello" > $report;
- echo "World" > '${__new_file_path__}/primary_${report.id}_moo_visible_?'
+ echo "World Contents" > '${__new_file_path__}/primary_${report.id}_world_visible_?'
</command><inputs><param name="input" type="integer" value="7" />
@@ -16,6 +16,11 @@
<assert_contents><has_line line="Hello" /></assert_contents>
+ <discovered_dataset designation="world">
+ <assert_contents>
+ <has_line line="World Contents" />
+ </assert_contents>
+ </discovered_dataset></output></test></tests>
diff -r 839a099d99a3d1f35c35c76740087655eacfe46f -r 0ce5e9eb984bc70f1f1c338a3f1d21ed9d6ddee4 test/functional/workflow.py
--- a/test/functional/workflow.py
+++ b/test/functional/workflow.py
@@ -4,6 +4,7 @@
from base.interactor import GalaxyInteractorApi, stage_data_in_history
from galaxy.util import parse_xml
+from galaxy.util import bunch
from galaxy.tools.test import parse_param_elem, require_file, test_data_iter, parse_output_elems
from json import load, dumps
@@ -66,10 +67,11 @@
for expected_output_def in workflow_test.outputs:
# Get the correct hid
name, outfile, attributes = expected_output_def
+ output_testdef = bunch.Bunch( name=name, outfile=outfile, attributes=attributes )
output_data = outputs[ int( name ) ]
try:
- galaxy_interactor.verify_output( test_history, output_data, outfile, attributes=attributes, shed_tool_id=None, maxseconds=maxseconds )
+ galaxy_interactor.verify_output( test_history, output_data, output_testdef=output_testdef, shed_tool_id=None, maxseconds=maxseconds )
except Exception:
for stream in ['stdout', 'stderr']:
stream_output = galaxy_interactor.get_job_stream( test_history, output_data, stream=stream )
https://bitbucket.org/galaxy/galaxy-central/commits/681f2cc6dcfa/
Changeset: 681f2cc6dcfa
User: jmchilton
Date: 2014-03-29 23:11:17
Summary: Refactor Tool.collect_primary_datasets into own module.
Want to break it down in smaller pieces and make process more configurable. Will be easier if its outside of monolithic tool class.
Affected #: 2 files
diff -r 0ce5e9eb984bc70f1f1c338a3f1d21ed9d6ddee4 -r 681f2cc6dcfa2a6674875d10fa8c7699be63dba4 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -42,6 +42,7 @@
from galaxy.tools.deps import build_dependency_manager
from galaxy.tools.deps.requirements import parse_requirements_from_xml
from galaxy.tools.parameters import check_param, params_from_strings, params_to_strings
+from galaxy.tools.parameters import output_collect
from galaxy.tools.parameters.basic import (BaseURLToolParameter,
DataToolParameter, HiddenToolParameter, LibraryDatasetToolParameter,
SelectToolParameter, ToolParameter, UnvalidatedValue,
@@ -2757,94 +2758,7 @@
Find any additional datasets generated by a tool and attach (for
cases where number of outputs is not known in advance).
"""
- new_primary_datasets = {}
- try:
- json_file = open( os.path.join( job_working_directory, jobs.TOOL_PROVIDED_JOB_METADATA_FILE ), 'r' )
- for line in json_file:
- line = json.loads( line )
- if line.get( 'type' ) == 'new_primary_dataset':
- new_primary_datasets[ os.path.split( line.get( 'filename' ) )[-1] ] = line
- except Exception:
- # This should not be considered an error or warning condition, this file is optional
- pass
- # Loop through output file names, looking for generated primary
- # datasets in form of:
- # 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
- primary_datasets = {}
- for name, outdata in output.items():
- filenames = []
- if 'new_file_path' in self.app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(self.app.config.new_file_path, "primary_%i_*" % outdata.id) ) )
- if 'job_working_directory' in self.app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(job_working_directory, "primary_%i_*" % outdata.id) ) )
- for filename in filenames:
- if not name in primary_datasets:
- primary_datasets[name] = {}
- fields = os.path.basename(filename).split("_")
- fields.pop(0)
- parent_id = int(fields.pop(0))
- designation = fields.pop(0)
- visible = fields.pop(0).lower()
- if visible == "visible":
- visible = True
- else:
- visible = False
- ext = fields.pop(0).lower()
- dbkey = outdata.dbkey
- if fields:
- dbkey = fields[ 0 ]
- # Create new primary dataset
- primary_data = self.app.model.HistoryDatasetAssociation( extension=ext,
- designation=designation,
- visible=visible,
- dbkey=dbkey,
- create_dataset=True,
- sa_session=self.sa_session )
- self.app.security_agent.copy_dataset_permissions( outdata.dataset, primary_data.dataset )
- self.sa_session.add( primary_data )
- self.sa_session.flush()
- # Move data from temp location to dataset location
- self.app.object_store.update_from_file(primary_data.dataset, file_name=filename, create=True)
- primary_data.set_size()
- primary_data.name = "%s (%s)" % ( outdata.name, designation )
- primary_data.info = outdata.info
- primary_data.init_meta( copy_from=outdata )
- primary_data.dbkey = dbkey
- # Associate new dataset with job
- job = None
- for assoc in outdata.creating_job_associations:
- job = assoc.job
- break
- if job:
- assoc = self.app.model.JobToOutputDatasetAssociation( '__new_primary_file_%s|%s__' % ( name, designation ), primary_data )
- assoc.job = job
- self.sa_session.add( assoc )
- self.sa_session.flush()
- primary_data.state = outdata.state
- #add tool/metadata provided information
- new_primary_datasets_attributes = new_primary_datasets.get( os.path.split( filename )[-1] )
- if new_primary_datasets_attributes:
- dataset_att_by_name = dict( ext='extension' )
- for att_set in [ 'name', 'info', 'ext', 'dbkey' ]:
- dataset_att_name = dataset_att_by_name.get( att_set, att_set )
- setattr( primary_data, dataset_att_name, new_primary_datasets_attributes.get( att_set, getattr( primary_data, dataset_att_name ) ) )
- primary_data.set_meta()
- primary_data.set_peek()
- self.sa_session.add( primary_data )
- self.sa_session.flush()
- outdata.history.add_dataset( primary_data )
- # Add dataset to return dict
- primary_datasets[name][designation] = primary_data
- # Need to update all associated output hdas, i.e. history was
- # shared with job running
- for dataset in outdata.dataset.history_associations:
- if outdata == dataset:
- continue
- new_data = primary_data.copy()
- dataset.history.add_dataset( new_data )
- self.sa_session.add( new_data )
- self.sa_session.flush()
- return primary_datasets
+ return output_collect.collect_primary_datatasets( self, output, job_working_directory )
def to_dict( self, trans, link_details=False, io_details=False ):
""" Returns dict of tool. """
diff -r 0ce5e9eb984bc70f1f1c338a3f1d21ed9d6ddee4 -r 681f2cc6dcfa2a6674875d10fa8c7699be63dba4 lib/galaxy/tools/parameters/output_collect.py
--- /dev/null
+++ b/lib/galaxy/tools/parameters/output_collect.py
@@ -0,0 +1,101 @@
+""" Code allowing tools to define extra files associated with an output datset.
+"""
+import os
+import glob
+import json
+
+
+from galaxy import jobs
+
+
+def collect_primary_datatasets( tool, output, job_working_directory ):
+ app = tool.app
+ sa_session = tool.sa_session
+ new_primary_datasets = {}
+ try:
+ json_file = open( os.path.join( job_working_directory, jobs.TOOL_PROVIDED_JOB_METADATA_FILE ), 'r' )
+ for line in json_file:
+ line = json.loads( line )
+ if line.get( 'type' ) == 'new_primary_dataset':
+ new_primary_datasets[ os.path.split( line.get( 'filename' ) )[-1] ] = line
+ except Exception:
+ # This should not be considered an error or warning condition, this file is optional
+ pass
+ # Loop through output file names, looking for generated primary
+ # datasets in form of:
+ # 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
+ primary_datasets = {}
+ for name, outdata in output.items():
+ filenames = []
+ if 'new_file_path' in app.config.collect_outputs_from:
+ filenames.extend( glob.glob(os.path.join(app.config.new_file_path, "primary_%i_*" % outdata.id) ) )
+ if 'job_working_directory' in app.config.collect_outputs_from:
+ filenames.extend( glob.glob(os.path.join(job_working_directory, "primary_%i_*" % outdata.id) ) )
+ for filename in filenames:
+ if not name in primary_datasets:
+ primary_datasets[name] = {}
+ fields = os.path.basename(filename).split("_")
+ fields.pop(0)
+ parent_id = int(fields.pop(0))
+ designation = fields.pop(0)
+ visible = fields.pop(0).lower()
+ if visible == "visible":
+ visible = True
+ else:
+ visible = False
+ ext = fields.pop(0).lower()
+ dbkey = outdata.dbkey
+ if fields:
+ dbkey = fields[ 0 ]
+ # Create new primary dataset
+ primary_data = app.model.HistoryDatasetAssociation( extension=ext,
+ designation=designation,
+ visible=visible,
+ dbkey=dbkey,
+ create_dataset=True,
+ sa_session=sa_session )
+ app.security_agent.copy_dataset_permissions( outdata.dataset, primary_data.dataset )
+ sa_session.add( primary_data )
+ sa_session.flush()
+ # Move data from temp location to dataset location
+ app.object_store.update_from_file(primary_data.dataset, file_name=filename, create=True)
+ primary_data.set_size()
+ primary_data.name = "%s (%s)" % ( outdata.name, designation )
+ primary_data.info = outdata.info
+ primary_data.init_meta( copy_from=outdata )
+ primary_data.dbkey = dbkey
+ # Associate new dataset with job
+ job = None
+ for assoc in outdata.creating_job_associations:
+ job = assoc.job
+ break
+ if job:
+ assoc = app.model.JobToOutputDatasetAssociation( '__new_primary_file_%s|%s__' % ( name, designation ), primary_data )
+ assoc.job = job
+ sa_session.add( assoc )
+ sa_session.flush()
+ primary_data.state = outdata.state
+ #add tool/metadata provided information
+ new_primary_datasets_attributes = new_primary_datasets.get( os.path.split( filename )[-1] )
+ if new_primary_datasets_attributes:
+ dataset_att_by_name = dict( ext='extension' )
+ for att_set in [ 'name', 'info', 'ext', 'dbkey' ]:
+ dataset_att_name = dataset_att_by_name.get( att_set, att_set )
+ setattr( primary_data, dataset_att_name, new_primary_datasets_attributes.get( att_set, getattr( primary_data, dataset_att_name ) ) )
+ primary_data.set_meta()
+ primary_data.set_peek()
+ sa_session.add( primary_data )
+ sa_session.flush()
+ outdata.history.add_dataset( primary_data )
+ # Add dataset to return dict
+ primary_datasets[name][designation] = primary_data
+ # Need to update all associated output hdas, i.e. history was
+ # shared with job running
+ for dataset in outdata.dataset.history_associations:
+ if outdata == dataset:
+ continue
+ new_data = primary_data.copy()
+ dataset.history.add_dataset( new_data )
+ sa_session.add( new_data )
+ sa_session.flush()
+ return primary_datasets
https://bitbucket.org/galaxy/galaxy-central/commits/7b8a02bb183b/
Changeset: 7b8a02bb183b
User: jmchilton
Date: 2014-03-29 23:11:17
Summary: Rework parsing of metadata from file names of runtime discovered datasets.
Newer method uses regex and named groups instead of split for more extensible approach to parsing metadata fields during primary dataset collecting. This method will be easier to allow override and configuration of in subsequent changesets.
Affected #: 1 file
diff -r 681f2cc6dcfa2a6674875d10fa8c7699be63dba4 -r 7b8a02bb183bcd7edf6ee9997ea73fe2b6097d5b lib/galaxy/tools/parameters/output_collect.py
--- a/lib/galaxy/tools/parameters/output_collect.py
+++ b/lib/galaxy/tools/parameters/output_collect.py
@@ -1,12 +1,15 @@
""" Code allowing tools to define extra files associated with an output datset.
"""
import os
+import re
import glob
import json
from galaxy import jobs
+DEFAULT_EXTRA_FILENAME_PATTERN = re.compile(r"primary_(?P<id>\d+)_(?P<designation>[^_]+)_(?P<visible>[^_]+)_(?P<ext>[^_]+)(_(?P<dbkey>[^_]+))?")
+
def collect_primary_datatasets( tool, output, job_working_directory ):
app = tool.app
@@ -34,19 +37,14 @@
for filename in filenames:
if not name in primary_datasets:
primary_datasets[name] = {}
- fields = os.path.basename(filename).split("_")
- fields.pop(0)
- parent_id = int(fields.pop(0))
- designation = fields.pop(0)
- visible = fields.pop(0).lower()
- if visible == "visible":
- visible = True
- else:
- visible = False
- ext = fields.pop(0).lower()
- dbkey = outdata.dbkey
- if fields:
- dbkey = fields[ 0 ]
+ fields_match = DEFAULT_EXTRA_FILENAME_PATTERN.match( os.path.basename(filename) )
+ if not fields_match:
+ # Before I guess pop() would just have thrown an IndexError
+ raise Exception( "Problem parsing metadata fields for file %s" % filename )
+ designation = fields_match.group( "designation" )
+ visible = fields_match.group( "visible" ).lower() == "visible"
+ ext = fields_match.group( "ext" ).lower()
+ dbkey = fields_match.group( "dbkey" ) or outdata.dbkey
# Create new primary dataset
primary_data = app.model.HistoryDatasetAssociation( extension=ext,
designation=designation,
https://bitbucket.org/galaxy/galaxy-central/commits/56e9203f0200/
Changeset: 56e9203f0200
User: jmchilton
Date: 2014-03-29 23:11:17
Summary: Allow tool outputs to configure runtime dataset discovery.
Output tags on tool XML datasets may contain any number of child "discover_datasets" elements describing how Galaxy should discover datasests. This new method only works for job_working_directory collection - new_file_path based discovery should be considered deprecated.
Example unit and functional tests describe this new configurability in detail.
Affected #: 5 files
diff -r 7b8a02bb183bcd7edf6ee9997ea73fe2b6097d5b -r 56e9203f020027c8c7a294555f6286ce654f79d2 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1413,6 +1413,7 @@
output.hidden = string_as_bool( data_elem.get("hidden", "") )
output.tool = self
output.actions = ToolOutputActionGroup( output, data_elem.find( 'actions' ) )
+ output.dataset_collectors = output_collect.dataset_collectors_from_elem( data_elem )
self.outputs[ output.name ] = output
# TODO: Include the tool's name in any parsing warnings.
diff -r 7b8a02bb183bcd7edf6ee9997ea73fe2b6097d5b -r 56e9203f020027c8c7a294555f6286ce654f79d2 lib/galaxy/tools/parameters/output_collect.py
--- a/lib/galaxy/tools/parameters/output_collect.py
+++ b/lib/galaxy/tools/parameters/output_collect.py
@@ -7,8 +7,11 @@
from galaxy import jobs
+from galaxy import util
+from galaxy.util import odict
-DEFAULT_EXTRA_FILENAME_PATTERN = re.compile(r"primary_(?P<id>\d+)_(?P<designation>[^_]+)_(?P<visible>[^_]+)_(?P<ext>[^_]+)(_(?P<dbkey>[^_]+))?")
+DATASET_ID_TOKEN = "DATASET_ID"
+DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P<designation>[^_]+)_(?P<visible>[^_]+)_(?P<ext>[^_]+)(_(?P<dbkey>[^_]+))?"
def collect_primary_datatasets( tool, output, job_working_directory ):
@@ -29,22 +32,41 @@
# 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
primary_datasets = {}
for name, outdata in output.items():
- filenames = []
+ dataset_collectors = tool.outputs[ name ].dataset_collectors if name in tool.outputs else [ DEFAULT_DATASET_COLLECTOR ]
+ filenames = odict.odict()
if 'new_file_path' in app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(app.config.new_file_path, "primary_%i_*" % outdata.id) ) )
+ if DEFAULT_DATASET_COLLECTOR in dataset_collectors:
+ # 'new_file_path' collection should be considered deprecated,
+ # only use old-style matching (glob instead of regex and only
+ # using default collector - if enabled).
+ for filename in glob.glob(os.path.join(app.config.new_file_path, "primary_%i_*" % outdata.id) ):
+ filenames[ filename ] = DEFAULT_DATASET_COLLECTOR
if 'job_working_directory' in app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(job_working_directory, "primary_%i_*" % outdata.id) ) )
- for filename in filenames:
+ for extra_file_collector in dataset_collectors:
+ directory = job_working_directory
+ if extra_file_collector.directory:
+ directory = os.path.join( directory, extra_file_collector.directory )
+ if not util.in_directory( directory, job_working_directory ):
+ raise Exception( "Problem with tool configuration, attempting to pull in datasets from outside working directory." )
+ if not os.path.isdir( directory ):
+ continue
+ for filename in os.listdir( directory ):
+ path = os.path.join( directory, filename )
+ if not os.path.isfile( path ):
+ continue
+ if extra_file_collector.match( outdata, filename ):
+ filenames[ path ] = extra_file_collector
+ for filename, extra_file_collector in filenames.iteritems():
if not name in primary_datasets:
primary_datasets[name] = {}
- fields_match = DEFAULT_EXTRA_FILENAME_PATTERN.match( os.path.basename(filename) )
+ fields_match = extra_file_collector.match( outdata, os.path.basename( filename ) )
if not fields_match:
# Before I guess pop() would just have thrown an IndexError
raise Exception( "Problem parsing metadata fields for file %s" % filename )
- designation = fields_match.group( "designation" )
- visible = fields_match.group( "visible" ).lower() == "visible"
- ext = fields_match.group( "ext" ).lower()
- dbkey = fields_match.group( "dbkey" ) or outdata.dbkey
+ designation = fields_match.designation
+ visible = fields_match.visible
+ ext = fields_match.ext
+ dbkey = fields_match.dbkey
# Create new primary dataset
primary_data = app.model.HistoryDatasetAssociation( extension=ext,
designation=designation,
@@ -58,7 +80,9 @@
# Move data from temp location to dataset location
app.object_store.update_from_file(primary_data.dataset, file_name=filename, create=True)
primary_data.set_size()
- primary_data.name = "%s (%s)" % ( outdata.name, designation )
+ # If match specified a name use otherwise generate one from
+ # designation.
+ primary_data.name = fields_match.name or "%s (%s)" % ( outdata.name, designation )
primary_data.info = outdata.info
primary_data.init_meta( copy_from=outdata )
primary_data.dbkey = dbkey
@@ -97,3 +121,99 @@
sa_session.add( new_data )
sa_session.flush()
return primary_datasets
+
+
+# XML can describe custom patterns, but these literals describe named
+# patterns that will be replaced.
+NAMED_PATTERNS = {
+ "__default__": DEFAULT_EXTRA_FILENAME_PATTERN,
+ "__name__": r"(?P<name>.*)",
+ "__designation__": r"(?P<designation>.*)",
+ "__name_and_ext__": r"(?P<name>.*)\.(?P<ext>[^\.]+)?",
+ "__designation_and_ext__": r"(?P<designation>.*)\.(?P<ext>[^\._]+)?",
+}
+
+
+def dataset_collectors_from_elem( elem ):
+ primary_dataset_elems = elem.findall( "discover_datasets" )
+ if not primary_dataset_elems:
+ return [ DEFAULT_DATASET_COLLECTOR ]
+ else:
+ return map( lambda elem: DatasetCollector( **elem.attrib ), primary_dataset_elems )
+
+
+class DatasetCollector( object ):
+
+ def __init__( self, **kwargs ):
+ pattern = kwargs.get( "pattern", "__default__" )
+ if pattern in NAMED_PATTERNS:
+ pattern = NAMED_PATTERNS.get( pattern )
+ self.pattern = pattern
+ self.default_dbkey = kwargs.get( "dbkey", None )
+ self.default_ext = kwargs.get( "ext", None )
+ self.default_visible = util.asbool( kwargs.get( "visible", None ) )
+ self.directory = kwargs.get( "directory", None )
+
+ def pattern_for_dataset( self, dataset_instance=None ):
+ token_replacement = r'\d+'
+ if dataset_instance:
+ token_replacement = str( dataset_instance.id )
+ return self.pattern.replace( DATASET_ID_TOKEN, token_replacement )
+
+ def match( self, dataset_instance, filename ):
+ re_match = re.match( self.pattern_for_dataset( dataset_instance ), filename )
+ match_object = None
+ if re_match:
+ match_object = CollectedDatasetMatch( re_match, self )
+ return match_object
+
+
+class CollectedDatasetMatch( object ):
+
+ def __init__( self, re_match, collector ):
+ self.re_match = re_match
+ self.collector = collector
+
+ @property
+ def designation( self ):
+ re_match = self.re_match
+ if "designation" in re_match.groupdict():
+ return re_match.group( "designation" )
+ elif "name" in re_match.groupdict():
+ return re_match.group( "name" )
+ else:
+ return None
+
+ @property
+ def name( self ):
+ """ Return name or None if not defined by the discovery pattern.
+ """
+ re_match = self.re_match
+ name = None
+ if "name" in re_match.groupdict():
+ name = re_match.group( "name" )
+ return name
+
+ @property
+ def dbkey( self ):
+ try:
+ return self.re_match.group( "dbkey" )
+ except IndexError:
+ return self.collector.default_dbkey
+
+ @property
+ def ext( self ):
+ try:
+ return self.re_match.group( "ext" )
+ except IndexError:
+ return self.collector.default_ext
+
+ @property
+ def visible( self ):
+ try:
+ return self.re_match.group( "visible" ).lower() == "visible"
+ except IndexError:
+ return self.collector.default_visible
+
+
+DEFAULT_DATASET_COLLECTOR = DatasetCollector()
diff -r 7b8a02bb183bcd7edf6ee9997ea73fe2b6097d5b -r 56e9203f020027c8c7a294555f6286ce654f79d2 test/functional/tools/multi_output_configured.xml
--- /dev/null
+++ b/test/functional/tools/multi_output_configured.xml
@@ -0,0 +1,43 @@
+<tool id="multi_output_configured" name="Multi_Output_Configured" description="multi_output_configured" force_history_refresh="True" version="0.1.0">
+ <command>
+ echo "Hello" > $report;
+ mkdir subdir1;
+ echo "This" > subdir1/this.txt;
+ echo "That" > subdir1/that.txt;
+ mkdir subdir2;
+ echo "1" > subdir2/CUSTOM_1.txt;
+ echo "2" > subdir2/CUSTOM_2.tabular;
+ echo "3" > subdir2/CUSTOM_3.txt;
+ </command>
+ <inputs>
+ <param name="input" type="integer" value="7" />
+ </inputs>
+ <outputs>
+ <data format="txt" name="report">
+ <discover_datasets pattern="__designation_and_ext__" directory="subdir1" />
+ <discover_datasets pattern="CUSTOM_(?P<designation>.+)\.(?P<ext>.+)" directory="subdir2" />
+ </data>
+ </outputs>
+ <tests>
+ <test>
+ <param name="input" value="7" />
+ <output name="report">
+ <assert_contents>
+ <has_line line="Hello" />
+ </assert_contents>
+ <discovered_dataset designation="this" ftype="txt">
+ <assert_contents><has_line line="This" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="that" ftype="txt">
+ <assert_contents><has_line line="That" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="1" ftype="txt">
+ <assert_contents><has_line line="1" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="2" ftype="tabular">
+ <assert_contents><has_line line="2" /></assert_contents>
+ </discovered_dataset>
+ </output>
+ </test>
+ </tests>
+</tool>
diff -r 7b8a02bb183bcd7edf6ee9997ea73fe2b6097d5b -r 56e9203f020027c8c7a294555f6286ce654f79d2 test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -8,6 +8,7 @@
<tool file="multi_page.xml"/><tool file="multi_select.xml" /><tool file="multi_output.xml" />
+ <tool file="multi_output_configured.xml" /><tool file="composite_output.xml" /><tool file="metadata.xml" /><tool file="output_order.xml" />
diff -r 7b8a02bb183bcd7edf6ee9997ea73fe2b6097d5b -r 56e9203f020027c8c7a294555f6286ce654f79d2 test/unit/tools/test_collect_primary_datasets.py
--- a/test/unit/tools/test_collect_primary_datasets.py
+++ b/test/unit/tools/test_collect_primary_datasets.py
@@ -5,6 +5,8 @@
import tools_support
from galaxy import model
+from galaxy import util
+from galaxy.tools.parameters import output_collect
DEFAULT_TOOL_OUTPUT = "out1"
DEFAULT_EXTRA_NAME = "test1"
@@ -114,6 +116,75 @@
extra_job_assoc = filter( lambda job_assoc: job_assoc.name.startswith( "__" ), self.job.output_datasets )[ 0 ]
assert extra_job_assoc.name == "__new_primary_file_out1|test1__"
+ def test_pattern_override_designation( self ):
+ self._replace_output_collectors( '''<output><discover_datasets pattern="__designation__" directory="subdir" ext="txt" /></output>''' )
+ self._setup_extra_file( subdir="subdir", filename="foo.txt" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 1
+ created_hda = primary_outputs.values()[ 0 ]
+ assert "foo.txt" in created_hda.name
+ assert created_hda.ext == "txt"
+
+ def test_name_and_ext_pattern( self ):
+ self._replace_output_collectors( '''<output><discover_datasets pattern="__name_and_ext__" directory="subdir" /></output>''' )
+ self._setup_extra_file( subdir="subdir", filename="foo1.txt" )
+ self._setup_extra_file( subdir="subdir", filename="foo2.tabular" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 2
+ assert primary_outputs[ "foo1" ].ext == "txt"
+ assert primary_outputs[ "foo2" ].ext == "tabular"
+
+ def test_custom_pattern( self ):
+ # Hypothetical oral metagenomic classifier that populates a directory
+ # of files based on name and genome. Use custom regex pattern to grab
+ # and classify these files.
+ self._replace_output_collectors( '''<output><discover_datasets pattern="(?P<designation>.*)__(?P<dbkey>.*).fasta" directory="genome_breakdown" ext="fasta" /></output>''' )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp1__hg19.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp2__lactLact.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp3__hg19.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp4__lactPlan.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp5__fusoNucl.fasta" )
+
+ # Put a file in directory we don't care about, just to make sure
+ # it doesn't get picked up by pattern.
+ self._setup_extra_file( subdir="genome_breakdown", filename="overview.txt" )
+
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 5
+ genomes = dict( samp1="hg19", samp2="lactLact", samp3="hg19", samp4="lactPlan", samp5="fusoNucl" )
+ for key, hda in primary_outputs.iteritems():
+ assert hda.dbkey == genomes[ key ]
+
+ def test_name_versus_designation( self ):
+ """ This test demonstrates the difference between name and desgination
+ in grouping patterns and named patterns such as __designation__,
+ __name__, __designation_and_ext__, and __name_and_ext__.
+ """
+ self._replace_output_collectors( '''<output>
+ <discover_datasets pattern="__name_and_ext__" directory="subdir_for_name_discovery" />
+ <discover_datasets pattern="__designation_and_ext__" directory="subdir_for_designation_discovery" />
+ </output>''')
+ self._setup_extra_file( subdir="subdir_for_name_discovery", filename="example1.txt" )
+ self._setup_extra_file( subdir="subdir_for_designation_discovery", filename="example2.txt" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ name_output = primary_outputs[ "example1" ]
+ designation_output = primary_outputs[ "example2" ]
+ # While name is also used for designation, designation is not the name -
+ # it is used in the calculation of the name however...
+ assert name_output.name == "example1"
+ assert designation_output.name == "%s (%s)" % ( self.hda.name, "example2" )
+
+ def test_cannot_read_files_outside_job_directory( self ):
+ self._replace_output_collectors( '''<output>
+ <discover_datasets pattern="__name_and_ext__" directory="../../secrets" />
+ </output>''')
+ exception_thrown = False
+ try:
+ self._collect( )
+ except Exception:
+ exception_thrown = True
+ assert exception_thrown
+
def _collect_default_extra( self, **kwargs ):
return self._collect( **kwargs )[ DEFAULT_TOOL_OUTPUT ][ DEFAULT_EXTRA_NAME ]
@@ -122,6 +193,12 @@
job_working_directory = self.test_directory
return self.tool.collect_primary_datasets( self.outputs, job_working_directory )
+ def _replace_output_collectors( self, xml_str ):
+ # Rewrite tool as if it had been created with output containing
+ # supplied dataset_collector elem.
+ elem = util.parse_xml_string( xml_str )
+ self.tool.outputs[ DEFAULT_TOOL_OUTPUT ].dataset_collectors = output_collect.dataset_collectors_from_elem( elem )
+
def _append_job_json( self, object, output_path=None, line_type="new_primary_dataset" ):
object[ "type" ] = line_type
if output_path:
@@ -133,7 +210,8 @@
def _setup_extra_file( self, **kwargs ):
path = kwargs.get( "path", None )
- if not path:
+ filename = kwargs.get( "filename", None )
+ if not path and not filename:
name = kwargs.get( "name", DEFAULT_EXTRA_NAME )
visible = kwargs.get( "visible", "visible" )
ext = kwargs.get( "ext", "data" )
@@ -142,6 +220,13 @@
path = os.path.join( directory, "primary_%s_%s_%s_%s" % template_args )
if "dbkey" in kwargs:
path = "%s_%s" % ( path, kwargs[ "dbkey" ] )
+ if not path:
+ assert filename
+ subdir = kwargs.get( "subdir", "." )
+ path = os.path.join( self.test_directory, subdir, filename )
+ directory = os.path.dirname( path )
+ if not os.path.exists( directory ):
+ os.makedirs( directory )
contents = kwargs.get( "contents", "test contents" )
open( path, "w" ).write( contents )
return path
https://bitbucket.org/galaxy/galaxy-central/commits/8e6cda4c1b3d/
Changeset: 8e6cda4c1b3d
User: jmchilton
Date: 2014-05-06 15:13:29
Summary: Merged in jmchilton/galaxy-central-fork-1 (pull request #356)
Enhancements for Runtime Discovered (Collected Primary) Datasets
Affected #: 13 files
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -42,6 +42,7 @@
from galaxy.tools.deps import build_dependency_manager
from galaxy.tools.deps.requirements import parse_requirements_from_xml
from galaxy.tools.parameters import check_param, params_from_strings, params_to_strings
+from galaxy.tools.parameters import output_collect
from galaxy.tools.parameters.basic import (BaseURLToolParameter,
DataToolParameter, HiddenToolParameter, LibraryDatasetToolParameter,
SelectToolParameter, ToolParameter, UnvalidatedValue,
@@ -1452,6 +1453,7 @@
output.hidden = string_as_bool( data_elem.get("hidden", "") )
output.tool = self
output.actions = ToolOutputActionGroup( output, data_elem.find( 'actions' ) )
+ output.dataset_collectors = output_collect.dataset_collectors_from_elem( data_elem )
self.outputs[ output.name ] = output
# TODO: Include the tool's name in any parsing warnings.
@@ -2800,94 +2802,7 @@
Find any additional datasets generated by a tool and attach (for
cases where number of outputs is not known in advance).
"""
- new_primary_datasets = {}
- try:
- json_file = open( os.path.join( job_working_directory, jobs.TOOL_PROVIDED_JOB_METADATA_FILE ), 'r' )
- for line in json_file:
- line = json.loads( line )
- if line.get( 'type' ) == 'new_primary_dataset':
- new_primary_datasets[ os.path.split( line.get( 'filename' ) )[-1] ] = line
- except Exception:
- # This should not be considered an error or warning condition, this file is optional
- pass
- # Loop through output file names, looking for generated primary
- # datasets in form of:
- # 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
- primary_datasets = {}
- for name, outdata in output.items():
- filenames = []
- if 'new_file_path' in self.app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(self.app.config.new_file_path, "primary_%i_*" % outdata.id) ) )
- if 'job_working_directory' in self.app.config.collect_outputs_from:
- filenames.extend( glob.glob(os.path.join(job_working_directory, "primary_%i_*" % outdata.id) ) )
- for filename in filenames:
- if not name in primary_datasets:
- primary_datasets[name] = {}
- fields = os.path.basename(filename).split("_")
- fields.pop(0)
- parent_id = int(fields.pop(0))
- designation = fields.pop(0)
- visible = fields.pop(0).lower()
- if visible == "visible":
- visible = True
- else:
- visible = False
- ext = fields.pop(0).lower()
- dbkey = outdata.dbkey
- if fields:
- dbkey = fields[ 0 ]
- # Create new primary dataset
- primary_data = self.app.model.HistoryDatasetAssociation( extension=ext,
- designation=designation,
- visible=visible,
- dbkey=dbkey,
- create_dataset=True,
- sa_session=self.sa_session )
- self.app.security_agent.copy_dataset_permissions( outdata.dataset, primary_data.dataset )
- self.sa_session.add( primary_data )
- self.sa_session.flush()
- # Move data from temp location to dataset location
- self.app.object_store.update_from_file(primary_data.dataset, file_name=filename, create=True)
- primary_data.set_size()
- primary_data.name = "%s (%s)" % ( outdata.name, designation )
- primary_data.info = outdata.info
- primary_data.init_meta( copy_from=outdata )
- primary_data.dbkey = dbkey
- # Associate new dataset with job
- job = None
- for assoc in outdata.creating_job_associations:
- job = assoc.job
- break
- if job:
- assoc = self.app.model.JobToOutputDatasetAssociation( '__new_primary_file_%s|%s__' % ( name, designation ), primary_data )
- assoc.job = job
- self.sa_session.add( assoc )
- self.sa_session.flush()
- primary_data.state = outdata.state
- #add tool/metadata provided information
- new_primary_datasets_attributes = new_primary_datasets.get( os.path.split( filename )[-1] )
- if new_primary_datasets_attributes:
- dataset_att_by_name = dict( ext='extension' )
- for att_set in [ 'name', 'info', 'ext', 'dbkey' ]:
- dataset_att_name = dataset_att_by_name.get( att_set, att_set )
- setattr( primary_data, dataset_att_name, new_primary_datasets_attributes.get( att_set, getattr( primary_data, dataset_att_name ) ) )
- primary_data.set_meta()
- primary_data.set_peek()
- self.sa_session.add( primary_data )
- self.sa_session.flush()
- outdata.history.add_dataset( primary_data )
- # Add dataset to return dict
- primary_datasets[name][designation] = primary_data
- # Need to update all associated output hdas, i.e. history was
- # shared with job running
- for dataset in outdata.dataset.history_associations:
- if outdata == dataset:
- continue
- new_data = primary_data.copy()
- dataset.history.add_dataset( new_data )
- self.sa_session.add( new_data )
- self.sa_session.flush()
- return primary_datasets
+ return output_collect.collect_primary_datatasets( self, output, job_working_directory )
def to_dict( self, trans, link_details=False, io_details=False ):
""" Returns dict of tool. """
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/tools/parameters/output_collect.py
--- /dev/null
+++ b/lib/galaxy/tools/parameters/output_collect.py
@@ -0,0 +1,219 @@
+""" Code allowing tools to define extra files associated with an output datset.
+"""
+import os
+import re
+import glob
+import json
+
+
+from galaxy import jobs
+from galaxy import util
+from galaxy.util import odict
+
+DATASET_ID_TOKEN = "DATASET_ID"
+DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P<designation>[^_]+)_(?P<visible>[^_]+)_(?P<ext>[^_]+)(_(?P<dbkey>[^_]+))?"
+
+
+def collect_primary_datatasets( tool, output, job_working_directory ):
+ app = tool.app
+ sa_session = tool.sa_session
+ new_primary_datasets = {}
+ try:
+ json_file = open( os.path.join( job_working_directory, jobs.TOOL_PROVIDED_JOB_METADATA_FILE ), 'r' )
+ for line in json_file:
+ line = json.loads( line )
+ if line.get( 'type' ) == 'new_primary_dataset':
+ new_primary_datasets[ os.path.split( line.get( 'filename' ) )[-1] ] = line
+ except Exception:
+ # This should not be considered an error or warning condition, this file is optional
+ pass
+ # Loop through output file names, looking for generated primary
+ # datasets in form of:
+ # 'primary_associatedWithDatasetID_designation_visibility_extension(_DBKEY)'
+ primary_datasets = {}
+ for name, outdata in output.items():
+ dataset_collectors = tool.outputs[ name ].dataset_collectors if name in tool.outputs else [ DEFAULT_DATASET_COLLECTOR ]
+ filenames = odict.odict()
+ if 'new_file_path' in app.config.collect_outputs_from:
+ if DEFAULT_DATASET_COLLECTOR in dataset_collectors:
+ # 'new_file_path' collection should be considered deprecated,
+ # only use old-style matching (glob instead of regex and only
+ # using default collector - if enabled).
+ for filename in glob.glob(os.path.join(app.config.new_file_path, "primary_%i_*" % outdata.id) ):
+ filenames[ filename ] = DEFAULT_DATASET_COLLECTOR
+ if 'job_working_directory' in app.config.collect_outputs_from:
+ for extra_file_collector in dataset_collectors:
+ directory = job_working_directory
+ if extra_file_collector.directory:
+ directory = os.path.join( directory, extra_file_collector.directory )
+ if not util.in_directory( directory, job_working_directory ):
+ raise Exception( "Problem with tool configuration, attempting to pull in datasets from outside working directory." )
+ if not os.path.isdir( directory ):
+ continue
+ for filename in os.listdir( directory ):
+ path = os.path.join( directory, filename )
+ if not os.path.isfile( path ):
+ continue
+ if extra_file_collector.match( outdata, filename ):
+ filenames[ path ] = extra_file_collector
+ for filename, extra_file_collector in filenames.iteritems():
+ if not name in primary_datasets:
+ primary_datasets[name] = {}
+ fields_match = extra_file_collector.match( outdata, os.path.basename( filename ) )
+ if not fields_match:
+ # Before I guess pop() would just have thrown an IndexError
+ raise Exception( "Problem parsing metadata fields for file %s" % filename )
+ designation = fields_match.designation
+ visible = fields_match.visible
+ ext = fields_match.ext
+ dbkey = fields_match.dbkey
+ # Create new primary dataset
+ primary_data = app.model.HistoryDatasetAssociation( extension=ext,
+ designation=designation,
+ visible=visible,
+ dbkey=dbkey,
+ create_dataset=True,
+ sa_session=sa_session )
+ app.security_agent.copy_dataset_permissions( outdata.dataset, primary_data.dataset )
+ sa_session.add( primary_data )
+ sa_session.flush()
+ # Move data from temp location to dataset location
+ app.object_store.update_from_file(primary_data.dataset, file_name=filename, create=True)
+ primary_data.set_size()
+ # If match specified a name use otherwise generate one from
+ # designation.
+ primary_data.name = fields_match.name or "%s (%s)" % ( outdata.name, designation )
+ primary_data.info = outdata.info
+ primary_data.init_meta( copy_from=outdata )
+ primary_data.dbkey = dbkey
+ # Associate new dataset with job
+ job = None
+ for assoc in outdata.creating_job_associations:
+ job = assoc.job
+ break
+ if job:
+ assoc = app.model.JobToOutputDatasetAssociation( '__new_primary_file_%s|%s__' % ( name, designation ), primary_data )
+ assoc.job = job
+ sa_session.add( assoc )
+ sa_session.flush()
+ primary_data.state = outdata.state
+ #add tool/metadata provided information
+ new_primary_datasets_attributes = new_primary_datasets.get( os.path.split( filename )[-1] )
+ if new_primary_datasets_attributes:
+ dataset_att_by_name = dict( ext='extension' )
+ for att_set in [ 'name', 'info', 'ext', 'dbkey' ]:
+ dataset_att_name = dataset_att_by_name.get( att_set, att_set )
+ setattr( primary_data, dataset_att_name, new_primary_datasets_attributes.get( att_set, getattr( primary_data, dataset_att_name ) ) )
+ primary_data.set_meta()
+ primary_data.set_peek()
+ sa_session.add( primary_data )
+ sa_session.flush()
+ outdata.history.add_dataset( primary_data )
+ # Add dataset to return dict
+ primary_datasets[name][designation] = primary_data
+ # Need to update all associated output hdas, i.e. history was
+ # shared with job running
+ for dataset in outdata.dataset.history_associations:
+ if outdata == dataset:
+ continue
+ new_data = primary_data.copy()
+ dataset.history.add_dataset( new_data )
+ sa_session.add( new_data )
+ sa_session.flush()
+ return primary_datasets
+
+
+# XML can describe custom patterns, but these literals describe named
+# patterns that will be replaced.
+NAMED_PATTERNS = {
+ "__default__": DEFAULT_EXTRA_FILENAME_PATTERN,
+ "__name__": r"(?P<name>.*)",
+ "__designation__": r"(?P<designation>.*)",
+ "__name_and_ext__": r"(?P<name>.*)\.(?P<ext>[^\.]+)?",
+ "__designation_and_ext__": r"(?P<designation>.*)\.(?P<ext>[^\._]+)?",
+}
+
+
+def dataset_collectors_from_elem( elem ):
+ primary_dataset_elems = elem.findall( "discover_datasets" )
+ if not primary_dataset_elems:
+ return [ DEFAULT_DATASET_COLLECTOR ]
+ else:
+ return map( lambda elem: DatasetCollector( **elem.attrib ), primary_dataset_elems )
+
+
+class DatasetCollector( object ):
+
+ def __init__( self, **kwargs ):
+ pattern = kwargs.get( "pattern", "__default__" )
+ if pattern in NAMED_PATTERNS:
+ pattern = NAMED_PATTERNS.get( pattern )
+ self.pattern = pattern
+ self.default_dbkey = kwargs.get( "dbkey", None )
+ self.default_ext = kwargs.get( "ext", None )
+ self.default_visible = util.asbool( kwargs.get( "visible", None ) )
+ self.directory = kwargs.get( "directory", None )
+
+ def pattern_for_dataset( self, dataset_instance=None ):
+ token_replacement = r'\d+'
+ if dataset_instance:
+ token_replacement = str( dataset_instance.id )
+ return self.pattern.replace( DATASET_ID_TOKEN, token_replacement )
+
+ def match( self, dataset_instance, filename ):
+ re_match = re.match( self.pattern_for_dataset( dataset_instance ), filename )
+ match_object = None
+ if re_match:
+ match_object = CollectedDatasetMatch( re_match, self )
+ return match_object
+
+
+class CollectedDatasetMatch( object ):
+
+ def __init__( self, re_match, collector ):
+ self.re_match = re_match
+ self.collector = collector
+
+ @property
+ def designation( self ):
+ re_match = self.re_match
+ if "designation" in re_match.groupdict():
+ return re_match.group( "designation" )
+ elif "name" in re_match.groupdict():
+ return re_match.group( "name" )
+ else:
+ return None
+
+ @property
+ def name( self ):
+ """ Return name or None if not defined by the discovery pattern.
+ """
+ re_match = self.re_match
+ name = None
+ if "name" in re_match.groupdict():
+ name = re_match.group( "name" )
+ return name
+
+ @property
+ def dbkey( self ):
+ try:
+ return self.re_match.group( "dbkey" )
+ except IndexError:
+ return self.collector.default_dbkey
+
+ @property
+ def ext( self ):
+ try:
+ return self.re_match.group( "ext" )
+ except IndexError:
+ return self.collector.default_ext
+
+ @property
+ def visible( self ):
+ try:
+ return self.re_match.group( "visible" ).lower() == "visible"
+ except IndexError:
+ return self.collector.default_visible
+
+
+DEFAULT_DATASET_COLLECTOR = DatasetCollector()
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -297,6 +297,19 @@
if name is None:
raise Exception( "Test output does not have a 'name'" )
+ file, attributes = __parse_test_attributes( output_elem, attrib )
+ primary_datasets = {}
+ for primary_elem in ( output_elem.findall( "discovered_dataset" ) or [] ):
+ primary_attrib = dict( primary_elem.attrib )
+ designation = primary_attrib.pop( 'designation', None )
+ if designation is None:
+ raise Exception( "Test primary dataset does not have a 'designation'" )
+ primary_datasets[ designation ] = __parse_test_attributes( primary_elem, primary_attrib )
+ attributes[ "primary_datasets" ] = primary_datasets
+ return name, file, attributes
+
+
+def __parse_test_attributes( output_elem, attrib ):
assert_list = __parse_assert_list( output_elem )
file = attrib.pop( 'file', None )
# File no longer required if an list of assertions was present.
@@ -321,7 +334,7 @@
attributes['assert_list'] = assert_list
attributes['extra_files'] = extra_files
attributes['metadata'] = metadata
- return name, file, attributes
+ return file, attributes
def __parse_assert_list( output_elem ):
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -13,6 +13,7 @@
from galaxy.web.base.controller import UsesLibraryMixinItems
from galaxy import exceptions
from galaxy import util
+from galaxy import model
import logging
log = logging.getLogger( __name__ )
@@ -91,10 +92,62 @@
:rtype: dictionary
:returns: dictionary containing full description of job data
"""
+ job = self.__get_job( trans, id )
+ return self.encode_all_ids( trans, job.to_dict( 'element' ), True )
+
+ @expose_api
+ def inputs( self, trans, id, **kwd ):
+ """
+ show( trans, id )
+ * GET /api/jobs/{job_id}/inputs
+ returns input datasets created by job
+
+ :type id: string
+ :param id: Encoded job id
+
+ :rtype: dictionary
+ :returns: dictionary containing input dataset associations
+ """
+ job = self.__get_job( trans, id )
+ return self.__dictify_associations( trans, job.input_datasets, job.input_library_datasets )
+
+ @expose_api
+ def outputs( self, trans, id, **kwd ):
+ """
+ show( trans, id )
+ * GET /api/jobs/{job_id}/outputs
+ returns output datasets created by job
+
+ :type id: string
+ :param id: Encoded job id
+
+ :rtype: dictionary
+ :returns: dictionary containing output dataset associations
+ """
+ job = self.__get_job( trans, id )
+ return self.__dictify_associations( trans, job.output_datasets, job.output_library_datasets )
+
+ def __dictify_associations( self, trans, *association_lists ):
+ rval = []
+ for association_list in association_lists:
+ rval.extend( map( lambda a: self.__dictify_association( trans, a ), association_list ) )
+ return rval
+
+ def __dictify_association( self, trans, job_dataset_association ):
+ dataset_dict = None
+ dataset = job_dataset_association.dataset
+ if dataset:
+ if isinstance( dataset, model.HistoryDatasetAssociation ):
+ dataset_dict = dict( src="hda", id=trans.security.encode_id( dataset.id ) )
+ else:
+ dataset_dict = dict( src="ldda", id=trans.security.encode_id( dataset.id ) )
+ return dict( name=job_dataset_association.name, dataset=dataset_dict )
+
+ def __get_job( self, trans, id ):
try:
- decoded_job_id = trans.security.decode_id(id)
- except:
- raise exceptions.ObjectAttributeInvalidException()
+ decoded_job_id = trans.security.decode_id( id )
+ except Exception:
+ raise exceptions.MalformedId()
query = trans.sa_session.query( trans.app.model.Job ).filter(
trans.app.model.Job.user == trans.user,
trans.app.model.Job.id == decoded_job_id
@@ -102,7 +155,7 @@
job = query.first()
if job is None:
raise exceptions.ObjectNotFound()
- return self.encode_all_ids( trans, job.to_dict( 'element' ), True )
+ return job
@expose_api
def create( self, trans, payload, **kwd ):
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/webapps/galaxy/api/provenance.py
--- a/lib/galaxy/webapps/galaxy/api/provenance.py
+++ b/lib/galaxy/webapps/galaxy/api/provenance.py
@@ -46,6 +46,7 @@
return {
"id": trans.security.encode_id(item.id),
"uuid": ( lambda uuid: str( uuid ) if uuid else None )( item.dataset.uuid),
+ "job_id": trans.security.encode_id( job.id ),
"tool_id": job.tool_id,
"parameters": self._get_job_record(trans, job, follow),
"stderr": job.stderr,
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -281,6 +281,8 @@
'jobs',
path_prefix='/api' )
webapp.mapper.connect( 'job_search', '/api/jobs/search', controller='jobs', action='search', conditions=dict( method=['POST'] ) )
+ webapp.mapper.connect( 'job_inputs', '/api/jobs/{id}/inputs', controller='jobs', action='inputs', conditions=dict( method=['GET'] ) )
+ webapp.mapper.connect( 'job_outputs', '/api/jobs/{id}/outputs', controller='jobs', action='outputs', conditions=dict( method=['GET'] ) )
# Job files controllers. Only for consumption by remote job runners.
webapp.mapper.resource( 'file',
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/base/interactor.py
--- a/test/base/interactor.py
+++ b/test/base/interactor.py
@@ -44,16 +44,44 @@
self.api_key = self.__get_user_key( twill_test_case.user_api_key, twill_test_case.master_api_key, test_user=test_user )
self.uploads = {}
- def verify_output( self, history_id, output_data, outfile, attributes, shed_tool_id, maxseconds ):
+ def verify_output( self, history_id, output_data, output_testdef, shed_tool_id, maxseconds ):
+ outfile = output_testdef.outfile
+ attributes = output_testdef.attributes
+ name = output_testdef.name
self.wait_for_history( history_id, maxseconds )
hid = self.__output_id( output_data )
fetcher = self.__dataset_fetcher( history_id )
## TODO: Twill version verifys dataset is 'ok' in here.
self.twill_test_case.verify_hid( outfile, hda_id=hid, attributes=attributes, dataset_fetcher=fetcher, shed_tool_id=shed_tool_id )
+
+ primary_datasets = attributes.get( 'primary_datasets', {} )
+ if primary_datasets:
+ job_id = self._dataset_provenance( history_id, hid )[ "job_id" ]
+ outputs = self._get( "jobs/%s/outputs" % ( job_id ) ).json()
+
+ for designation, ( primary_outfile, primary_attributes ) in primary_datasets.iteritems():
+ primary_output = None
+ for output in outputs:
+ if output[ "name" ] == '__new_primary_file_%s|%s__' % ( name, designation ):
+ primary_output = output
+ break
+
+ if not primary_output:
+ msg_template = "Failed to find primary dataset with designation [%s] for output with name [%s]"
+ msg_args = ( designation, name )
+ raise Exception( msg_template % msg_args )
+
+ primary_hda_id = primary_output[ "dataset" ][ "id" ]
+ self.twill_test_case.verify_hid( primary_outfile, hda_id=primary_hda_id, attributes=primary_attributes, dataset_fetcher=fetcher, shed_tool_id=shed_tool_id )
+ self._verify_metadata( history_id, primary_hda_id, primary_attributes )
+
+ self._verify_metadata( history_id, hid, attributes )
+
+ def _verify_metadata( self, history_id, hid, attributes ):
metadata = attributes.get( 'metadata', {} ).copy()
for key, value in metadata.copy().iteritems():
new_key = "metadata_%s" % key
- metadata[ new_key ] = metadata[ key ]
+ metadata[ new_key ] = metadata[ key ]
del metadata[ key ]
expected_file_type = attributes.get( 'ftype', None )
if expected_file_type:
@@ -319,7 +347,10 @@
def __init__( self, twill_test_case ):
self.twill_test_case = twill_test_case
- def verify_output( self, history, output_data, outfile, attributes, shed_tool_id, maxseconds ):
+ def verify_output( self, history, output_data, output_testdef, shed_tool_id, maxseconds ):
+ outfile = output_testdef.outfile
+ attributes = output_testdef.attributes
+
hid = output_data.get( 'hid' )
self.twill_test_case.verify_dataset_correctness( outfile, hid=hid, attributes=attributes, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -3,6 +3,7 @@
from base.twilltestcase import TwillTestCase
from base.interactor import build_interactor, stage_data_in_history
from galaxy.tools import DataManagerTool
+from galaxy.util import bunch
import logging
log = logging.getLogger( __name__ )
@@ -52,6 +53,7 @@
for output_index, output_tuple in enumerate(testdef.outputs):
# Get the correct hid
name, outfile, attributes = output_tuple
+ output_testdef = bunch.Bunch( name=name, outfile=outfile, attributes=attributes )
try:
output_data = data_list[ name ]
except (TypeError, KeyError):
@@ -64,7 +66,7 @@
output_data = data_list[ len(data_list) - len(testdef.outputs) + output_index ]
self.assertTrue( output_data is not None )
try:
- galaxy_interactor.verify_output( history, output_data, outfile, attributes=attributes, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
+ galaxy_interactor.verify_output( history, output_data, output_testdef=output_testdef, shed_tool_id=shed_tool_id, maxseconds=maxseconds )
except Exception:
for stream in ['stdout', 'stderr']:
stream_output = galaxy_interactor.get_job_stream( history, output_data, stream=stream )
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/tools/multi_output.xml
--- a/test/functional/tools/multi_output.xml
+++ b/test/functional/tools/multi_output.xml
@@ -1,7 +1,7 @@
<tool id="multi_output" name="Multi_Output" description="multi_output" force_history_refresh="True" version="0.1.0"><command>
echo "Hello" > $report;
- echo "World" > '${__new_file_path__}/primary_${report.id}_moo_visible_?'
+ echo "World Contents" > '${__new_file_path__}/primary_${report.id}_world_visible_?'
</command><inputs><param name="input" type="integer" value="7" />
@@ -16,6 +16,11 @@
<assert_contents><has_line line="Hello" /></assert_contents>
+ <discovered_dataset designation="world">
+ <assert_contents>
+ <has_line line="World Contents" />
+ </assert_contents>
+ </discovered_dataset></output></test></tests>
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/tools/multi_output_configured.xml
--- /dev/null
+++ b/test/functional/tools/multi_output_configured.xml
@@ -0,0 +1,43 @@
+<tool id="multi_output_configured" name="Multi_Output_Configured" description="multi_output_configured" force_history_refresh="True" version="0.1.0">
+ <command>
+ echo "Hello" > $report;
+ mkdir subdir1;
+ echo "This" > subdir1/this.txt;
+ echo "That" > subdir1/that.txt;
+ mkdir subdir2;
+ echo "1" > subdir2/CUSTOM_1.txt;
+ echo "2" > subdir2/CUSTOM_2.tabular;
+ echo "3" > subdir2/CUSTOM_3.txt;
+ </command>
+ <inputs>
+ <param name="input" type="integer" value="7" />
+ </inputs>
+ <outputs>
+ <data format="txt" name="report">
+ <discover_datasets pattern="__designation_and_ext__" directory="subdir1" />
+ <discover_datasets pattern="CUSTOM_(?P<designation>.+)\.(?P<ext>.+)" directory="subdir2" />
+ </data>
+ </outputs>
+ <tests>
+ <test>
+ <param name="input" value="7" />
+ <output name="report">
+ <assert_contents>
+ <has_line line="Hello" />
+ </assert_contents>
+ <discovered_dataset designation="this" ftype="txt">
+ <assert_contents><has_line line="This" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="that" ftype="txt">
+ <assert_contents><has_line line="That" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="1" ftype="txt">
+ <assert_contents><has_line line="1" /></assert_contents>
+ </discovered_dataset>
+ <discovered_dataset designation="2" ftype="tabular">
+ <assert_contents><has_line line="2" /></assert_contents>
+ </discovered_dataset>
+ </output>
+ </test>
+ </tests>
+</tool>
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -8,6 +8,7 @@
<tool file="multi_page.xml"/><tool file="multi_select.xml" /><tool file="multi_output.xml" />
+ <tool file="multi_output_configured.xml" /><tool file="composite_output.xml" /><tool file="metadata.xml" /><tool file="output_order.xml" />
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/functional/workflow.py
--- a/test/functional/workflow.py
+++ b/test/functional/workflow.py
@@ -4,6 +4,7 @@
from base.interactor import GalaxyInteractorApi, stage_data_in_history
from galaxy.util import parse_xml
+from galaxy.util import bunch
from galaxy.tools.test import parse_param_elem, require_file, test_data_iter, parse_output_elems
from json import load, dumps
@@ -66,10 +67,11 @@
for expected_output_def in workflow_test.outputs:
# Get the correct hid
name, outfile, attributes = expected_output_def
+ output_testdef = bunch.Bunch( name=name, outfile=outfile, attributes=attributes )
output_data = outputs[ int( name ) ]
try:
- galaxy_interactor.verify_output( test_history, output_data, outfile, attributes=attributes, shed_tool_id=None, maxseconds=maxseconds )
+ galaxy_interactor.verify_output( test_history, output_data, output_testdef=output_testdef, shed_tool_id=None, maxseconds=maxseconds )
except Exception:
for stream in ['stdout', 'stderr']:
stream_output = galaxy_interactor.get_job_stream( test_history, output_data, stream=stream )
diff -r 74b6e23ed7882f3c091d2b66ce85025241372017 -r 8e6cda4c1b3d1685a8ce07412dc542f34eb8b44b test/unit/tools/test_collect_primary_datasets.py
--- a/test/unit/tools/test_collect_primary_datasets.py
+++ b/test/unit/tools/test_collect_primary_datasets.py
@@ -5,6 +5,8 @@
import tools_support
from galaxy import model
+from galaxy import util
+from galaxy.tools.parameters import output_collect
DEFAULT_TOOL_OUTPUT = "out1"
DEFAULT_EXTRA_NAME = "test1"
@@ -114,6 +116,75 @@
extra_job_assoc = filter( lambda job_assoc: job_assoc.name.startswith( "__" ), self.job.output_datasets )[ 0 ]
assert extra_job_assoc.name == "__new_primary_file_out1|test1__"
+ def test_pattern_override_designation( self ):
+ self._replace_output_collectors( '''<output><discover_datasets pattern="__designation__" directory="subdir" ext="txt" /></output>''' )
+ self._setup_extra_file( subdir="subdir", filename="foo.txt" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 1
+ created_hda = primary_outputs.values()[ 0 ]
+ assert "foo.txt" in created_hda.name
+ assert created_hda.ext == "txt"
+
+ def test_name_and_ext_pattern( self ):
+ self._replace_output_collectors( '''<output><discover_datasets pattern="__name_and_ext__" directory="subdir" /></output>''' )
+ self._setup_extra_file( subdir="subdir", filename="foo1.txt" )
+ self._setup_extra_file( subdir="subdir", filename="foo2.tabular" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 2
+ assert primary_outputs[ "foo1" ].ext == "txt"
+ assert primary_outputs[ "foo2" ].ext == "tabular"
+
+ def test_custom_pattern( self ):
+ # Hypothetical oral metagenomic classifier that populates a directory
+ # of files based on name and genome. Use custom regex pattern to grab
+ # and classify these files.
+ self._replace_output_collectors( '''<output><discover_datasets pattern="(?P<designation>.*)__(?P<dbkey>.*).fasta" directory="genome_breakdown" ext="fasta" /></output>''' )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp1__hg19.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp2__lactLact.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp3__hg19.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp4__lactPlan.fasta" )
+ self._setup_extra_file( subdir="genome_breakdown", filename="samp5__fusoNucl.fasta" )
+
+ # Put a file in directory we don't care about, just to make sure
+ # it doesn't get picked up by pattern.
+ self._setup_extra_file( subdir="genome_breakdown", filename="overview.txt" )
+
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ assert len( primary_outputs ) == 5
+ genomes = dict( samp1="hg19", samp2="lactLact", samp3="hg19", samp4="lactPlan", samp5="fusoNucl" )
+ for key, hda in primary_outputs.iteritems():
+ assert hda.dbkey == genomes[ key ]
+
+ def test_name_versus_designation( self ):
+ """ This test demonstrates the difference between name and desgination
+ in grouping patterns and named patterns such as __designation__,
+ __name__, __designation_and_ext__, and __name_and_ext__.
+ """
+ self._replace_output_collectors( '''<output>
+ <discover_datasets pattern="__name_and_ext__" directory="subdir_for_name_discovery" />
+ <discover_datasets pattern="__designation_and_ext__" directory="subdir_for_designation_discovery" />
+ </output>''')
+ self._setup_extra_file( subdir="subdir_for_name_discovery", filename="example1.txt" )
+ self._setup_extra_file( subdir="subdir_for_designation_discovery", filename="example2.txt" )
+ primary_outputs = self._collect( )[ DEFAULT_TOOL_OUTPUT ]
+ name_output = primary_outputs[ "example1" ]
+ designation_output = primary_outputs[ "example2" ]
+ # While name is also used for designation, designation is not the name -
+ # it is used in the calculation of the name however...
+ assert name_output.name == "example1"
+ assert designation_output.name == "%s (%s)" % ( self.hda.name, "example2" )
+
+ def test_cannot_read_files_outside_job_directory( self ):
+ self._replace_output_collectors( '''<output>
+ <discover_datasets pattern="__name_and_ext__" directory="../../secrets" />
+ </output>''')
+ exception_thrown = False
+ try:
+ self._collect( )
+ except Exception:
+ exception_thrown = True
+ assert exception_thrown
+
def _collect_default_extra( self, **kwargs ):
return self._collect( **kwargs )[ DEFAULT_TOOL_OUTPUT ][ DEFAULT_EXTRA_NAME ]
@@ -122,6 +193,12 @@
job_working_directory = self.test_directory
return self.tool.collect_primary_datasets( self.outputs, job_working_directory )
+ def _replace_output_collectors( self, xml_str ):
+ # Rewrite tool as if it had been created with output containing
+ # supplied dataset_collector elem.
+ elem = util.parse_xml_string( xml_str )
+ self.tool.outputs[ DEFAULT_TOOL_OUTPUT ].dataset_collectors = output_collect.dataset_collectors_from_elem( elem )
+
def _append_job_json( self, object, output_path=None, line_type="new_primary_dataset" ):
object[ "type" ] = line_type
if output_path:
@@ -133,7 +210,8 @@
def _setup_extra_file( self, **kwargs ):
path = kwargs.get( "path", None )
- if not path:
+ filename = kwargs.get( "filename", None )
+ if not path and not filename:
name = kwargs.get( "name", DEFAULT_EXTRA_NAME )
visible = kwargs.get( "visible", "visible" )
ext = kwargs.get( "ext", "data" )
@@ -142,6 +220,13 @@
path = os.path.join( directory, "primary_%s_%s_%s_%s" % template_args )
if "dbkey" in kwargs:
path = "%s_%s" % ( path, kwargs[ "dbkey" ] )
+ if not path:
+ assert filename
+ subdir = kwargs.get( "subdir", "." )
+ path = os.path.join( self.test_directory, subdir, filename )
+ directory = os.path.dirname( path )
+ if not os.path.exists( directory ):
+ os.makedirs( directory )
contents = kwargs.get( "contents", "test contents" )
open( path, "w" ).write( contents )
return path
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Charts: Fixes for heatmaps
by commits-noreply@bitbucket.org 05 May '14
by commits-noreply@bitbucket.org 05 May '14
05 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/74b6e23ed788/
Changeset: 74b6e23ed788
User: guerler
Date: 2014-05-05 22:02:16
Summary: Charts: Fixes for heatmaps
Affected #: 3 files
diff -r c69894bb9855d38560eb9a55eaaedcd150930f10 -r 74b6e23ed7882f3c091d2b66ce85025241372017 config/plugins/visualizations/charts/static/charts/heatmap/config.js
--- a/config/plugins/visualizations/charts/static/charts/heatmap/config.js
+++ b/config/plugins/visualizations/charts/static/charts/heatmap/config.js
@@ -1,10 +1,12 @@
define([], function() {
return {
- title : 'Heatmap',
- library : '',
- tag : 'div',
+ title : 'Heatmap',
+ library : '',
+ tag : 'div',
use_panels : true,
+
+ // columns
columns : {
col_label : {
title : 'Columns',
@@ -19,6 +21,7 @@
},
},
+ // settings
settings: {
color_set : {
title : 'Color scheme',
@@ -107,6 +110,38 @@
value : 'wysiwyg'
}
]
+ },
+
+ sorting : {
+ title : 'Sorting',
+ info : 'How should the columns be clustered?',
+ type : 'select',
+ init : 'hclust',
+ data : [
+ {
+ label : 'Read from dataset',
+ value : 'hclust'
+ },
+ {
+ label : 'Sort column and row labels',
+ value : 'byboth'
+ },
+ {
+ label : 'Sort column labels',
+ value : 'bycolumns'
+ },
+ {
+ label : 'Sort by rows',
+ value : 'byrow'
+ }
+ ]
+ }
+ },
+
+ // menu definition
+ menu : function() {
+ return {
+ color_set : this.settings.color_set
}
}
};
diff -r c69894bb9855d38560eb9a55eaaedcd150930f10 -r 74b6e23ed7882f3c091d2b66ce85025241372017 config/plugins/visualizations/charts/static/charts/heatmap/heatmap-plugin.js
--- a/config/plugins/visualizations/charts/static/charts/heatmap/heatmap-plugin.js
+++ b/config/plugins/visualizations/charts/static/charts/heatmap/heatmap-plugin.js
@@ -180,26 +180,22 @@
//
// add ui elements
//
- // create ui elements
+ // create tooltip
this.$tooltip = $(this._templateTooltip());
- this.$select = $(this._templateSelect());
-
- // append
this.$el.append(this.$tooltip);
- this.$el.append(this.$select);
-
- // add event to select field
- this.$select.on('change', function(){
- self._sortByOrder(this.value);
- });
//
// finally draw the heatmap
//
- this._draw();
+ this._build();
+
+ // catch window resize event
+ $(window).resize(function () {
+ self._build();
+ });
},
- _draw: function() {
+ _build: function() {
// link this
var self = this;
@@ -212,7 +208,7 @@
this.height = this.heightContainer;
// calculate cell size
- this.cellSize = Math.min(((this.height - 50) / (this.rowNumber + this.margin.top + this.margin.bottom)),
+ this.cellSize = Math.min(((this.height) / (this.rowNumber + this.margin.top + this.margin.bottom)),
(this.width / (this.colNumber + this.margin.left + this.margin.right)));
// set font size
@@ -227,22 +223,27 @@
var width = this.width;
var height = this.height;
+ // reset svg
+ if (this.svg !== undefined) {
+ this.$el.find('svg').remove();
+ }
+
// add main group and translate
this.svg = d3.select(this.$el[0]).append('svg')
.append('g')
.attr('transform', 'translate(' + (this.widthContainer - width) / 2 + ',' +
- (this.heightContainer - height) / 2 + ')')
-
+ (this.heightContainer - height) / 2 + ')');
+
// reset sorting
this.rowSortOrder = false;
this.colSortOrder = false;
// build
- this._buildRowLabels();
- this._buildColLabels();
- this._buildHeatMap();
- this._buildLegend();
- this._buildTitle();
+ this.d3RowLabels = this._buildRowLabels();
+ this.d3ColLabels = this._buildColLabels();
+ this.d3HeatMap = this._buildHeatMap();
+ this.d3Legend = this._buildLegend();
+ this.d3Title = this._buildTitle();
},
// build title
@@ -258,7 +259,7 @@
var title = this.options.title;
// add title
- this.svg.append('g')
+ return this.svg.append('g')
.append('text')
.attr('x', width / 2)
.attr('y', height + 3 * cellSize + fontSize + 3)
@@ -323,6 +324,9 @@
})
.attr('y', height + cellSize - 3)
.style('font-size', fontSize + 'px');
+
+ // return
+ return legend;
},
// build column labels
@@ -366,6 +370,9 @@
self._sortByLabel('c', 'row', self.rowNumber, i, self.colSortOrder);
d3.select('#order').property('selectedIndex', 4).node().focus();
});
+
+ // return
+ return colLabels;
},
// build row labels
@@ -409,6 +416,9 @@
self._sortByLabel('r', 'col', self.colNumber, i, self.rowSortOrder);
d3.select('#order').property('selectedIndex', 4).node().focus();
});
+
+ // return
+ return rowLabels;
},
// build heat map
@@ -424,7 +434,7 @@
var colLabel = this.colLabel;
// heat map
- var heatMap = this.svg.append('g').attr('class','g3')
+ var heatmap = this.svg.append('g').attr('class','g3')
.selectAll('.cellg')
.data(self.data, function(d) {
return d.row + ':' + d.col;
@@ -466,6 +476,9 @@
d3.selectAll('.colLabel').classed('text-highlight',false);
d3.select('#heatmap-tooltip').classed('hidden', true);
});
+
+ // return
+ return heatmap;
},
// change ordering of cells
diff -r c69894bb9855d38560eb9a55eaaedcd150930f10 -r 74b6e23ed7882f3c091d2b66ce85025241372017 config/plugins/visualizations/charts/static/views/viewport.js
--- a/config/plugins/visualizations/charts/static/views/viewport.js
+++ b/config/plugins/visualizations/charts/static/views/viewport.js
@@ -6,7 +6,8 @@
return Backbone.View.extend({
// list of canvas elements
- canvas: [],
+ container_list: [],
+ canvas_list: [],
// initialize
initialize: function(app, options) {
@@ -26,7 +27,7 @@
this._fullscreen(this.$el, 80);
// create canvas element
- this._createCanvas('div');
+ this._createContainer('div');
// events
var self = this;
@@ -38,6 +39,7 @@
this.chart.on('set:state', function() {
// get info element
var $info = self.$el.find('#info');
+ var $container = self.$el.find('container');
// get icon
var $icon = $info.find('#icon');
@@ -49,11 +51,15 @@
$info.show();
$info.find('#text').html(self.chart.get('state_info'));
+ // hide containers
+ $container.hide();
+
// check status
var state = self.chart.get('state');
switch (state) {
case 'ok':
$info.hide();
+ $container.show()
break;
case 'failed':
$icon.addClass('fa fa-warning');
@@ -86,29 +92,35 @@
},
// creates n canvas elements
- _createCanvas: function(tag, n) {
+ _createContainer: function(tag, n) {
// check size of requested canvas elements
n = n || 1;
// clear previous canvas elements
- for (var i in this.canvas) {
- this.canvas[i].remove();
- this.canvas.slice(i, 0);
+ for (var i in this.container_list) {
+ this.container_list[i].remove();
}
+ // reset lists
+ this.container_list = [];
+ this.canvas_list = [];
+
// create requested canvas elements
for (var i = 0; i < n; i++) {
// create element
- var canvas_el = $(this._templateCanvas(tag, parseInt(100 / n)));
+ var canvas_el = $(this._templateContainer(tag, parseInt(100 / n)));
// add to view
this.$el.append(canvas_el);
- // find canvas element
+ // add to list
+ this.container_list[i] = canvas_el;
+
+ // add a separate list for canvas elements
if (tag == 'svg') {
- this.canvas[i] = d3.select(canvas_el[0]);
+ this.canvas_list[i] = d3.select(canvas_el.find('#canvas')[0]);
} else {
- this.canvas[i] = canvas_el;
+ this.canvas_list[i] = canvas_el.find('#canvas');
}
}
},
@@ -137,7 +149,7 @@
}
// create canvas element and add to canvas list
- this._createCanvas(this.chart_settings.tag, n_panels);
+ this._createContainer(this.chart_settings.tag, n_panels);
// set chart state
chart.state('wait', 'Please wait...');
@@ -145,6 +157,7 @@
// clean up data if there is any from previous jobs
if (!this.chart_settings.execute ||
(this.chart_settings.execute && chart.get('modified'))) {
+
// reset jobs
this.app.jobs.cleanup(chart);
@@ -156,7 +169,7 @@
var self = this;
require(['plugin/charts/' + chart_type + '/' + chart_type], function(ChartView) {
// create chart
- var view = new ChartView(self.app, {canvas : self.canvas});
+ var view = new ChartView(self.app, {canvas : self.canvas_list});
// request data
if (self.chart_settings.execute) {
@@ -269,8 +282,11 @@
},
// template svg/div element
- _templateCanvas: function(tag, width) {
- return '<' + tag + ' class="canvas" style="float: left; display: block; width:' + width + '%; height: 100%;"/>';
+ _templateContainer: function(tag, width) {
+ return '<div class="container" style="float: left; display: block; width:' + width + '%; height: 100%;">' +
+ '<div id="menu"/>' +
+ '<' + tag + ' id="canvas" class="canvas" style="display: block; width:100%; height: inherit;">' +
+ '</div>';
}
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: martenson: data libraries: when importing into history set it as current and provide link to the 'Analyze page' so users can switch quickly
by commits-noreply@bitbucket.org 05 May '14
by commits-noreply@bitbucket.org 05 May '14
05 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c69894bb9855/
Changeset: c69894bb9855
User: martenson
Date: 2014-05-05 19:51:13
Summary: data libraries: when importing into history set it as current and provide link to the 'Analyze page' so users can switch quickly
Affected #: 4 files
diff -r 24834f127f4cced95f0a64dd5a7ccf72a3f18134 -r c69894bb9855d38560eb9a55eaaedcd150930f10 static/scripts/mvc/library/library-folderrow-view.js
--- a/static/scripts/mvc/library/library-folderrow-view.js
+++ b/static/scripts/mvc/library/library-folderrow-view.js
@@ -183,10 +183,18 @@
var self = this;
historyItem.url = historyItem.urlRoot + history_id + '/contents';
+ // set the used history as current so user will see the last one
+ // that he imported into in the history panel on the 'analysis' page
+ var set_current_url = '/api/histories/' + history_id + '/set_as_current';
+ $.ajax({
+ url: set_current_url,
+ type: 'PUT'
+ });
+
// save the dataset into selected history
historyItem.save({ content : library_dataset_id, source : 'library' }, {
success : function(){
- mod_toastr.success('Dataset imported');
+ mod_toastr.success('Dataset imported. Click this to start analysing it.', '', {onclick: function() {window.location='/'}});
//enable the buttons
self.modal.enableButton('Import');
self.modal.enableButton('Download');
diff -r 24834f127f4cced95f0a64dd5a7ccf72a3f18134 -r c69894bb9855d38560eb9a55eaaedcd150930f10 static/scripts/mvc/library/library-foldertoolbar-view.js
--- a/static/scripts/mvc/library/library-foldertoolbar-view.js
+++ b/static/scripts/mvc/library/library-foldertoolbar-view.js
@@ -222,6 +222,14 @@
datasets_to_import.push(historyItem);
}
this.options.chain_call_control.total_number = datasets_to_import.length;
+
+ // set the used history as current so user will see the last one
+ // that he imported into in the history panel on the 'analysis' page
+ var set_current_url = '/api/histories/' + history_id + '/set_as_current';
+ $.ajax({
+ url: set_current_url,
+ type: 'PUT'
+ });
// call the recursive function to call ajax one after each other (request FIFO queue)
this.chainCall(datasets_to_import, history_name);
},
@@ -231,11 +239,11 @@
var popped_item = history_item_set.pop();
if (typeof popped_item === "undefined") {
if (this.options.chain_call_control.failed_number === 0){
- mod_toastr.success('Selected datasets imported into history');
+ mod_toastr.success('Selected datasets imported into history. Click this to start analysing it.', '', {onclick: function() {window.location='/'}});
} else if (this.options.chain_call_control.failed_number === this.options.chain_call_control.total_number){
mod_toastr.error('There was an error and no datasets were imported into history.');
} else if (this.options.chain_call_control.failed_number < this.options.chain_call_control.total_number){
- mod_toastr.warning('Some of the datasets could not be imported into history');
+ mod_toastr.warning('Some of the datasets could not be imported into history. Click this to see what was imported.', '', {onclick: function() {window.location='/'}});
}
Galaxy.modal.hide();
return;
diff -r 24834f127f4cced95f0a64dd5a7ccf72a3f18134 -r c69894bb9855d38560eb9a55eaaedcd150930f10 static/scripts/packed/mvc/library/library-folderrow-view.js
--- a/static/scripts/packed/mvc/library/library-folderrow-view.js
+++ b/static/scripts/packed/mvc/library/library-folderrow-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .undelete_dataset_btn":"undelete_dataset"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";if(f.get("deleted")){g=this.templateRowDeletedFile()}else{g=this.templateRowFile()}}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(){var i=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=i;var f=this;h.fetch({success:function(j){g.fetch({success:function(k){f.renderModalAfterFetch(j,k)},error:function(l,k){if(typeof k.responseJSON!=="undefined"){e.error(k.responseJSON.err_msg)}else{e.error("An error occured during fetching histories:(")}f.renderModalAfterFetch(j)}})},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error(j.responseJSON.err_msg)}else{e.error("An error occured during loading dataset details :(")}}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:k.get("name"),body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var h=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=h;var f=$("#id_row").attr("data-id");var i=new c.HistoryItem();var g=this;i.url=i.urlRoot+h+"/contents";i.save({content:f,source:"library"},{success:function(){e.success("Dataset imported");g.modal.enableButton("Import");g.modal.enableButton("Download")},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error("Dataset not imported. "+j.responseJSON.err_msg)}else{e.error("An error occured! Dataset not imported. Please try again.")}g.modal.enableButton("Import");g.modal.enableButton("Download")}})},undelete_dataset:function(g){$(".tooltip").hide();var f=$(g.target).closest("tr")[0].id;var h=Galaxy.libraries.folderListView.collection.get(f);h.url=h.urlRoot+h.id+"?undelete=true";h.destroy({success:function(j,i){Galaxy.libraries.folderListView.collection.remove(f);var k=new c.Item(i);Galaxy.libraries.folderListView.collection.add(k);e.success("Dataset undeleted")},error:function(j,i){if(typeof i.responseJSON!=="undefined"){e.error("Dataset was not undeleted. "+i.responseJSON.err_msg)}else{e.error("An error occured! Dataset was not undeleted. Please try again.")}}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>');tmpl_array.push(" <span>(empty folder)</span>");tmpl_array.push(" <% } %>");tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowDeletedFile:function(){tmpl_array=[];tmpl_array.push('<tr class="active deleted_dataset" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span></td>');tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(' <td class="right-center"><button data-toggle="tooltip" data-placement="top" title="Undelete <%- content_item.get("name") %>" class="primary-button btn-xs undelete_dataset_btn show_on_hover" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")}});return{FolderRowView:a}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .undelete_dataset_btn":"undelete_dataset"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";if(f.get("deleted")){g=this.templateRowDeletedFile()}else{g=this.templateRowFile()}}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(){var i=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=i;var f=this;h.fetch({success:function(j){g.fetch({success:function(k){f.renderModalAfterFetch(j,k)},error:function(l,k){if(typeof k.responseJSON!=="undefined"){e.error(k.responseJSON.err_msg)}else{e.error("An error occured during fetching histories:(")}f.renderModalAfterFetch(j)}})},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error(j.responseJSON.err_msg)}else{e.error("An error occured during loading dataset details :(")}}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:k.get("name"),body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var i=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=i;var g=$("#id_row").attr("data-id");var j=new c.HistoryItem();var h=this;j.url=j.urlRoot+i+"/contents";var f="/api/histories/"+i+"/set_as_current";$.ajax({url:f,type:"PUT"});j.save({content:g,source:"library"},{success:function(){e.success("Dataset imported. Click this to start analysing it.","",{onclick:function(){window.location="/"}});h.modal.enableButton("Import");h.modal.enableButton("Download")},error:function(l,k){if(typeof k.responseJSON!=="undefined"){e.error("Dataset not imported. "+k.responseJSON.err_msg)}else{e.error("An error occured! Dataset not imported. Please try again.")}h.modal.enableButton("Import");h.modal.enableButton("Download")}})},undelete_dataset:function(g){$(".tooltip").hide();var f=$(g.target).closest("tr")[0].id;var h=Galaxy.libraries.folderListView.collection.get(f);h.url=h.urlRoot+h.id+"?undelete=true";h.destroy({success:function(j,i){Galaxy.libraries.folderListView.collection.remove(f);var k=new c.Item(i);Galaxy.libraries.folderListView.collection.add(k);e.success("Dataset undeleted")},error:function(j,i){if(typeof i.responseJSON!=="undefined"){e.error("Dataset was not undeleted. "+i.responseJSON.err_msg)}else{e.error("An error occured! Dataset was not undeleted. Please try again.")}}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>');tmpl_array.push(" <span>(empty folder)</span>");tmpl_array.push(" <% } %>");tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowDeletedFile:function(){tmpl_array=[];tmpl_array.push('<tr class="active deleted_dataset" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span></td>');tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(' <td class="right-center"><button data-toggle="tooltip" data-placement="top" title="Undelete <%- content_item.get("name") %>" class="primary-button btn-xs undelete_dataset_btn show_on_hover" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")}});return{FolderRowView:a}});
\ No newline at end of file
diff -r 24834f127f4cced95f0a64dd5a7ccf72a3f18134 -r c69894bb9855d38560eb9a55eaaedcd150930f10 static/scripts/packed/mvc/library/library-foldertoolbar-view.js
--- a/static/scripts/packed/mvc/library/library-foldertoolbar-view.js
+++ b/static/scripts/packed/mvc/library/library-foldertoolbar-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({el:"#center",events:{"click #toolbtn_create_folder":"createFolderFromModal","click #toolbtn_bulk_import":"modalBulkImport","click .toolbtn_add_files":"addFilesToFolderModal","click #include_deleted_datasets_chk":"checkIncludeDeleted","click #toolbtn_bulk_delete":"deleteSelectedDatasets"},defaults:{can_add_library_item:false,contains_file:false,chain_call_control:{total_number:0,failed_number:0}},modal:null,histories:null,initialize:function(f){this.options=_.defaults(f||{},this.defaults);this.render()},render:function(g){this.options=_.extend(this.options,g);var i=false;var f=true;if(Galaxy.currUser){i=Galaxy.currUser.isAdmin();f=Galaxy.currUser.isAnonymous()}var h=this.templateToolBar();this.$el.html(h({id:this.options.id,admin_user:i,anonym:f}))},configureElements:function(f){this.options=_.extend(this.options,f);if(this.options.can_add_library_item===true){$(".add-library-items").show()}else{$(".add-library-items").hide()}if(this.options.contains_file===true){if(Galaxy.currUser){if(!Galaxy.currUser.isAnonymous()){$(".logged-dataset-manipulation").show();$(".dataset-manipulation").show()}else{$(".dataset-manipulation").show();$(".logged-dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}this.$el.find("[data-toggle]").tooltip()},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;var g=this.templateNewFolderInModal();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:g(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){Galaxy.modal.hide()}}})},create_new_folder_event:function(){var f=this.serialize_new_folder();if(this.validate_new_folder(f)){var g=new c.FolderAsModel();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];g.url=g.urlRoot+"/"+current_folder_id;g.save(f,{success:function(h){Galaxy.modal.hide();e.success("Folder created");h.set({type:"folder"});Galaxy.libraries.folderListView.collection.add(h)},error:function(i,h){Galaxy.modal.hide();if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})}else{e.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""},modalBulkImport:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{this.refreshUserHistoriesList(function(g){var h=g.templateBulkImportInModal();g.modal=Galaxy.modal;g.modal.show({closing_events:true,title:"Import into History",body:h({histories:g.histories.models}),buttons:{Import:function(){g.importAllIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})}},refreshUserHistoriesList:function(g){var f=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){g(f)},error:function(i,h){if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})},importAllIntoHistory:function(){this.modal.disableButton("Import");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var j=$("select[name=dataset_import_bulk] option:selected").val();this.options.last_used_history_id=j;var m=$("select[name=dataset_import_bulk] option:selected").text();var o=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){o.push(this.parentElement.parentElement.id)}});var n=this.templateImportIntoHistoryProgressBar();this.modal.$el.find(".modal-body").html(n({history_name:m}));var k=100/o.length;this.initProgress(k);var f=[];for(var g=o.length-1;g>=0;g--){var h=o[g];var l=new c.HistoryItem();l.url=l.urlRoot+j+"/contents";l.content=h;l.source="library";f.push(l)}this.options.chain_call_control.total_number=f.length;this.chainCall(f,m)},chainCall:function(g,j){var f=this;var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets imported into history")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were imported into history.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be imported into history")}}}Galaxy.modal.hide();return}var i=$.when(h.save({content:h.content,source:h.source}));i.done(function(){f.updateProgress();f.chainCall(g,j)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCall(g,j)})},initProgress:function(f){this.progress=0;this.progressStep=f},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(f,j){var h=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){h.push(this.parentElement.parentElement.id)}});var g="/api/libraries/datasets/download/"+j;var i={ldda_ids:h};this.processDownload(g,i,"get")},processDownload:function(g,h,i){if(g&&h){h=typeof h==="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},addFilesToFolderModal:function(){this.refreshUserHistoriesList(function(f){f.modal=Galaxy.modal;var g=f.templateAddFilesInModal();f.modal.show({closing_events:true,title:"Add datasets from history to "+f.options.folder_name,body:g({histories:f.histories.models}),buttons:{Add:function(){f.addAllDatasetsFromHistory()},Close:function(){Galaxy.modal.hide()}}});if(f.histories.models.length>0){f.fetchAndDisplayHistoryContents(f.histories.models[0].id);$("#dataset_add_bulk").change(function(h){f.fetchAndDisplayHistoryContents(h.target.value)})}else{e.error("An error ocurred :(")}})},fetchAndDisplayHistoryContents:function(h){var g=new c.HistoryContents({id:h});var f=this;g.fetch({success:function(j){var i=f.templateHistoryContents();f.histories.get(h).set({contents:j});f.modal.$el.find("#selected_history_content").html(i({history_contents:j.models.reverse()}))},error:function(){e.error("An error ocurred :(")}})},addAllDatasetsFromHistory:function(){this.modal.disableButton("Add");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var f=[];this.modal.$el.find("#selected_history_content").find(":checked").each(function(){var i=$(this.parentElement).data("id");if(i){f.push(i)}});var l=this.options.folder_name;var k=this.templateAddingDatasetsProgressBar();this.modal.$el.find(".modal-body").html(k({folder_name:l}));this.progressStep=100/f.length;this.progress=0;var j=[];for(var h=f.length-1;h>=0;h--){history_dataset_id=f[h];var g=new c.Item();g.url="/api/folders/"+this.options.id+"/contents";g.set({from_hda_id:history_dataset_id});j.push(g)}this.options.chain_call_control.total_number=j.length;this.chainCallAddingHdas(j)},chainCallAddingHdas:function(g){var f=this;this.added_hdas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets from history added to the folder")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were added to the folder.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be added to the folder")}}}Galaxy.modal.hide();return this.added_hdas}var i=$.when(h.save({from_hda_id:h.get("from_hda_id")}));i.done(function(j){Galaxy.libraries.folderListView.collection.add(j);f.updateProgress();f.chainCallAddingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallAddingHdas(g)})},checkIncludeDeleted:function(f){if(f.target.checked){Galaxy.libraries.folderListView.fetchFolder({include_deleted:true})}else{Galaxy.libraries.folderListView.fetchFolder({include_deleted:false})}},deleteSelectedDatasets:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{var j=this.templateDeletingDatasetsProgressBar();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Deleting selected datasets",body:j({}),buttons:{Close:function(){Galaxy.modal.hide()}}});this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var g=[];f.each(function(){if(this.parentElement.parentElement.id!==""){g.push(this.parentElement.parentElement.id)}});this.progressStep=100/g.length;this.progress=0;var l=[];for(var h=g.length-1;h>=0;h--){var k=new c.Item({id:g[h]});l.push(k)}this.options.chain_call_control.total_number=g.length;this.chainCallDeletingHdas(l)}},chainCallDeletingHdas:function(g){var f=this;this.deleted_lddas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets deleted")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were deleted.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be deleted")}}}Galaxy.modal.hide();return this.deleted_lddas}var i=$.when(h.destroy());i.done(function(k){Galaxy.libraries.folderListView.collection.remove(h.id);f.updateProgress();if(Galaxy.libraries.folderListView.options.include_deleted){var j=new c.Item(k);Galaxy.libraries.folderListView.collection.add(j)}f.chainCallDeletingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallDeletingHdas(g)})},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push('<div id="library_folder_toolbar">');tmpl_array.push('<span data-toggle="tooltip" data-placement="top" class="logged-dataset-manipulation" title="Include deleted datasets" style="display:none;"><input id="include_deleted_datasets_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push('<div class="btn-group add-library-items" style="display:none;">');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="btn btn-default primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="btn btn-default toolbtn_add_files primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');tmpl_array.push("</div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button dataset-manipulation" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to history</button>');tmpl_array.push(' <div id="toolbtn_dl" class="btn-group dataset-manipulation" style="margin-left: 0.5em; display:none; ">');tmpl_array.push(' <button title="Download selected datasets as archive" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');tmpl_array.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');tmpl_array.push(" </button>");tmpl_array.push(' <ul class="dropdown-menu" role="menu">');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');tmpl_array.push(" </ul>");tmpl_array.push(" </div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Mark selected datasets deleted" id="toolbtn_bulk_delete" class="primary-button logged-dataset-manipulation" style="margin-left: 0.5em; display:none; " type="button"><span class="fa fa-times"></span> delete</button>');tmpl_array.push(" </div>");tmpl_array.push(' <div id="folder_items_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_modal">');tmpl_array.push("<form>");tmpl_array.push('<input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push('<input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push("</form>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateBulkImportInModal:function(){var f=[];f.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return _.template(f.join(""))},templateImportIntoHistoryProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Adding selected datasets from history to library folder <b><%= _.escape(folder_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateDeletingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-delete" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddFilesInModal:function(){var f=[];f.push('<div id="add_files_modal">');f.push('<div id="history_modal_combo_bulk">');f.push("Select history: ");f.push('<select id="dataset_add_bulk" name="dataset_add_bulk" style="width:66%; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</div>");f.push('<div id="selected_history_content">');f.push("</div>");f.push("</div>");return _.template(f.join(""))},templateHistoryContents:function(){var f=[];f.push("Choose the datasets to import:");f.push("<ul>");f.push(" <% _.each(history_contents, function(history_item) { %>");f.push(' <li data-id="<%= _.escape(history_item.get("id")) %>">');f.push(' <input style="margin: 0;" type="checkbox"><%= _.escape(history_item.get("hid")) %>: <%= _.escape(history_item.get("name")) %>');f.push(" </li>");f.push(" <% }); %>");f.push("</ul>");return _.template(f.join(""))}});return{FolderToolbarView:a}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({el:"#center",events:{"click #toolbtn_create_folder":"createFolderFromModal","click #toolbtn_bulk_import":"modalBulkImport","click .toolbtn_add_files":"addFilesToFolderModal","click #include_deleted_datasets_chk":"checkIncludeDeleted","click #toolbtn_bulk_delete":"deleteSelectedDatasets"},defaults:{can_add_library_item:false,contains_file:false,chain_call_control:{total_number:0,failed_number:0}},modal:null,histories:null,initialize:function(f){this.options=_.defaults(f||{},this.defaults);this.render()},render:function(g){this.options=_.extend(this.options,g);var i=false;var f=true;if(Galaxy.currUser){i=Galaxy.currUser.isAdmin();f=Galaxy.currUser.isAnonymous()}var h=this.templateToolBar();this.$el.html(h({id:this.options.id,admin_user:i,anonym:f}))},configureElements:function(f){this.options=_.extend(this.options,f);if(this.options.can_add_library_item===true){$(".add-library-items").show()}else{$(".add-library-items").hide()}if(this.options.contains_file===true){if(Galaxy.currUser){if(!Galaxy.currUser.isAnonymous()){$(".logged-dataset-manipulation").show();$(".dataset-manipulation").show()}else{$(".dataset-manipulation").show();$(".logged-dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}this.$el.find("[data-toggle]").tooltip()},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;var g=this.templateNewFolderInModal();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:g(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){Galaxy.modal.hide()}}})},create_new_folder_event:function(){var f=this.serialize_new_folder();if(this.validate_new_folder(f)){var g=new c.FolderAsModel();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];g.url=g.urlRoot+"/"+current_folder_id;g.save(f,{success:function(h){Galaxy.modal.hide();e.success("Folder created");h.set({type:"folder"});Galaxy.libraries.folderListView.collection.add(h)},error:function(i,h){Galaxy.modal.hide();if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})}else{e.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""},modalBulkImport:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{this.refreshUserHistoriesList(function(g){var h=g.templateBulkImportInModal();g.modal=Galaxy.modal;g.modal.show({closing_events:true,title:"Import into History",body:h({histories:g.histories.models}),buttons:{Import:function(){g.importAllIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})}},refreshUserHistoriesList:function(g){var f=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){g(f)},error:function(i,h){if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})},importAllIntoHistory:function(){this.modal.disableButton("Import");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var k=$("select[name=dataset_import_bulk] option:selected").val();this.options.last_used_history_id=k;var n=$("select[name=dataset_import_bulk] option:selected").text();var p=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){p.push(this.parentElement.parentElement.id)}});var o=this.templateImportIntoHistoryProgressBar();this.modal.$el.find(".modal-body").html(o({history_name:n}));var l=100/p.length;this.initProgress(l);var f=[];for(var h=p.length-1;h>=0;h--){var j=p[h];var m=new c.HistoryItem();m.url=m.urlRoot+k+"/contents";m.content=j;m.source="library";f.push(m)}this.options.chain_call_control.total_number=f.length;var g="/api/histories/"+k+"/set_as_current";$.ajax({url:g,type:"PUT"});this.chainCall(f,n)},chainCall:function(g,j){var f=this;var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets imported into history. Click this to start analysing it.","",{onclick:function(){window.location="/"}})}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were imported into history.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be imported into history. Click this to see what was imported.","",{onclick:function(){window.location="/"}})}}}Galaxy.modal.hide();return}var i=$.when(h.save({content:h.content,source:h.source}));i.done(function(){f.updateProgress();f.chainCall(g,j)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCall(g,j)})},initProgress:function(f){this.progress=0;this.progressStep=f},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(f,j){var h=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){h.push(this.parentElement.parentElement.id)}});var g="/api/libraries/datasets/download/"+j;var i={ldda_ids:h};this.processDownload(g,i,"get")},processDownload:function(g,h,i){if(g&&h){h=typeof h==="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},addFilesToFolderModal:function(){this.refreshUserHistoriesList(function(f){f.modal=Galaxy.modal;var g=f.templateAddFilesInModal();f.modal.show({closing_events:true,title:"Add datasets from history to "+f.options.folder_name,body:g({histories:f.histories.models}),buttons:{Add:function(){f.addAllDatasetsFromHistory()},Close:function(){Galaxy.modal.hide()}}});if(f.histories.models.length>0){f.fetchAndDisplayHistoryContents(f.histories.models[0].id);$("#dataset_add_bulk").change(function(h){f.fetchAndDisplayHistoryContents(h.target.value)})}else{e.error("An error ocurred :(")}})},fetchAndDisplayHistoryContents:function(h){var g=new c.HistoryContents({id:h});var f=this;g.fetch({success:function(j){var i=f.templateHistoryContents();f.histories.get(h).set({contents:j});f.modal.$el.find("#selected_history_content").html(i({history_contents:j.models.reverse()}))},error:function(){e.error("An error ocurred :(")}})},addAllDatasetsFromHistory:function(){this.modal.disableButton("Add");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var f=[];this.modal.$el.find("#selected_history_content").find(":checked").each(function(){var i=$(this.parentElement).data("id");if(i){f.push(i)}});var l=this.options.folder_name;var k=this.templateAddingDatasetsProgressBar();this.modal.$el.find(".modal-body").html(k({folder_name:l}));this.progressStep=100/f.length;this.progress=0;var j=[];for(var h=f.length-1;h>=0;h--){history_dataset_id=f[h];var g=new c.Item();g.url="/api/folders/"+this.options.id+"/contents";g.set({from_hda_id:history_dataset_id});j.push(g)}this.options.chain_call_control.total_number=j.length;this.chainCallAddingHdas(j)},chainCallAddingHdas:function(g){var f=this;this.added_hdas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets from history added to the folder")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were added to the folder.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be added to the folder")}}}Galaxy.modal.hide();return this.added_hdas}var i=$.when(h.save({from_hda_id:h.get("from_hda_id")}));i.done(function(j){Galaxy.libraries.folderListView.collection.add(j);f.updateProgress();f.chainCallAddingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallAddingHdas(g)})},checkIncludeDeleted:function(f){if(f.target.checked){Galaxy.libraries.folderListView.fetchFolder({include_deleted:true})}else{Galaxy.libraries.folderListView.fetchFolder({include_deleted:false})}},deleteSelectedDatasets:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{var j=this.templateDeletingDatasetsProgressBar();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Deleting selected datasets",body:j({}),buttons:{Close:function(){Galaxy.modal.hide()}}});this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var g=[];f.each(function(){if(this.parentElement.parentElement.id!==""){g.push(this.parentElement.parentElement.id)}});this.progressStep=100/g.length;this.progress=0;var l=[];for(var h=g.length-1;h>=0;h--){var k=new c.Item({id:g[h]});l.push(k)}this.options.chain_call_control.total_number=g.length;this.chainCallDeletingHdas(l)}},chainCallDeletingHdas:function(g){var f=this;this.deleted_lddas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets deleted")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were deleted.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be deleted")}}}Galaxy.modal.hide();return this.deleted_lddas}var i=$.when(h.destroy());i.done(function(k){Galaxy.libraries.folderListView.collection.remove(h.id);f.updateProgress();if(Galaxy.libraries.folderListView.options.include_deleted){var j=new c.Item(k);Galaxy.libraries.folderListView.collection.add(j)}f.chainCallDeletingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallDeletingHdas(g)})},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push('<div id="library_folder_toolbar">');tmpl_array.push('<span data-toggle="tooltip" data-placement="top" class="logged-dataset-manipulation" title="Include deleted datasets" style="display:none;"><input id="include_deleted_datasets_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push('<div class="btn-group add-library-items" style="display:none;">');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="btn btn-default primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="btn btn-default toolbtn_add_files primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');tmpl_array.push("</div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button dataset-manipulation" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to history</button>');tmpl_array.push(' <div id="toolbtn_dl" class="btn-group dataset-manipulation" style="margin-left: 0.5em; display:none; ">');tmpl_array.push(' <button title="Download selected datasets as archive" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');tmpl_array.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');tmpl_array.push(" </button>");tmpl_array.push(' <ul class="dropdown-menu" role="menu">');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');tmpl_array.push(" </ul>");tmpl_array.push(" </div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Mark selected datasets deleted" id="toolbtn_bulk_delete" class="primary-button logged-dataset-manipulation" style="margin-left: 0.5em; display:none; " type="button"><span class="fa fa-times"></span> delete</button>');tmpl_array.push(" </div>");tmpl_array.push(' <div id="folder_items_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_modal">');tmpl_array.push("<form>");tmpl_array.push('<input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push('<input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push("</form>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateBulkImportInModal:function(){var f=[];f.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return _.template(f.join(""))},templateImportIntoHistoryProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Adding selected datasets from history to library folder <b><%= _.escape(folder_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateDeletingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-delete" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddFilesInModal:function(){var f=[];f.push('<div id="add_files_modal">');f.push('<div id="history_modal_combo_bulk">');f.push("Select history: ");f.push('<select id="dataset_add_bulk" name="dataset_add_bulk" style="width:66%; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</div>");f.push('<div id="selected_history_content">');f.push("</div>");f.push("</div>");return _.template(f.join(""))},templateHistoryContents:function(){var f=[];f.push("Choose the datasets to import:");f.push("<ul>");f.push(" <% _.each(history_contents, function(history_item) { %>");f.push(' <li data-id="<%= _.escape(history_item.get("id")) %>">');f.push(' <input style="margin: 0;" type="checkbox"><%= _.escape(history_item.get("hid")) %>: <%= _.escape(history_item.get("name")) %>');f.push(" </li>");f.push(" <% }); %>");f.push("</ul>");return _.template(f.join(""))}});return{FolderToolbarView: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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/aad9eb1a8486/
Changeset: aad9eb1a8486
User: carlfeberhard
Date: 2014-05-05 19:34:07
Summary: Fixes: correct docs in histories/set_as_current to PUT; use correct empty msg when removing the last hda view in a history; remove dependency on utils.js from ui-modal.js
Affected #: 6 files
diff -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 -r aad9eb1a8486211c2204452d466e5b811496f6e7 lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -121,7 +121,7 @@
def set_as_current( self, trans, id, **kwd ):
"""
set_as_current( trans, id, **kwd )
- * POST /api/histories/{id}/set_as_current:
+ * PUT /api/histories/{id}/set_as_current:
set the history with ``id`` to the user's current history and return details
:type id: an encoded id string
diff -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 -r aad9eb1a8486211c2204452d466e5b811496f6e7 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -165,7 +165,6 @@
parent_resources=dict( member_name='page', collection_name='pages' ) )
# add as a non-ATOM API call to support the notion of a 'current/working' history unique to the history resource
- #webapp.mapper.connect( "set_as_current", "/api/histories/set_as_current/{id}",
webapp.mapper.connect( "set_as_current", "/api/histories/{id}/set_as_current",
controller="histories", action="set_as_current", conditions=dict( method=["PUT"] ) )
diff -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 -r aad9eb1a8486211c2204452d466e5b811496f6e7 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -330,9 +330,8 @@
hdaView.remove();
delete panel.hdaViews[ hdaView.model.id ];
if( _.isEmpty( panel.hdaViews ) ){
- panel.$emptyMessage().fadeIn( panel.fxSpeed, function(){
- panel.trigger( 'empty-history', panel );
- });
+ panel.trigger( 'empty-history', panel );
+ panel._renderEmptyMsg();
}
});
},
diff -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 -r aad9eb1a8486211c2204452d466e5b811496f6e7 static/scripts/mvc/ui/ui-modal.js
--- a/static/scripts/mvc/ui/ui-modal.js
+++ b/static/scripts/mvc/ui/ui-modal.js
@@ -1,5 +1,4 @@
-// dependencies
-define(['utils/utils'], function(Utils) {
+define([], function() {
var View = Backbone.View.extend({
@@ -28,6 +27,7 @@
// adds and displays a new frame/window
show: function(options) {
+ console.debug( this );
// create
this.initialize(options);
diff -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 -r aad9eb1a8486211c2204452d466e5b811496f6e7 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/dataset/hda-model","mvc/dataset/hda-edit","mvc/history/readonly-history-panel","mvc/tags","mvc/annotations","utils/localization"],function(f,b,d,a,c,e){var g=d.ReadOnlyHistoryPanel.extend({HDAViewClass:b.HDAEditView,initialize:function(h){h=h||{};this.selectedHdaIds=[];this.tagsEditor=null;this.annotationEditor=null;this.purgeAllowed=h.purgeAllowed||false;this.selecting=h.selecting||false;this.annotationEditorShown=h.annotationEditorShown||false;this.tagsEditorShown=h.tagsEditorShown||false;d.ReadOnlyHistoryPanel.prototype.initialize.call(this,h)},_setUpModelEventHandlers:function(){d.ReadOnlyHistoryPanel.prototype._setUpModelEventHandlers.call(this);this.model.on("change:nice_size",this.updateHistoryDiskSize,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(h){this.model.fetch()},this)},renderModel:function(){var h=$("<div/>");h.append(g.templates.historyPanel(this.model.toJSON()));this.$emptyMessage(h).text(this.emptyMsg);if(Galaxy&&Galaxy.currUser&&Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(h);this._renderAnnotation(h)}h.find(".history-secondary-actions").prepend(this._renderSelectButton());h.find(".history-dataset-actions").toggle(this.selecting);h.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(h);this.renderHdas(h);return h},_renderTags:function(h){var i=this;this.tagsEditor=new a.TagsEditor({model:this.model,el:h.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.toggleHDATagEditors(true,i.fxSpeed)},onhide:function(){i.toggleHDATagEditors(false,i.fxSpeed)},$activator:faIconButton({title:e("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(h.find(".history-secondary-actions"))})},_renderAnnotation:function(h){var i=this;this.annotationEditor=new c.AnnotationEditor({model:this.model,el:h.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.toggleHDAAnnotationEditors(true,i.fxSpeed)},onhide:function(){i.toggleHDAAnnotationEditors(false,i.fxSpeed)},$activator:faIconButton({title:e("Edit history annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(h.find(".history-secondary-actions"))})},_renderSelectButton:function(h){return faIconButton({title:e("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(h){h=h||this.$el;d.ReadOnlyHistoryPanel.prototype._setUpBehaviours.call(this,h);if(!this.model){return}this._setUpDatasetActionsPopup(h);if((!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var i=this;h.find(".history-name").attr("title",e("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(j){var k=i.model.get("name");if(j&&j!==k){i.$el.find(".history-name").text(j);i.model.save({name:j}).fail(function(){i.$el.find(".history-name").text(i.model.previous("name"))})}else{i.$el.find(".history-name").text(k)}}})},_setUpDatasetActionsPopup:function(h){var i=this,j=[{html:e("Hide datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype.hide;i.getSelectedHdaCollection().ajaxQueue(k)}},{html:e("Unhide datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype.unhide;i.getSelectedHdaCollection().ajaxQueue(k)}},{html:e("Delete datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype["delete"];i.getSelectedHdaCollection().ajaxQueue(k)}},{html:e("Undelete datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype.undelete;i.getSelectedHdaCollection().ajaxQueue(k)}}];if(i.purgeAllowed){j.push({html:e("Permanently delete datasets"),func:function(){if(confirm(e("This will permanently remove the data in your datasets. Are you sure?"))){var k=f.HistoryDatasetAssociation.prototype.purge;i.getSelectedHdaCollection().ajaxQueue(k)}}})}return new PopupMenu(h.find(".history-dataset-action-popup-btn"),j)},_handleHdaDeletionChange:function(h){if(h.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[h.id])}},_handleHdaVisibleChange:function(h){if(h.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[h.id])}},_createHdaView:function(i){var h=i.get("id"),j=new this.HDAViewClass({model:i,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[h],selectable:this.selecting,purgeAllowed:this.purgeAllowed,hasUser:this.model.ownedByCurrUser(),logger:this.logger,tagsEditorShown:(this.tagsEditor&&!this.tagsEditor.hidden),annotationEditorShown:(this.annotationEditor&&!this.annotationEditor.hidden)});this._setUpHdaListeners(j);return j},_setUpHdaListeners:function(i){var h=this;d.ReadOnlyHistoryPanel.prototype._setUpHdaListeners.call(this,i);i.on("selected",function(j){var k=j.model.get("id");h.selectedHdaIds=_.union(h.selectedHdaIds,[k])});i.on("de-selected",function(j){var k=j.model.get("id");h.selectedHdaIds=_.without(h.selectedHdaIds,k)})},toggleHDATagEditors:function(h){var i=arguments;_.each(this.hdaViews,function(j){if(j.tagsEditor){j.tagsEditor.toggle.apply(j.tagsEditor,i)}})},toggleHDAAnnotationEditors:function(h){var i=arguments;_.each(this.hdaViews,function(j){if(j.annotationEditor){j.annotationEditor.toggle.apply(j.annotationEditor,i)}})},removeHdaView:function(i){if(!i){return}var h=this;i.$el.fadeOut(h.fxSpeed,function(){i.off();i.remove();delete h.hdaViews[i.model.id];if(_.isEmpty(h.hdaViews)){h.$emptyMessage().fadeIn(h.fxSpeed,function(){h.trigger("empty-history",h)})}})},events:_.extend(_.clone(d.ReadOnlyHistoryPanel.prototype.events),{"click .history-select-btn":"toggleSelectors","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"))},showSelectors:function(h){h=(h!==undefined)?(h):(this.fxSpeed);this.selecting=true;this.$(".history-dataset-actions").slideDown(h);_.each(this.hdaViews,function(i){i.showSelector()});this.selectedHdaIds=[]},hideSelectors:function(h){h=(h!==undefined)?(h):(this.fxSpeed);this.selecting=false;this.$(".history-dataset-actions").slideUp(h);_.each(this.hdaViews,function(i){i.hideSelector()});this.selectedHdaIds=[]},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAllDatasets:function(h){_.each(this.hdaViews,function(i){i.select(h)})},deselectAllDatasets:function(h){_.each(this.hdaViews,function(i){i.deselect(h)})},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(h){return h.selected})},getSelectedHdaCollection:function(){return new f.HDACollection(_.map(this.getSelectedHdaViews(),function(h){return h.model}),{historyId:this.model.id})},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{HistoryPanel:g}});
\ No newline at end of file
+define(["mvc/dataset/hda-model","mvc/dataset/hda-edit","mvc/history/readonly-history-panel","mvc/tags","mvc/annotations","utils/localization"],function(f,b,d,a,c,e){var g=d.ReadOnlyHistoryPanel.extend({HDAViewClass:b.HDAEditView,initialize:function(h){h=h||{};this.selectedHdaIds=[];this.tagsEditor=null;this.annotationEditor=null;this.purgeAllowed=h.purgeAllowed||false;this.selecting=h.selecting||false;this.annotationEditorShown=h.annotationEditorShown||false;this.tagsEditorShown=h.tagsEditorShown||false;d.ReadOnlyHistoryPanel.prototype.initialize.call(this,h)},_setUpModelEventHandlers:function(){d.ReadOnlyHistoryPanel.prototype._setUpModelEventHandlers.call(this);this.model.on("change:nice_size",this.updateHistoryDiskSize,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(h){this.model.fetch()},this)},renderModel:function(){var h=$("<div/>");h.append(g.templates.historyPanel(this.model.toJSON()));this.$emptyMessage(h).text(this.emptyMsg);if(Galaxy&&Galaxy.currUser&&Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(h);this._renderAnnotation(h)}h.find(".history-secondary-actions").prepend(this._renderSelectButton());h.find(".history-dataset-actions").toggle(this.selecting);h.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(h);this.renderHdas(h);return h},_renderTags:function(h){var i=this;this.tagsEditor=new a.TagsEditor({model:this.model,el:h.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.toggleHDATagEditors(true,i.fxSpeed)},onhide:function(){i.toggleHDATagEditors(false,i.fxSpeed)},$activator:faIconButton({title:e("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(h.find(".history-secondary-actions"))})},_renderAnnotation:function(h){var i=this;this.annotationEditor=new c.AnnotationEditor({model:this.model,el:h.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.toggleHDAAnnotationEditors(true,i.fxSpeed)},onhide:function(){i.toggleHDAAnnotationEditors(false,i.fxSpeed)},$activator:faIconButton({title:e("Edit history annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(h.find(".history-secondary-actions"))})},_renderSelectButton:function(h){return faIconButton({title:e("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(h){h=h||this.$el;d.ReadOnlyHistoryPanel.prototype._setUpBehaviours.call(this,h);if(!this.model){return}this._setUpDatasetActionsPopup(h);if((!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var i=this;h.find(".history-name").attr("title",e("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(j){var k=i.model.get("name");if(j&&j!==k){i.$el.find(".history-name").text(j);i.model.save({name:j}).fail(function(){i.$el.find(".history-name").text(i.model.previous("name"))})}else{i.$el.find(".history-name").text(k)}}})},_setUpDatasetActionsPopup:function(h){var i=this,j=[{html:e("Hide datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype.hide;i.getSelectedHdaCollection().ajaxQueue(k)}},{html:e("Unhide datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype.unhide;i.getSelectedHdaCollection().ajaxQueue(k)}},{html:e("Delete datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype["delete"];i.getSelectedHdaCollection().ajaxQueue(k)}},{html:e("Undelete datasets"),func:function(){var k=f.HistoryDatasetAssociation.prototype.undelete;i.getSelectedHdaCollection().ajaxQueue(k)}}];if(i.purgeAllowed){j.push({html:e("Permanently delete datasets"),func:function(){if(confirm(e("This will permanently remove the data in your datasets. Are you sure?"))){var k=f.HistoryDatasetAssociation.prototype.purge;i.getSelectedHdaCollection().ajaxQueue(k)}}})}return new PopupMenu(h.find(".history-dataset-action-popup-btn"),j)},_handleHdaDeletionChange:function(h){if(h.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[h.id])}},_handleHdaVisibleChange:function(h){if(h.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[h.id])}},_createHdaView:function(i){var h=i.get("id"),j=new this.HDAViewClass({model:i,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[h],selectable:this.selecting,purgeAllowed:this.purgeAllowed,hasUser:this.model.ownedByCurrUser(),logger:this.logger,tagsEditorShown:(this.tagsEditor&&!this.tagsEditor.hidden),annotationEditorShown:(this.annotationEditor&&!this.annotationEditor.hidden)});this._setUpHdaListeners(j);return j},_setUpHdaListeners:function(i){var h=this;d.ReadOnlyHistoryPanel.prototype._setUpHdaListeners.call(this,i);i.on("selected",function(j){var k=j.model.get("id");h.selectedHdaIds=_.union(h.selectedHdaIds,[k])});i.on("de-selected",function(j){var k=j.model.get("id");h.selectedHdaIds=_.without(h.selectedHdaIds,k)})},toggleHDATagEditors:function(h){var i=arguments;_.each(this.hdaViews,function(j){if(j.tagsEditor){j.tagsEditor.toggle.apply(j.tagsEditor,i)}})},toggleHDAAnnotationEditors:function(h){var i=arguments;_.each(this.hdaViews,function(j){if(j.annotationEditor){j.annotationEditor.toggle.apply(j.annotationEditor,i)}})},removeHdaView:function(i){if(!i){return}var h=this;i.$el.fadeOut(h.fxSpeed,function(){i.off();i.remove();delete h.hdaViews[i.model.id];if(_.isEmpty(h.hdaViews)){h.trigger("empty-history",h);h._renderEmptyMsg()}})},events:_.extend(_.clone(d.ReadOnlyHistoryPanel.prototype.events),{"click .history-select-btn":"toggleSelectors","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"))},showSelectors:function(h){h=(h!==undefined)?(h):(this.fxSpeed);this.selecting=true;this.$(".history-dataset-actions").slideDown(h);_.each(this.hdaViews,function(i){i.showSelector()});this.selectedHdaIds=[]},hideSelectors:function(h){h=(h!==undefined)?(h):(this.fxSpeed);this.selecting=false;this.$(".history-dataset-actions").slideUp(h);_.each(this.hdaViews,function(i){i.hideSelector()});this.selectedHdaIds=[]},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAllDatasets:function(h){_.each(this.hdaViews,function(i){i.select(h)})},deselectAllDatasets:function(h){_.each(this.hdaViews,function(i){i.deselect(h)})},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(h){return h.selected})},getSelectedHdaCollection:function(){return new f.HDACollection(_.map(this.getSelectedHdaViews(),function(h){return h.model}),{historyId:this.model.id})},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{HistoryPanel:g}});
\ No newline at end of file
diff -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 -r aad9eb1a8486211c2204452d466e5b811496f6e7 static/scripts/packed/mvc/ui/ui-modal.js
--- a/static/scripts/packed/mvc/ui/ui-modal.js
+++ b/static/scripts/packed/mvc/ui/ui-modal.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(c){if(c){this._create(c)}},show:function(c){this.initialize(c);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(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",false)},disableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",true)},showButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).show()},hideButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).hide()},getButton:function(c){var d=this.buttonList[c];return this.$buttons.find("#"+d)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var d=this;this.options=_.defaults(e,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.ui-modal")}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 c=0;$.each(this.options.buttons,function(f,h){var g="button-"+c++;d.$buttons.append($('<button id="'+g+'"></button>').text(f).click(h)).append(" ");d.buttonList[f]=g})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){$(document).on("keyup.ui-modal",function(f){if(f.keyCode==27){d.hide()}});this.$el.find(".modal-backdrop").on("click",function(){d.hide()})}},_template:function(c){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">'+c+'</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{View:b}});
\ No newline at end of file
+define([],function(){var a=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(b){if(b){this._create(b)}},show:function(b){console.debug(this);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.ui-modal")}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){$(document).on("keyup.ui-modal",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{View:a}});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/24834f127f4c/
Changeset: 24834f127f4c
User: carlfeberhard
Date: 2014-05-05 19:36:51
Summary: aad9eb1a8486: remove debugging statement
Affected #: 2 files
diff -r aad9eb1a8486211c2204452d466e5b811496f6e7 -r 24834f127f4cced95f0a64dd5a7ccf72a3f18134 static/scripts/mvc/ui/ui-modal.js
--- a/static/scripts/mvc/ui/ui-modal.js
+++ b/static/scripts/mvc/ui/ui-modal.js
@@ -27,7 +27,6 @@
// adds and displays a new frame/window
show: function(options) {
- console.debug( this );
// create
this.initialize(options);
diff -r aad9eb1a8486211c2204452d466e5b811496f6e7 -r 24834f127f4cced95f0a64dd5a7ccf72a3f18134 static/scripts/packed/mvc/ui/ui-modal.js
--- a/static/scripts/packed/mvc/ui/ui-modal.js
+++ b/static/scripts/packed/mvc/ui/ui-modal.js
@@ -1,1 +1,1 @@
-define([],function(){var a=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(b){if(b){this._create(b)}},show:function(b){console.debug(this);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.ui-modal")}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){$(document).on("keyup.ui-modal",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{View:a}});
\ No newline at end of file
+define([],function(){var a=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-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.ui-modal")}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){$(document).on("keyup.ui-modal",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{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: martenson: data libraries: router improvements, detecting whether the loaded page is the first page of the app (user came from outside) or within and navigating accordingly
by commits-noreply@bitbucket.org 05 May '14
by commits-noreply@bitbucket.org 05 May '14
05 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b94b4da49bfd/
Changeset: b94b4da49bfd
User: martenson
Date: 2014-05-05 19:03:16
Summary: data libraries: router improvements, detecting whether the loaded page is the first page of the app (user came from outside) or within and navigating accordingly
Affected #: 6 files
diff -r fe6c48de949dd4e640d3632ab23cfe6ab5fa0494 -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 static/scripts/galaxy.library.js
--- a/static/scripts/galaxy.library.js
+++ b/static/scripts/galaxy.library.js
@@ -27,12 +27,29 @@
// ============================================================================
// ROUTER
var LibraryRouter = Backbone.Router.extend({
- routes: {
- "" : "libraries",
- "folders/:id" : "folder_content",
- "folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
- "folders/:folder_id/download/:format" : "download"
+ initialize: function() {
+ this.routesHit = 0;
+ //keep count of number of routes handled by the application
+ Backbone.history.on('route', function() { this.routesHit++; }, this);
+ },
+
+ routes: {
+ "" : "libraries",
+ "folders/:id" : "folder_content",
+ "folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
+ "folders/:folder_id/download/:format" : "download"
+ },
+
+ back: function() {
+ if(this.routesHit > 1) {
+ //more than one route hit -> user did not land to current page directly
+ window.history.back();
+ } else {
+ //otherwise go to the home page. Use replaceState if available so
+ //the navigation doesn't create an extra history entry
+ this.navigate('#', {trigger:true, replace:true});
}
+ }
});
// ============================================================================
@@ -70,7 +87,7 @@
});
this.library_router.on('route:folder_content', function(id) {
- // TODO place caching here, sessionstorage/localstorage?
+ // TODO maybe caching somewhere here, sessionstorage/localstorage?
if (Galaxy.libraries.folderToolbarView){
Galaxy.libraries.folderToolbarView.$el.unbind('click');
}
@@ -80,7 +97,6 @@
this.library_router.on('route:download', function(folder_id, format) {
if ($('#folder_list_body').find(':checked').length === 0) {
- //TODO make URL sharable
mod_toastr.info('You have to select some datasets to download');
Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true});
} else {
@@ -91,11 +107,11 @@
this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){
if (Galaxy.libraries.folderToolbarView){
- Galaxy.libraries.folderToolbarView.$el.unbind('click');
+ Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id, dataset_id: dataset_id});
+ } else {
+ Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: folder_id});
+ Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id, dataset_id: dataset_id});
}
- Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: folder_id});
- Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id, dataset_id: dataset_id});
- // Galaxy.libraries.folderListView.rowViews.get(dataset_id).showDatasetDetails();
});
Backbone.history.start({pushState: false});
diff -r fe6c48de949dd4e640d3632ab23cfe6ab5fa0494 -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 static/scripts/mvc/library/library-folderlist-view.js
--- a/static/scripts/mvc/library/library-folderlist-view.js
+++ b/static/scripts/mvc/library/library-folderlist-view.js
@@ -70,9 +70,9 @@
},
error: function(model, response){
if (typeof response.responseJSON !== "undefined"){
- mod_toastr.error(response.responseJSON.err_msg);
+ mod_toastr.error(response.responseJSON.err_msg + ' Click this to go back.', '', {onclick: function() {Galaxy.libraries.library_router.back();}});
} else {
- mod_toastr.error('An error ocurred :(');
+ mod_toastr.error('An error ocurred :(. Click this to go back.', '', {onclick: function() {Galaxy.libraries.library_router.back();}});
}
}
});
diff -r fe6c48de949dd4e640d3632ab23cfe6ab5fa0494 -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 static/scripts/mvc/library/library-folderrow-view.js
--- a/static/scripts/mvc/library/library-folderrow-view.js
+++ b/static/scripts/mvc/library/library-folderrow-view.js
@@ -49,11 +49,7 @@
},
//show modal with current dataset info
- // showDatasetDetails : function(event){
showDatasetDetails : function(){
- // prevent default
- // event.preventDefault();
-
var id = this.id;
//create new item
@@ -100,7 +96,7 @@
this.modal = Galaxy.modal;
this.modal.show({
closing_events : true,
- title : 'Dataset Details',
+ title : item.get('name'),
body : template,
buttons : {
'Import' : function() { self.importCurrentIntoHistory(); },
diff -r fe6c48de949dd4e640d3632ab23cfe6ab5fa0494 -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 static/scripts/packed/galaxy.library.js
--- a/static/scripts/packed/galaxy.library.js
+++ b/static/scripts/packed/galaxy.library.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view"],function(e,c,g,k,h,a,f,d,i){var l=Backbone.Router.extend({routes:{"":"libraries","folders/:id":"folder_content","folders/:folder_id/datasets/:dataset_id":"dataset_detail","folders/:folder_id/download/:format":"download"}});var j=k.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,folderToolbarView:null,folderListView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new j({id:"global-lib-prefs"});this.library_router=new l();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new d.LibraryToolbarView();Galaxy.libraries.libraryListView=new f.LibraryListView()});this.library_router.on("route:folder_content",function(m){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:m});Galaxy.libraries.folderListView=new a.FolderListView({id:m})});this.library_router.on("route:download",function(m,n){if($("#folder_list_body").find(":checked").length===0){g.info("You have to select some datasets to download");Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:true,replace:true})}else{Galaxy.libraries.folderToolbarView.download(m,n);Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:false,replace:true})}});this.library_router.on("route:dataset_detail",function(n,m){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:n});Galaxy.libraries.folderListView=new a.FolderListView({id:n,dataset_id:m})});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view"],function(e,c,g,k,h,a,f,d,i){var l=Backbone.Router.extend({initialize:function(){this.routesHit=0;Backbone.history.on("route",function(){this.routesHit++},this)},routes:{"":"libraries","folders/:id":"folder_content","folders/:folder_id/datasets/:dataset_id":"dataset_detail","folders/:folder_id/download/:format":"download"},back:function(){if(this.routesHit>1){window.history.back()}else{this.navigate("#",{trigger:true,replace:true})}}});var j=k.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,folderToolbarView:null,folderListView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new j({id:"global-lib-prefs"});this.library_router=new l();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new d.LibraryToolbarView();Galaxy.libraries.libraryListView=new f.LibraryListView()});this.library_router.on("route:folder_content",function(m){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:m});Galaxy.libraries.folderListView=new a.FolderListView({id:m})});this.library_router.on("route:download",function(m,n){if($("#folder_list_body").find(":checked").length===0){g.info("You have to select some datasets to download");Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:true,replace:true})}else{Galaxy.libraries.folderToolbarView.download(m,n);Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:false,replace:true})}});this.library_router.on("route:dataset_detail",function(n,m){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderListView=new a.FolderListView({id:n,dataset_id:m})}else{Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:n});Galaxy.libraries.folderListView=new a.FolderListView({id:n,dataset_id:m})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
diff -r fe6c48de949dd4e640d3632ab23cfe6ab5fa0494 -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 static/scripts/packed/mvc/library/library-folderlist-view.js
--- a/static/scripts/packed/mvc/library/library-folderlist-view.js
+++ b/static/scripts/packed/mvc/library/library-folderlist-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderrow-view"],function(c,e,f,d,a){var b=Backbone.View.extend({el:"#folder_items_element",defaults:{include_deleted:false},progress:0,progressStep:1,modal:null,folderContainer:null,sort:"asc",events:{"click #select-all-checkboxes":"selectAll","click .dataset_row":"selectClickedRow","click .sort-folder-link":"sort_clicked"},rowViews:{},initialize:function(g){this.options=_.defaults(this.options||{},g);this.fetchFolder()},fetchFolder:function(g){var g=g||{};this.options.include_deleted=g.include_deleted;var h=this;this.collection=new d.Folder();this.listenTo(this.collection,"add",this.renderOne);this.listenTo(this.collection,"remove",this.removeOne);this.folderContainer=new d.FolderContainer({id:this.options.id});this.folderContainer.url=this.folderContainer.attributes.urlRoot+this.options.id+"/contents";if(this.options.include_deleted){this.folderContainer.url=this.folderContainer.url+"?include_deleted=true"}this.folderContainer.fetch({success:function(i){h.folder_container=i;h.render();h.addAll(i.get("folder").models);if(h.options.dataset_id){_.findWhere(h.rowViews,{id:h.options.dataset_id}).showDatasetDetails()}},error:function(j,i){if(typeof i.responseJSON!=="undefined"){f.error(i.responseJSON.err_msg)}else{f.error("An error ocurred :(")}}})},render:function(g){this.options=_.defaults(this.options,g);var h=this.templateFolder();var i=this.folderContainer.attributes.metadata.full_path;var j;if(i.length===1){j=0}else{j=i[i.length-2][0]}this.$el.html(h({path:this.folderContainer.attributes.metadata.full_path,id:this.options.id,upper_folder_id:j,order:this.sort}));$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},postRender:function(){var g=this.folderContainer.attributes.metadata;g.contains_file=typeof this.collection.findWhere({type:"file"})!=="undefined";Galaxy.libraries.folderToolbarView.configureElements(g);$(".deleted_dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},addAll:function(g){_.each(g.reverse(),function(h){Galaxy.libraries.folderListView.collection.add(h)});$("#center [data-toggle]").tooltip();this.checkEmptiness();this.postRender()},renderAll:function(){var g=this;_.each(this.collection.models.reverse(),function(h){g.renderOne(h)});this.postRender()},renderOne:function(h){if(h.get("data_type")!=="folder"){this.options.contains_file=true;h.set("readable_size",this.size_to_string(h.get("file_size")))}h.set("folder_id",this.id);var g=new a.FolderRowView(h);this.rowViews[h.get("id")]=g;this.$el.find("#first_folder_item").after(g.el);$(".deleted_dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},removeOne:function(g){this.$el.find("#"+g.id).remove()},checkEmptiness:function(){if((this.$el.find(".dataset_row").length===0)&&(this.$el.find(".folder_row").length===0)){this.$el.find(".empty-folder-message").show()}else{this.$el.find(".empty-folder-message").hide()}},sort_clicked:function(g){g.preventDefault();if(this.sort==="asc"){this.sortFolder("name","desc");this.sort="desc"}else{this.sortFolder("name","asc");this.sort="asc"}this.render();this.renderAll()},sortFolder:function(h,g){if(h==="name"){if(g==="asc"){return this.collection.sortByNameAsc()}else{if(g==="desc"){return this.collection.sortByNameDesc()}}}},size_to_string:function(g){var h="";if(g>=100000000000){g=g/100000000000;h="TB"}else{if(g>=100000000){g=g/100000000;h="GB"}else{if(g>=100000){g=g/100000;h="MB"}else{if(g>=100){g=g/100;h="KB"}else{g=g*10;h="b"}}}}return(Math.round(g)/10)+h},selectAll:function(h){var g=h.target.checked;that=this;$(":checkbox","#folder_list_body").each(function(){this.checked=g;$row=$(this.parentElement.parentElement);if(g){that.makeDarkRow($row)}else{that.makeWhiteRow($row)}})},selectClickedRow:function(h){var j="";var g;var i;if(h.target.localName==="input"){j=h.target;g=$(h.target.parentElement.parentElement);i="input"}else{if(h.target.localName==="td"){j=$("#"+h.target.parentElement.id).find(":checkbox")[0];g=$(h.target.parentElement);i="td"}}if(j.checked){if(i==="td"){j.checked="";this.makeWhiteRow(g)}else{if(i==="input"){this.makeDarkRow(g)}}}else{if(i==="td"){j.checked="selected";this.makeDarkRow(g)}else{if(i==="input"){this.makeWhiteRow(g)}}}},makeDarkRow:function(g){g.removeClass("light");g.find("a").removeClass("light");g.addClass("dark");g.find("a").addClass("dark");g.find("span").removeClass("fa-file-o");g.find("span").addClass("fa-file")},makeWhiteRow:function(g){g.removeClass("dark");g.find("a").removeClass("dark");g.addClass("light");g.find("a").addClass("light");g.find("span").addClass("fa-file-o");g.find("span").removeClass("fa-file")},templateFolder:function(){var g=[];g.push('<ol class="breadcrumb">');g.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');g.push(" <% _.each(path, function(path_item) { %>");g.push(" <% if (path_item[0] != id) { %>");g.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');g.push("<% } else { %>");g.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');g.push(" <% } %>");g.push(" <% }); %>");g.push("</ol>");g.push('<table id="folder_table" class="grid table table-condensed">');g.push(" <thead>");g.push(' <th class="button_heading"></th>');g.push(' <th style="text-align: center; width: 20px; " title="Check to select all datasets"><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');g.push(' <th style="width:30%;"><a class="sort-folder-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');g.push(" <th>data type</th>");g.push(" <th>size</th>");g.push(" <th>time updated (UTC)</th>");g.push(' <th style="width:15%;"></th> ');g.push(" </thead>");g.push(' <tbody id="folder_list_body">');g.push(' <tr id="first_folder_item">');g.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" </tr>");g.push(" </tbody>");g.push("</table>");g.push('<div class="empty-folder-message" style="display:none;">This folder is either empty or you do not have proper access permissions to see the contents.</div>');return _.template(g.join(""))}});return{FolderListView:b}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderrow-view"],function(c,e,f,d,a){var b=Backbone.View.extend({el:"#folder_items_element",defaults:{include_deleted:false},progress:0,progressStep:1,modal:null,folderContainer:null,sort:"asc",events:{"click #select-all-checkboxes":"selectAll","click .dataset_row":"selectClickedRow","click .sort-folder-link":"sort_clicked"},rowViews:{},initialize:function(g){this.options=_.defaults(this.options||{},g);this.fetchFolder()},fetchFolder:function(g){var g=g||{};this.options.include_deleted=g.include_deleted;var h=this;this.collection=new d.Folder();this.listenTo(this.collection,"add",this.renderOne);this.listenTo(this.collection,"remove",this.removeOne);this.folderContainer=new d.FolderContainer({id:this.options.id});this.folderContainer.url=this.folderContainer.attributes.urlRoot+this.options.id+"/contents";if(this.options.include_deleted){this.folderContainer.url=this.folderContainer.url+"?include_deleted=true"}this.folderContainer.fetch({success:function(i){h.folder_container=i;h.render();h.addAll(i.get("folder").models);if(h.options.dataset_id){_.findWhere(h.rowViews,{id:h.options.dataset_id}).showDatasetDetails()}},error:function(j,i){if(typeof i.responseJSON!=="undefined"){f.error(i.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{f.error("An error ocurred :(. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(g){this.options=_.defaults(this.options,g);var h=this.templateFolder();var i=this.folderContainer.attributes.metadata.full_path;var j;if(i.length===1){j=0}else{j=i[i.length-2][0]}this.$el.html(h({path:this.folderContainer.attributes.metadata.full_path,id:this.options.id,upper_folder_id:j,order:this.sort}));$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},postRender:function(){var g=this.folderContainer.attributes.metadata;g.contains_file=typeof this.collection.findWhere({type:"file"})!=="undefined";Galaxy.libraries.folderToolbarView.configureElements(g);$(".deleted_dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},addAll:function(g){_.each(g.reverse(),function(h){Galaxy.libraries.folderListView.collection.add(h)});$("#center [data-toggle]").tooltip();this.checkEmptiness();this.postRender()},renderAll:function(){var g=this;_.each(this.collection.models.reverse(),function(h){g.renderOne(h)});this.postRender()},renderOne:function(h){if(h.get("data_type")!=="folder"){this.options.contains_file=true;h.set("readable_size",this.size_to_string(h.get("file_size")))}h.set("folder_id",this.id);var g=new a.FolderRowView(h);this.rowViews[h.get("id")]=g;this.$el.find("#first_folder_item").after(g.el);$(".deleted_dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},removeOne:function(g){this.$el.find("#"+g.id).remove()},checkEmptiness:function(){if((this.$el.find(".dataset_row").length===0)&&(this.$el.find(".folder_row").length===0)){this.$el.find(".empty-folder-message").show()}else{this.$el.find(".empty-folder-message").hide()}},sort_clicked:function(g){g.preventDefault();if(this.sort==="asc"){this.sortFolder("name","desc");this.sort="desc"}else{this.sortFolder("name","asc");this.sort="asc"}this.render();this.renderAll()},sortFolder:function(h,g){if(h==="name"){if(g==="asc"){return this.collection.sortByNameAsc()}else{if(g==="desc"){return this.collection.sortByNameDesc()}}}},size_to_string:function(g){var h="";if(g>=100000000000){g=g/100000000000;h="TB"}else{if(g>=100000000){g=g/100000000;h="GB"}else{if(g>=100000){g=g/100000;h="MB"}else{if(g>=100){g=g/100;h="KB"}else{g=g*10;h="b"}}}}return(Math.round(g)/10)+h},selectAll:function(h){var g=h.target.checked;that=this;$(":checkbox","#folder_list_body").each(function(){this.checked=g;$row=$(this.parentElement.parentElement);if(g){that.makeDarkRow($row)}else{that.makeWhiteRow($row)}})},selectClickedRow:function(h){var j="";var g;var i;if(h.target.localName==="input"){j=h.target;g=$(h.target.parentElement.parentElement);i="input"}else{if(h.target.localName==="td"){j=$("#"+h.target.parentElement.id).find(":checkbox")[0];g=$(h.target.parentElement);i="td"}}if(j.checked){if(i==="td"){j.checked="";this.makeWhiteRow(g)}else{if(i==="input"){this.makeDarkRow(g)}}}else{if(i==="td"){j.checked="selected";this.makeDarkRow(g)}else{if(i==="input"){this.makeWhiteRow(g)}}}},makeDarkRow:function(g){g.removeClass("light");g.find("a").removeClass("light");g.addClass("dark");g.find("a").addClass("dark");g.find("span").removeClass("fa-file-o");g.find("span").addClass("fa-file")},makeWhiteRow:function(g){g.removeClass("dark");g.find("a").removeClass("dark");g.addClass("light");g.find("a").addClass("light");g.find("span").addClass("fa-file-o");g.find("span").removeClass("fa-file")},templateFolder:function(){var g=[];g.push('<ol class="breadcrumb">');g.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');g.push(" <% _.each(path, function(path_item) { %>");g.push(" <% if (path_item[0] != id) { %>");g.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');g.push("<% } else { %>");g.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');g.push(" <% } %>");g.push(" <% }); %>");g.push("</ol>");g.push('<table id="folder_table" class="grid table table-condensed">');g.push(" <thead>");g.push(' <th class="button_heading"></th>');g.push(' <th style="text-align: center; width: 20px; " title="Check to select all datasets"><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');g.push(' <th style="width:30%;"><a class="sort-folder-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');g.push(" <th>data type</th>");g.push(" <th>size</th>");g.push(" <th>time updated (UTC)</th>");g.push(' <th style="width:15%;"></th> ');g.push(" </thead>");g.push(' <tbody id="folder_list_body">');g.push(' <tr id="first_folder_item">');g.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" </tr>");g.push(" </tbody>");g.push("</table>");g.push('<div class="empty-folder-message" style="display:none;">This folder is either empty or you do not have proper access permissions to see the contents.</div>');return _.template(g.join(""))}});return{FolderListView:b}});
\ No newline at end of file
diff -r fe6c48de949dd4e640d3632ab23cfe6ab5fa0494 -r b94b4da49bfdf4f204d0ad2dce878a37e6e4f3d3 static/scripts/packed/mvc/library/library-folderrow-view.js
--- a/static/scripts/packed/mvc/library/library-folderrow-view.js
+++ b/static/scripts/packed/mvc/library/library-folderrow-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .undelete_dataset_btn":"undelete_dataset"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";if(f.get("deleted")){g=this.templateRowDeletedFile()}else{g=this.templateRowFile()}}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(){var i=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=i;var f=this;h.fetch({success:function(j){g.fetch({success:function(k){f.renderModalAfterFetch(j,k)},error:function(l,k){if(typeof k.responseJSON!=="undefined"){e.error(k.responseJSON.err_msg)}else{e.error("An error occured during fetching histories:(")}f.renderModalAfterFetch(j)}})},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error(j.responseJSON.err_msg)}else{e.error("An error occured during loading dataset details :(")}}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var h=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=h;var f=$("#id_row").attr("data-id");var i=new c.HistoryItem();var g=this;i.url=i.urlRoot+h+"/contents";i.save({content:f,source:"library"},{success:function(){e.success("Dataset imported");g.modal.enableButton("Import");g.modal.enableButton("Download")},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error("Dataset not imported. "+j.responseJSON.err_msg)}else{e.error("An error occured! Dataset not imported. Please try again.")}g.modal.enableButton("Import");g.modal.enableButton("Download")}})},undelete_dataset:function(g){$(".tooltip").hide();var f=$(g.target).closest("tr")[0].id;var h=Galaxy.libraries.folderListView.collection.get(f);h.url=h.urlRoot+h.id+"?undelete=true";h.destroy({success:function(j,i){Galaxy.libraries.folderListView.collection.remove(f);var k=new c.Item(i);Galaxy.libraries.folderListView.collection.add(k);e.success("Dataset undeleted")},error:function(j,i){if(typeof i.responseJSON!=="undefined"){e.error("Dataset was not undeleted. "+i.responseJSON.err_msg)}else{e.error("An error occured! Dataset was not undeleted. Please try again.")}}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>');tmpl_array.push(" <span>(empty folder)</span>");tmpl_array.push(" <% } %>");tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowDeletedFile:function(){tmpl_array=[];tmpl_array.push('<tr class="active deleted_dataset" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span></td>');tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(' <td class="right-center"><button data-toggle="tooltip" data-placement="top" title="Undelete <%- content_item.get("name") %>" class="primary-button btn-xs undelete_dataset_btn show_on_hover" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")}});return{FolderRowView:a}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .undelete_dataset_btn":"undelete_dataset"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";if(f.get("deleted")){g=this.templateRowDeletedFile()}else{g=this.templateRowFile()}}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(){var i=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=i;var f=this;h.fetch({success:function(j){g.fetch({success:function(k){f.renderModalAfterFetch(j,k)},error:function(l,k){if(typeof k.responseJSON!=="undefined"){e.error(k.responseJSON.err_msg)}else{e.error("An error occured during fetching histories:(")}f.renderModalAfterFetch(j)}})},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error(j.responseJSON.err_msg)}else{e.error("An error occured during loading dataset details :(")}}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:k.get("name"),body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var h=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=h;var f=$("#id_row").attr("data-id");var i=new c.HistoryItem();var g=this;i.url=i.urlRoot+h+"/contents";i.save({content:f,source:"library"},{success:function(){e.success("Dataset imported");g.modal.enableButton("Import");g.modal.enableButton("Download")},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error("Dataset not imported. "+j.responseJSON.err_msg)}else{e.error("An error occured! Dataset not imported. Please try again.")}g.modal.enableButton("Import");g.modal.enableButton("Download")}})},undelete_dataset:function(g){$(".tooltip").hide();var f=$(g.target).closest("tr")[0].id;var h=Galaxy.libraries.folderListView.collection.get(f);h.url=h.urlRoot+h.id+"?undelete=true";h.destroy({success:function(j,i){Galaxy.libraries.folderListView.collection.remove(f);var k=new c.Item(i);Galaxy.libraries.folderListView.collection.add(k);e.success("Dataset undeleted")},error:function(j,i){if(typeof i.responseJSON!=="undefined"){e.error("Dataset was not undeleted. "+i.responseJSON.err_msg)}else{e.error("An error occured! Dataset was not undeleted. Please try again.")}}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>');tmpl_array.push(" <span>(empty folder)</span>");tmpl_array.push(" <% } %>");tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowDeletedFile:function(){tmpl_array=[];tmpl_array.push('<tr class="active deleted_dataset" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span></td>');tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(' <td class="right-center"><button data-toggle="tooltip" data-placement="top" title="Undelete <%- content_item.get("name") %>" class="primary-button btn-xs undelete_dataset_btn show_on_hover" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")}});return{FolderRowView: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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6f07000db257/
Changeset: 6f07000db257
User: jmchilton
Date: 2014-05-05 18:35:31
Summary: Remove duplicated code block - error in stable->central merge at some point I guess?
Affected #: 1 file
diff -r e7c77cb338c64f72310d844ee9e605e7b5438f94 -r 6f07000db257139dee35696da6dd840b240caef3 lib/galaxy/jobs/runners/__init__.py
--- a/lib/galaxy/jobs/runners/__init__.py
+++ b/lib/galaxy/jobs/runners/__init__.py
@@ -237,12 +237,6 @@
dependency_shell_commands = "&&".join( dependency_shell_commands )
external_metadata_script = "%s&&%s" % ( dependency_shell_commands, external_metadata_script )
log.debug( 'executing external set_meta script for job %d: %s' % ( job_wrapper.job_id, external_metadata_script ) )
- if resolve_requirements:
- dependency_shell_commands = self.app.datatypes_registry.set_external_metadata_tool.build_dependency_shell_commands()
- if dependency_shell_commands:
- if isinstance( dependency_shell_commands, list ):
- dependency_shell_commands = "&&".join( dependency_shell_commands )
- external_metadata_script = "%s&&%s" % ( dependency_shell_commands, external_metadata_script )
external_metadata_proc = subprocess.Popen( args=external_metadata_script,
shell=True,
env=os.environ,
https://bitbucket.org/galaxy/galaxy-central/commits/fe6c48de949d/
Changeset: fe6c48de949d
User: jmchilton
Date: 2014-05-05 18:35:31
Summary: Rework some error handling in local runner.
This way if something goes wrong in failing job - the original exception is reported.
Affected #: 1 file
diff -r 6f07000db257139dee35696da6dd840b240caef3 -r fe6c48de949dd4e640d3632ab23cfe6ab5fa0494 lib/galaxy/jobs/runners/local.py
--- a/lib/galaxy/jobs/runners/local.py
+++ b/lib/galaxy/jobs/runners/local.py
@@ -109,8 +109,8 @@
stderr_file.close()
log.debug('execution finished: %s' % command_line)
except Exception:
+ log.exception("failure running job %d" % job_wrapper.job_id)
job_wrapper.fail( "failure running job", exception=True )
- log.exception("failure running job %d" % job_wrapper.job_id)
return
self._handle_metadata_externally( job_wrapper, resolve_requirements=True )
# Finish the job!
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: Use correctly cased PyYAML
by commits-noreply@bitbucket.org 05 May '14
by commits-noreply@bitbucket.org 05 May '14
05 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e7c77cb338c6/
Changeset: e7c77cb338c6
User: dannon
Date: 2014-05-05 16:43:18
Summary: Use correctly cased PyYAML
Affected #: 1 file
diff -r 848d2c4e41c27e67e07431b152b0b329676ab8c5 -r e7c77cb338c64f72310d844ee9e605e7b5438f94 lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
--- a/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
+++ b/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
@@ -15,7 +15,7 @@
from galaxy.web.base.controller import BaseUIController
from galaxy.util.json import to_json_string
-eggs.require('pyyaml')
+eggs.require('PyYAML')
eggs.require('boto')
eggs.require('bioblend')
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c8e18e05f0ec/
Changeset: c8e18e05f0ec
User: jmchilton
Date: 2014-05-05 16:11:05
Summary: Truncate big job metric values.
Wasn't needed for sqlite based testing - but based on Nicola's experience must be for some other database backend.
https://bitbucket.org/galaxy/galaxy-central/commits/a45f6e57f3d5a4075430a6d…
Affected #: 2 files
diff -r 92519a9bfa32a42ce47a63fdb72c8e2d717ec52e -r c8e18e05f0ecee85cc6d3d7122b457fbc85915a4 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -107,6 +107,10 @@
else:
if isinstance( metric_value, str ):
metric_value = unicode( metric_value, 'utf-8' )
+ if len( metric_value ) > 1022:
+ # Truncate these values - not needed with sqlite
+ # but other backends must need it.
+ metric_value = metric_value[ :1022 ]
metric = self._text_metric( plugin, metric_name, metric_value )
self.text_metrics.append( metric )
diff -r 92519a9bfa32a42ce47a63fdb72c8e2d717ec52e -r c8e18e05f0ecee85cc6d3d7122b457fbc85915a4 test/unit/test_galaxy_mapping.py
--- a/test/unit/test_galaxy_mapping.py
+++ b/test/unit/test_galaxy_mapping.py
@@ -237,7 +237,12 @@
task = model.Task( job=job, working_directory="/tmp", prepare_files_cmd="split.sh" )
task.add_metric( "gx", "galaxy_slots", 5 )
task.add_metric( "system", "system_name", "localhost" )
+
+ big_value = ":".join( [ "%d" % i for i in range( 2000 ) ] )
+ task.add_metric( "env", "BIG_PATH", big_value )
self.persist( task )
+ # Ensure big values truncated
+ assert len( task.text_metrics[ 1 ].metric_value ) <= 1023
def test_tasks( self ):
model = self.model
https://bitbucket.org/galaxy/galaxy-central/commits/d9c6648ef265/
Changeset: d9c6648ef265
User: jmchilton
Date: 2014-05-05 16:11:05
Summary: Use Nicola's improved logic for env output parsing for env metrics plugin.
Very well laid out here https://bitbucket.org/galaxy/galaxy-central/commits/a45f6e57f3d5a4075430a6d… with examples. The one modification I made was to move the logic for truncated large property values into the model layer so it applies for all plugins.
Affected #: 1 file
diff -r c8e18e05f0ecee85cc6d3d7122b457fbc85915a4 -r d9c6648ef2658cc06708ecf908f8b5ce88a7996f lib/galaxy/jobs/metrics/instrumenters/env.py
--- a/lib/galaxy/jobs/metrics/instrumenters/env.py
+++ b/lib/galaxy/jobs/metrics/instrumenters/env.py
@@ -1,3 +1,5 @@
+import re
+
from ..instrumenters import InstrumentPlugin
from ...metrics import formatting
@@ -41,17 +43,19 @@
variables = self.variables
properties = {}
- for line in open( self.__env_file( job_directory ) ).readlines():
- if "=" not in line:
- # Previous line may have had a multiline property value, just
- # keep it simple here and only record the first part of
- # property. A more robust solution might be to record env -O
- # so properties are terminated by null characters instead of
- # newlines.
- continue
- var, value = line.split( "=", 1 )
+ env_string = ''.join( open( self.__env_file( job_directory ) ).readlines() )
+ while env_string:
+ # Check if the next lines contain a shell function.
+ # We use '\n\}\n' as regex termination because shell
+ # functions can be nested.
+ # We use the non-greedy '.+?' because of re.DOTALL .
+ m = re.match( '([^=]+)=(\(\) \{.+?\n\})\n', env_string, re.DOTALL )
+ if m is None:
+ m = re.match( '([^=]+)=(.*)\n', env_string )
+ (var, value) = m.groups()
if not variables or var in variables:
properties[ var ] = value
+ env_string = env_string[m.end():]
return properties
https://bitbucket.org/galaxy/galaxy-central/commits/848d2c4e41c2/
Changeset: 848d2c4e41c2
User: jmchilton
Date: 2014-05-05 16:11:05
Summary: Slightly more defensive job metrics env parsing.
The env string potentially may not match exactly if there are problems reading or recording env output. Log the problem and leave the parsing loop.
Affected #: 1 file
diff -r d9c6648ef2658cc06708ecf908f8b5ce88a7996f -r 848d2c4e41c27e67e07431b152b0b329676ab8c5 lib/galaxy/jobs/metrics/instrumenters/env.py
--- a/lib/galaxy/jobs/metrics/instrumenters/env.py
+++ b/lib/galaxy/jobs/metrics/instrumenters/env.py
@@ -52,6 +52,12 @@
m = re.match( '([^=]+)=(\(\) \{.+?\n\})\n', env_string, re.DOTALL )
if m is None:
m = re.match( '([^=]+)=(.*)\n', env_string )
+ if m is None:
+ # Some problem recording or reading back env output.
+ message_template = "Problem parsing env metric output for job %s - properties will be incomplete"
+ message = message_template % job_id
+ log.debug( message )
+ break
(var, value) = m.groups()
if not variables or var in variables:
properties[ var ] = value
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