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: natefoo: Correctly handle the case where the AMQP SSL connection param parser gets params=None.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c0eb8b472f3c/
Changeset: c0eb8b472f3c
User: natefoo
Date: 2014-05-14 22:27:28
Summary: Correctly handle the case where the AMQP SSL connection param parser gets params=None.
Affected #: 1 file
diff -r b483d9df129c00480fc72253a277de18ab67b27d -r c0eb8b472f3ccabdfd1b0396dbf92c34f3140200 lib/galaxy/jobs/runners/lwr_client/util.py
--- a/lib/galaxy/jobs/runners/lwr_client/util.py
+++ b/lib/galaxy/jobs/runners/lwr_client/util.py
@@ -65,7 +65,9 @@
def parse_amqp_connect_ssl_params(params):
ssl = None
rval = None
- ssl_options = filter(lambda x: x.startswith('amqp_connect_ssl_'), params.keys())
+ ssl_options = []
+ if params:
+ ssl_options = filter(lambda x: x.startswith('amqp_connect_ssl_'), params.keys())
if ssl_options:
ssl = __import__('ssl')
rval = {}
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: davebgx: Fix missing imports, add self.app in a few more places.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b483d9df129c/
Changeset: b483d9df129c
User: davebgx
Date: 2014-05-14 21:19:48
Summary: Fix missing imports, add self.app in a few more places.
Affected #: 1 file
diff -r c0832d30e315c24dcc2cf23918e4b0bd7b30ba56 -r b483d9df129c00480fc72253a277de18ab67b27d lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -19,6 +19,8 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import xml_util
+from tool_shed.galaxy_install.install_manager import InstallManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
from galaxy.util.odict import odict
log = logging.getLogger( __name__ )
@@ -497,12 +499,12 @@
tool_dependency,
error_message,
remove_installation_path=False )
- if tool_dependency and tool_dependency.status in [ app.install_model.ToolDependency.installation_status.INSTALLED,
- app.install_model.ToolDependency.installation_status.ERROR ]:
+ if tool_dependency and tool_dependency.status in [ self.app.install_model.ToolDependency.installation_status.INSTALLED,
+ self.app.install_model.ToolDependency.installation_status.ERROR ]:
installed_tool_dependencies.append( tool_dependency )
- if app.config.manage_dependency_relationships:
+ if self.app.config.manage_dependency_relationships:
# Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
- app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
+ self.app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
for installed_tool_dependency in installed_tool_dependencies:
if installed_tool_dependency.status == self.app.install_model.ToolDependency.installation_status.ERROR:
print '\nThe ToolMigrationManager returned the following error while installing tool dependency ', installed_tool_dependency.name, ':'
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/f95cf49907cc/
Changeset: f95cf49907cc
User: jmchilton
Date: 2014-05-14 21:08:03
Summary: Bugfix: Annotation, tags on collections update looking in old location.
Moved to collection instances instead of collections a little before PR opened.
Affected #: 1 file
diff -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 -r f95cf49907cca1c57a2fad9738e66c9aa5078fb9 lib/galaxy/dataset_collections/__init__.py
--- a/lib/galaxy/dataset_collections/__init__.py
+++ b/lib/galaxy/dataset_collections/__init__.py
@@ -138,10 +138,10 @@
changed = dataset_collection_instance.set_from_dict( new_data )
# the rest (often involving the trans) - do here
if 'annotation' in new_data.keys() and trans.get_user():
- dataset_collection_instance.add_item_annotation( trans.sa_session, trans.get_user(), dataset_collection_instance.collection, new_data[ 'annotation' ] )
+ dataset_collection_instance.add_item_annotation( trans.sa_session, trans.get_user(), dataset_collection_instance, new_data[ 'annotation' ] )
changed[ 'annotation' ] = new_data[ 'annotation' ]
if 'tags' in new_data.keys() and trans.get_user():
- self.set_tags_from_list( trans, dataset_collection_instance.collection, new_data[ 'tags' ], user=trans.user )
+ self.set_tags_from_list( trans, dataset_collection_instance, new_data[ 'tags' ], user=trans.user )
if changed.keys():
trans.sa_session.flush()
https://bitbucket.org/galaxy/galaxy-central/commits/c0832d30e315/
Changeset: c0832d30e315
User: jmchilton
Date: 2014-05-14 21:08:56
Summary: Merge.
Affected #: 1 file
diff -r f95cf49907cca1c57a2fad9738e66c9aa5078fb9 -r c0832d30e315c24dcc2cf23918e4b0bd7b30ba56 lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -470,7 +470,7 @@
if index is not None:
tool_dependency = tool_dependencies[ index ]
tool_dependency, proceed_with_install, action_elem_tuples = \
- tag_manager.process_tag_set( trans.app,
+ tag_manager.process_tag_set( self.app,
tool_shed_repository,
tool_dependency,
elem,
@@ -480,7 +480,7 @@
tool_dependency_db_records=tool_dependencies )
if proceed_with_install:
try:
- tool_dependency = install_manager.install_package( trans.app,
+ tool_dependency = install_manager.install_package( self.app,
elem,
tool_shed_repository,
tool_dependencies=tool_dependencies,
@@ -493,7 +493,7 @@
# Since there was an installation error, update the tool dependency status to Error. The
# remove_installation_path option must be left False here.
tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix for tool migration manager to use self.app instead of trans.app.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a4699a3d7c2d/
Changeset: a4699a3d7c2d
User: greg
Date: 2014-05-14 21:07:30
Summary: Fix for tool migration manager to use self.app instead of trans.app.
Affected #: 1 file
diff -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 -r a4699a3d7c2de78ad5aa5ea9e79409e85050fa9f lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -470,7 +470,7 @@
if index is not None:
tool_dependency = tool_dependencies[ index ]
tool_dependency, proceed_with_install, action_elem_tuples = \
- tag_manager.process_tag_set( trans.app,
+ tag_manager.process_tag_set( self.app,
tool_shed_repository,
tool_dependency,
elem,
@@ -480,7 +480,7 @@
tool_dependency_db_records=tool_dependencies )
if proceed_with_install:
try:
- tool_dependency = install_manager.install_package( trans.app,
+ tool_dependency = install_manager.install_package( self.app,
elem,
tool_shed_repository,
tool_dependencies=tool_dependencies,
@@ -493,7 +493,7 @@
# Since there was an installation error, update the tool dependency status to Error. The
# remove_installation_path option must be left False here.
tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6fecbad49afd/
Changeset: 6fecbad49afd
User: greg
Date: 2014-05-14 20:55:31
Summary: Phase 2 of the tool dependency package installation framework rewrite: 1) rename the RecipeManager class to be the StepManager class and add a new TagManager class, both of which are contained in the recipe_manager.py module. 2) Add appropriate new classes for handling recipe tag sets to a new tag_handler.py module. Add a new InstallManager class with functions for installing tool dependencies. Eliminate the use of fabric_util.py and install_util.py.
Affected #: 18 files
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -23,8 +23,11 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import workflow_util
+from tool_shed.util import xml_util
from tool_shed.galaxy_install import repository_util
import tool_shed.galaxy_install.grids.admin_toolshed_grids as admin_toolshed_grids
+from tool_shed.galaxy_install.install_manager import InstallManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
import pkg_resources
eggs.require( 'mercurial' )
@@ -444,20 +447,74 @@
@web.expose
@web.require_admin
def initiate_tool_dependency_installation( self, trans, tool_dependencies, **kwd ):
- """Install specified dependencies for repository tools."""
+ """
+ Install specified dependencies for repository tools. The received list of tool_dependencies
+ are the database records for those dependencies defined in the tool_dependencies.xml file
+ (contained in the repository) that should be installed. This allows for filtering out dependencies
+ that have not been checked for installation on the 'Manage tool dependencies' page for an installed
+ tool shed repository.
+ """
# Get the tool_shed_repository from one of the tool_dependencies.
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
err_msg = ''
+ attr_tups_of_dependencies_for_install = [ ( td.name, td.version, td.type ) for td in tool_dependencies ]
tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = suc.get_config_from_disk( suc.TOOL_DEPENDENCY_DEFINITION_FILENAME,
tool_shed_repository.repo_path( trans.app ) )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=trans.app,
- tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_dependencies,
- from_tool_migration_manager=False )
+ # Parse the tool_dependencies.xml config.
+ tree, error_message = xml_util.parse_xml( tool_dependencies_config )
+ installed_tool_dependencies = []
+ install_manager = InstallManager()
+ tag_manager = TagManager()
+ root = tree.getroot()
+ for elem in root:
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if package_name and package_version:
+ # elem is a package tag set.
+ attr_tup = ( package_name, package_version, 'package' )
+ try:
+ index = attr_tups_of_dependencies_for_install.index( attr_tup )
+ except Exception, e:
+ index = None
+ if index is not None:
+ tool_dependency = tool_dependencies[ index ]
+ tool_dependency, proceed_with_install, action_elem_tuples = \
+ tag_manager.process_tag_set( trans.app,
+ tool_shed_repository,
+ tool_dependency,
+ elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=False,
+ tool_dependency_db_records=tool_dependencies )
+ if proceed_with_install:
+ try:
+ tool_dependency = install_manager.install_package( trans.app,
+ elem,
+ tool_shed_repository,
+ tool_dependencies=tool_dependencies,
+ from_tool_migration_manager=False )
+ except Exception, e:
+ error_message = "Error installing tool dependency package %s version %s: %s" % \
+ ( str( package_name ), str( package_version ), str( e ) )
+ log.exception( error_message )
+ if tool_dependency:
+ # Since there was an installation error, update the tool dependency status to Error. The
+ # remove_installation_path option must be left False here.
+ tool_dependency = \
+ tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ if tool_dependency and tool_dependency.status in [ trans.app.install_model.ToolDependency.installation_status.INSTALLED,
+ trans.app.install_model.ToolDependency.installation_status.ERROR ]:
+ installed_tool_dependencies.append( tool_dependency )
+ if trans.app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ trans.app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
for installed_tool_dependency in installed_tool_dependencies:
if installed_tool_dependency.status == trans.app.install_model.ToolDependency.installation_status.ERROR:
text = util.unicodify( installed_tool_dependency.error_message )
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py
--- a/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py
+++ b/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py
@@ -185,8 +185,8 @@
operation='install latest revision' ) ),
grids.GridOperation( label="Install",
condition=( lambda item: \
- not item.deleted and \
- item.status == tool_shed_install.ToolShedRepository.installation_status.NEW ),
+ not item.deleted and \
+ item.status == tool_shed_install.ToolShedRepository.installation_status.NEW ),
allow_multiple=False,
url_args=dict( controller='admin_toolshed',
action='manage_repository',
@@ -196,7 +196,7 @@
not item.deleted and \
item.status not in \
[ tool_shed_install.ToolShedRepository.installation_status.ERROR,
- tool_shed_install.ToolShedRepository.installation_status.NEW ] ),
+ tool_shed_install.ToolShedRepository.installation_status.NEW ] ),
allow_multiple=False,
url_args=dict( controller='admin_toolshed',
action='browse_repositories',
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -1,8 +1,318 @@
import logging
import os
+from galaxy import eggs
+
+eggs.require( 'paramiko' )
+eggs.require( 'ssh' )
+eggs.require( 'Fabric' )
+
+from fabric.api import lcd
+
+from tool_shed.util import tool_dependency_util
+
+from tool_shed.galaxy_install.tool_dependencies import td_common_util
+from tool_shed.galaxy_install.tool_dependencies.recipe.env_file_builder import EnvFileBuilder
+from tool_shed.galaxy_install.tool_dependencies.recipe.install_environment import InstallEnvironment
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import StepManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
+
log = logging.getLogger( __name__ )
+INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environmnet',
+ 'setup_r_environmnet', 'setup_ruby_environmnet', 'shell_command' ]
+
class InstallManager( object ):
- pass
\ No newline at end of file
+
+ def get_tool_shed_repository_install_dir( self, app, tool_shed_repository ):
+ return os.path.abspath( tool_shed_repository.repo_files_directory( app ) )
+
+ def install_and_build_package( self, app, tool_shed_repository, tool_dependency, actions_dict ):
+ """Install a Galaxy tool dependency package either via a url or a mercurial or git clone command."""
+ tool_shed_repository_install_dir = self.get_tool_shed_repository_install_dir( app, tool_shed_repository )
+ install_dir = actions_dict[ 'install_dir' ]
+ package_name = actions_dict[ 'package_name' ]
+ actions = actions_dict.get( 'actions', None )
+ filtered_actions = []
+ env_file_builder = EnvFileBuilder( install_dir )
+ install_environment = InstallEnvironment( tool_shed_repository_install_dir=tool_shed_repository_install_dir,
+ install_dir=install_dir )
+ step_manager = StepManager()
+ if actions:
+ with install_environment.make_tmp_dir() as work_dir:
+ with lcd( work_dir ):
+ # The first action in the list of actions will be the one that defines the initial download process.
+ # There are currently three supported actions; download_binary, download_by_url and clone via a
+ # shell_command action type. The recipe steps will be filtered at this stage in the process, with
+ # the filtered actions being used in the next stage below. The installation directory (i.e., dir)
+ # is also defined in this stage and is used in the next stage below when defining current_dir.
+ action_type, action_dict = actions[ 0 ]
+ if action_type in INSTALL_ACTIONS:
+ # Some of the parameters passed here are needed only by a subset of the step handler classes,
+ # but to allow for a standard method signature we'll pass them along. We don't check the
+ # tool_dependency status in this stage because it should not have been changed based on a
+ # download.
+ tool_dependency, filtered_actions, dir = \
+ step_manager.execute_step( app=app,
+ tool_dependency=tool_dependency,
+ package_name=package_name,
+ actions=actions,
+ action_type=action_type,
+ action_dict=action_dict,
+ filtered_actions=filtered_actions,
+ env_file_builder=env_file_builder,
+ install_environment=install_environment,
+ work_dir=work_dir,
+ current_dir=None,
+ initial_download=True )
+ else:
+ # We're handling a complex repository dependency where we only have a set_environment tag set.
+ # <action type="set_environment">
+ # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+ # </action>
+ filtered_actions = [ a for a in actions ]
+ dir = install_dir
+ # We're in stage 2 of the installation process. The package has been down-loaded, so we can
+ # now perform all of the actions defined for building it.
+ for action_tup in filtered_actions:
+ current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
+ with lcd( current_dir ):
+ action_type, action_dict = action_tup
+ tool_dependency, tmp_filtered_actions, tmp_dir = \
+ step_manager.execute_step( app=app,
+ tool_dependency=tool_dependency,
+ package_name=package_name,
+ actions=actions,
+ action_type=action_type,
+ action_dict=action_dict,
+ filtered_actions=filtered_actions,
+ env_file_builder=env_file_builder,
+ install_environment=install_environment,
+ work_dir=work_dir,
+ current_dir=current_dir,
+ initial_download=False )
+ if tool_dependency.status in [ app.install_model.ToolDependency.installation_status.ERROR ]:
+ # If the tool_dependency status is in an error state, return it with no additional
+ # processing.
+ return tool_dependency
+ # Make sure to handle the special case where the value of dir is reset (this happens when
+ # the action_type is change_directiory). In all other action types, dir will be returned as
+ # None.
+ if tmp_dir is not None:
+ dir = tmp_dir
+ return tool_dependency
+
+ def install_and_build_package_via_fabric( self, app, tool_shed_repository, tool_dependency, actions_dict ):
+ sa_session = app.install_model.context
+ try:
+ # There is currently only one fabric method.
+ tool_dependency = self.install_and_build_package( app, tool_shed_repository, tool_dependency, actions_dict )
+ except Exception, e:
+ log.exception( 'Error installing tool dependency %s version %s.', str( tool_dependency.name ), str( tool_dependency.version ) )
+ # Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
+ # be left False here.
+ error_message = '%s\n%s' % ( td_common_util.format_traceback(), str( e ) )
+ tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ tool_dependency = tool_dependency_util.mark_tool_dependency_installed( app, tool_dependency )
+ return tool_dependency
+
+ def install_via_fabric( self, app, tool_shed_repository, tool_dependency, install_dir, package_name=None, custom_fabfile_path=None,
+ actions_elem=None, action_elem=None, **kwd ):
+ """
+ Parse a tool_dependency.xml file's <actions> tag set to gather information for installation using
+ self.install_and_build_package(). The use of fabric is being eliminated, so some of these functions
+ may need to be renamed at some point.
+ """
+ sa_session = app.install_model.context
+ if not os.path.exists( install_dir ):
+ os.makedirs( install_dir )
+ actions_dict = dict( install_dir=install_dir )
+ if package_name:
+ actions_dict[ 'package_name' ] = package_name
+ actions = []
+ is_binary_download = False
+ if actions_elem is not None:
+ elems = actions_elem
+ if elems.get( 'os' ) is not None and elems.get( 'architecture' ) is not None:
+ is_binary_download = True
+ elif action_elem is not None:
+ # We were provided with a single <action> element to perform certain actions after a platform-specific tarball was downloaded.
+ elems = [ action_elem ]
+ else:
+ elems = []
+ step_manager = StepManager()
+ tool_shed_repository_install_dir = self.get_tool_shed_repository_install_dir( app, tool_shed_repository )
+ install_environment = InstallEnvironment( tool_shed_repository_install_dir, install_dir )
+ for action_elem in elems:
+ # Make sure to skip all comments, since they are now included in the XML tree.
+ if action_elem.tag != 'action':
+ continue
+ action_dict = {}
+ action_type = action_elem.get( 'type', None )
+ if action_type is not None:
+ action_dict = step_manager.prepare_step( app=app,
+ tool_dependency=tool_dependency,
+ action_type=action_type,
+ action_elem=action_elem,
+ action_dict=action_dict,
+ install_environment=install_environment,
+ is_binary_download=is_binary_download )
+ action_tuple = ( action_type, action_dict )
+ if action_type == 'set_environment':
+ if action_tuple not in actions:
+ actions.append( action_tuple )
+ else:
+ actions.append( action_tuple )
+ if actions:
+ actions_dict[ 'actions' ] = actions
+ if custom_fabfile_path is not None:
+ # TODO: this is not yet supported or functional, but when it is handle it using the fabric api.
+ raise Exception( 'Tool dependency installation using proprietary fabric scripts is not yet supported.' )
+ else:
+ tool_dependency = self.install_and_build_package_via_fabric( app, tool_shed_repository, tool_dependency, actions_dict )
+ return tool_dependency
+
+ def install_package( self, app, elem, tool_shed_repository, tool_dependencies=None, from_tool_migration_manager=False ):
+ """
+ Install a tool dependency package defined by the XML element elem. The value of tool_dependencies is
+ a partial or full list of ToolDependency records associated with the tool_shed_repository.
+ """
+ tag_manager = TagManager()
+ sa_session = app.install_model.context
+ # The value of package_name should match the value of the "package" type in the tool config's
+ # <requirements> tag set, but it's not required.
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if tool_dependencies and package_name and package_version:
+ tool_dependency = None
+ for tool_dependency in tool_dependencies:
+ if package_name == str( tool_dependency.name ) and package_version == str( tool_dependency.version ):
+ break
+ if tool_dependency is not None:
+ for package_elem in elem:
+ tool_dependency, proceed_with_install, actions_elem_tuples = \
+ tag_manager.process_tag_set( app,
+ tool_shed_repository,
+ tool_dependency,
+ package_elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=from_tool_migration_manager,
+ tool_dependency_db_records=None )
+ if proceed_with_install and actions_elem_tuples:
+ # Get the installation directory for tool dependencies that will be installed for the received
+ # tool_shed_repository.
+ 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='package',
+ tool_dependency_name=package_name,
+ tool_dependency_version=package_version )
+ # At this point we have a list of <actions> elems that are either defined within an <actions_group>
+ # tag set with <actions> sub-elements that contains os and architecture attributes filtered by the
+ # platform into which the appropriate compiled binary will be installed, or not defined within an
+ # <actions_group> tag set and not filtered. Here is an example actions_elem_tuple.
+ # [(True, [<Element 'actions' at 0x109293d10>)]
+ binary_installed = False
+ for actions_elem_tuple in actions_elem_tuples:
+ in_actions_group, actions_elems = actions_elem_tuple
+ if in_actions_group:
+ # Platform matching is only performed inside <actions_group> tag sets, os and architecture
+ # attributes are otherwise ignored.
+ can_install_from_source = False
+ for actions_elem in actions_elems:
+ system = actions_elem.get( 'os' )
+ architecture = actions_elem.get( 'architecture' )
+ # If this <actions> element has the os and architecture attributes defined, then we only
+ # want to process until a successful installation is achieved.
+ if system and architecture:
+ # If an <actions> tag has been defined that matches our current platform, and the
+ # recipe specified within that <actions> tag has been successfully processed, skip
+ # any remaining platform-specific <actions> tags. We cannot break out of the loop
+ # here because there may be <action> tags at the end of the <actions_group> tag set
+ # that must be processed.
+ if binary_installed:
+ continue
+ # No platform-specific <actions> recipe has yet resulted in a successful installation.
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=actions_elem,
+ action_elem=None )
+ if tool_dependency.status == app.install_model.ToolDependency.installation_status.INSTALLED:
+ # If an <actions> tag was found that matches the current platform, and
+ # self.install_via_fabric() did not result in an error state, set binary_installed
+ # to True in order to skip any remaining platform-specific <actions> tags.
+ binary_installed = True
+ else:
+ # Process the next matching <actions> tag, or any defined <actions> tags that do not
+ # contain platform dependent recipes.
+ log.debug( 'Error downloading binary for tool dependency %s version %s: %s' % \
+ ( str( package_name ), str( package_version ), str( tool_dependency.error_message ) ) )
+ else:
+ if actions_elem.tag == 'actions':
+ # We've reached an <actions> tag that defines the recipe for installing and compiling from
+ # source. If binary installation failed, we proceed with the recipe.
+ if not binary_installed:
+ installation_directory = tool_dependency.installation_directory( app )
+ if os.path.exists( installation_directory ):
+ # Delete contents of installation directory if attempt at binary installation failed.
+ installation_directory_contents = os.listdir( installation_directory )
+ if installation_directory_contents:
+ removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
+ if removed:
+ can_install_from_source = True
+ else:
+ log.debug( 'Error removing old files from installation directory %s: %s' % \
+ ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
+ else:
+ can_install_from_source = True
+ else:
+ can_install_from_source = True
+ if can_install_from_source:
+ # We now know that binary installation was not successful, so proceed with the <actions>
+ # tag set that defines the recipe to install and compile from source.
+ log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % \
+ str( tool_dependency.name ) )
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=actions_elem,
+ action_elem=None )
+ if actions_elem.tag == 'action' and \
+ tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
+ # If the tool dependency is not in an error state, perform any final actions that have been
+ # defined within the actions_group tag set, but outside of an <actions> tag, which defines
+ # the recipe for installing and compiling from source.
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=None,
+ action_elem=actions_elem )
+ else:
+ # Checks for "os" and "architecture" attributes are not made for any <actions> tag sets outside of
+ # an <actions_group> tag set. If the attributes are defined, they will be ignored. All <actions> tags
+ # outside of an <actions_group> tag set will always be processed.
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=actions_elems,
+ action_elem=None )
+ if tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
+ log.debug( 'Tool dependency %s version %s has been installed in %s.' % \
+ ( str( package_name ), str( package_version ), str( install_dir ) ) )
+ return tool_dependency
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -20,7 +20,10 @@
from tool_shed.util import metadata_util
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
-from xml.etree import ElementTree as XmlET
+from tool_shed.util import xml_util
+
+from tool_shed.galaxy_install.install_manager import InstallManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
from galaxy import eggs
eggs.require( 'mercurial' )
@@ -621,11 +624,58 @@
trans.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', install_dir )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=trans.app,
- tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_shed_repository.tool_dependencies,
- from_tool_migration_manager=False )
+ # Parse the tool_dependencies.xml config.
+ tree, error_message = xml_util.parse_xml( tool_dependencies_config )
+ install_manager = InstallManager()
+ tag_manager = TagManager()
+ root = tree.getroot()
+ for elem in root:
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if package_name and package_version:
+ repository_tool_dependencies = util.listify( tool_shed_repository.tool_dependencies )
+ # elem is a package tag set.
+ attr_tups_of_dependencies_for_install = [ ( td.name, td.version, td.type ) for td in repository_tool_dependencies ]
+ attr_tup = ( package_name, package_version, 'package' )
+ try:
+ index = attr_tups_of_dependencies_for_install.index( attr_tup )
+ except Exception, e:
+ index = None
+ if index is not None:
+ tool_dependency = repository_tool_dependencies[ index ]
+ tool_dependency, proceed_with_install, action_elem_tuples = \
+ tag_manager.process_tag_set( trans.app,
+ tool_shed_repository,
+ tool_dependency,
+ elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=False,
+ tool_dependency_db_records=repository_tool_dependencies )
+ if proceed_with_install:
+ try:
+ tool_dependency = install_manager.install_package( trans.app,
+ elem,
+ tool_shed_repository,
+ tool_dependencies=repository_tool_dependencies,
+ from_tool_migration_manager=False )
+ except Exception, e:
+ error_message = "Error installing tool dependency package %s version %s: %s" % \
+ ( str( package_name ), str( package_version ), str( e ) )
+ log.exception( error_message )
+ if tool_dependency:
+ # Since there was an installation error, update the tool dependency status to Error. The
+ # remove_installation_path option must be left False here.
+ tool_dependency = \
+ tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ if tool_dependency and tool_dependency.status in [ trans.app.install_model.ToolDependency.installation_status.INSTALLED,
+ trans.app.install_model.ToolDependency.installation_status.ERROR ]:
+ if trans.app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ trans.app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
suc.remove_dir( work_dir )
suc.update_tool_shed_repository_status( trans.app,
tool_shed_repository,
@@ -877,11 +927,61 @@
trans.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repository.repo_path( trans.app ) )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=trans.app,
- tool_shed_repository=repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=repository.tool_dependencies,
- from_tool_migration_manager=False )
+ installed_tool_dependencies = []
+ # Parse the tool_dependencies.xml config.
+ tree, error_message = xml_util.parse_xml( tool_dependencies_config )
+ if tree is None:
+ return installed_tool_dependencies
+ install_manager = InstallManager()
+ tag_manager = TagManager()
+ root = tree.getroot()
+ for elem in root:
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if package_name and package_version:
+ # elem is a package tag set.
+ attr_tups_of_dependencies_for_install = [ ( td.name, td.version, td.type ) for td in tool_dependencies ]
+ attr_tup = ( package_name, package_version, 'package' )
+ try:
+ index = attr_tups_of_dependencies_for_install.index( attr_tup )
+ except Exception, e:
+ index = None
+ if index is not None:
+ tool_dependency = tool_dependency_db_records[ index ]
+ tool_dependency, proceed_with_install, action_elem_tuples = \
+ tag_manager.process_tag_set( trans.app,
+ tool_shed_repository,
+ tool_dependency,
+ elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=False,
+ tool_dependency_db_records=tool_dependencies )
+ if proceed_with_install:
+ try:
+ tool_dependency = install_manager.install_package( trans.app,
+ elem,
+ tool_shed_repository,
+ tool_dependencies=tool_dependencies,
+ from_tool_migration_manager=False )
+ except Exception, e:
+ error_message = "Error installing tool dependency package %s version %s: %s" % \
+ ( str( package_name ), str( package_version ), str( e ) )
+ log.exception( error_message )
+ if tool_dependency:
+ # Since there was an installation error, update the tool dependency status to Error. The
+ # remove_installation_path option must be left False here.
+ tool_dependency = \
+ tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ if tool_dependency and tool_dependency.status in [ app.install_model.ToolDependency.installation_status.INSTALLED,
+ app.install_model.ToolDependency.installation_status.ERROR ]:
+ installed_tool_dependencies.append( tool_dependency )
+ if app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
for installed_tool_dependency in installed_tool_dependencies:
if installed_tool_dependency.status in [ trans.install_model.ToolDependency.installation_status.ERROR ]:
repair_dict = add_repair_dict_entry( repository.name, installed_tool_dependency.error_message )
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ /dev/null
@@ -1,103 +0,0 @@
-import logging
-import os
-
-from galaxy import eggs
-
-eggs.require( 'paramiko' )
-eggs.require( 'ssh' )
-eggs.require( 'Fabric' )
-
-from fabric.api import env
-from fabric.api import lcd
-
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import EnvFileBuilder
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import InstallEnvironment
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import RecipeManager
-
-log = logging.getLogger( __name__ )
-
-INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environmnet',
- 'setup_r_environmnet', 'setup_ruby_environmnet', 'shell_command' ]
-
-def check_fabric_version():
- version = env.version
- if int( version.split( "." )[ 0 ] ) < 1:
- raise NotImplementedError( "Install Fabric version 1.0 or later." )
-
-def get_tool_shed_repository_install_dir( app, tool_shed_repository ):
- return os.path.abspath( tool_shed_repository.repo_files_directory( app ) )
-
-def install_and_build_package( app, tool_shed_repository, tool_dependency, actions_dict ):
- """Install a Galaxy tool dependency package either via a url or a mercurial or git clone command."""
- tool_shed_repository_install_dir = get_tool_shed_repository_install_dir( app, tool_shed_repository )
- install_dir = actions_dict[ 'install_dir' ]
- package_name = actions_dict[ 'package_name' ]
- actions = actions_dict.get( 'actions', None )
- filtered_actions = []
- env_file_builder = EnvFileBuilder( install_dir )
- install_environment = InstallEnvironment( tool_shed_repository_install_dir=tool_shed_repository_install_dir,
- install_dir=install_dir )
- recipe_manager = RecipeManager()
- if actions:
- with install_environment.make_tmp_dir() as work_dir:
- with lcd( work_dir ):
- # The first action in the list of actions will be the one that defines the initial download process.
- # There are currently three supported actions; download_binary, download_by_url and clone via a
- # shell_command action type. The recipe steps will be filtered at this stage in the process, with
- # the filtered actions being used in the next stage below. The installation directory (i.e., dir)
- # is also defined in this stage and is used in the next stage below when defining current_dir.
- action_type, action_dict = actions[ 0 ]
- if action_type in INSTALL_ACTIONS:
- # Some of the parameters passed here are needed only by a subset of the step handler classes,
- # but to allow for a standard method signature we'll pass them along. We don't check the
- # tool_dependency status in this stage because it should not have been changed based on a
- # download.
- tool_dependency, filtered_actions, dir = \
- recipe_manager.execute_step( app=app,
- tool_dependency=tool_dependency,
- package_name=package_name,
- actions=actions,
- action_type=action_type,
- action_dict=action_dict,
- filtered_actions=filtered_actions,
- env_file_builder=env_file_builder,
- install_environment=install_environment,
- work_dir=work_dir,
- current_dir=None,
- initial_download=True )
- else:
- # We're handling a complex repository dependency where we only have a set_environment tag set.
- # <action type="set_environment">
- # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
- # </action>
- filtered_actions = [ a for a in actions ]
- dir = install_dir
- # We're in stage 2 of the installation process. The package has been down-loaded, so we can
- # now perform all of the actions defined for building it.
- for action_tup in filtered_actions:
- current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
- with lcd( current_dir ):
- action_type, action_dict = action_tup
- tool_dependency, tmp_filtered_actions, tmp_dir = \
- recipe_manager.execute_step( app=app,
- tool_dependency=tool_dependency,
- package_name=package_name,
- actions=actions,
- action_type=action_type,
- action_dict=action_dict,
- filtered_actions=filtered_actions,
- env_file_builder=env_file_builder,
- install_environment=install_environment,
- work_dir=work_dir,
- current_dir=current_dir,
- initial_download=False )
- if tool_dependency.status in [ app.install_model.ToolDependency.installation_status.ERROR ]:
- # If the tool_dependency status is in an error state, return it with no additional
- # processing.
- return tool_dependency
- # Make sure to handle the special case where the value of dir is reset (this happens when
- # the action_type is change_directiory). In all other action types, dir will be returned as
- # None.
- if tmp_dir is not None:
- dir = tmp_dir
- return tool_dependency
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ /dev/null
@@ -1,734 +0,0 @@
-import logging
-import os
-import shutil
-import stat
-import subprocess
-import sys
-import tempfile
-import fabric_util
-import td_common_util
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import EnvFileBuilder
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import InstallEnvironment
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import RecipeManager
-import tool_shed.util.shed_util_common as suc
-from tool_shed.util import common_util
-from tool_shed.util import encoding_util
-from tool_shed.util import tool_dependency_util
-from tool_shed.util import xml_util
-from tool_shed.galaxy_install.tool_dependencies import td_common_util
-from galaxy.model.orm import and_
-from galaxy.util import asbool
-from galaxy.util import listify
-
-log = logging.getLogger( __name__ )
-
-def create_temporary_tool_dependencies_config( app, tool_shed_url, name, owner, changeset_revision ):
- """Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
- tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
- params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
- url = common_util.url_join( tool_shed_url,
- 'repository/get_tool_dependencies_config_contents%s' % params )
- text = common_util.tool_shed_get( app, tool_shed_url, url )
- if text:
- # Write the contents to a temporary file on disk so it can be reloaded and parsed.
- fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-cttdc" )
- tmp_filename = fh.name
- fh.close()
- fh = open( tmp_filename, 'wb' )
- fh.write( text )
- fh.close()
- return tmp_filename
- else:
- message = "Unable to retrieve required tool_dependencies.xml file from the tool shed for revision "
- message += "%s of installed repository %s owned by %s." % ( str( changeset_revision ), str( name ), str( owner ) )
- raise Exception( message )
- return None
-
-def create_tool_dependency_with_initialized_env_sh_file( app, dependent_install_dir, tool_shed_repository, required_repository, package_name,
- package_version, tool_dependencies_config ):
- """
- Create or get a tool_dependency record that is defined by the received package_name and package_version. An env.sh file will be
- created for the tool_dependency in the received dependent_install_dir.
- """
- #The received required_repository refers to a tool_shed_repository record that is defined as a complex repository dependency for this
- # tool_dependency. The required_repository may or may not be currently installed (it doesn't matter). If it is installed, it is
- # associated with a tool_dependency that has an env.sh file that this new tool_dependency must be able to locate and "source". If it
- # is not installed, we can still determine where that env.sh file will be, so we'll initialize this new tool_dependency's env.sh file
- # in either case. If the require repository end up with an installation error, this new tool dependency will still be fine because its
- # containing repository will be defined as missing dependencies.
- tool_dependencies = []
- if not os.path.exists( dependent_install_dir ):
- os.makedirs( dependent_install_dir )
- required_tool_dependency_env_file_path = None
- if tool_dependencies_config:
- required_td_tree, error_message = xml_util.parse_xml( tool_dependencies_config )
- if required_td_tree:
- required_td_root = required_td_tree.getroot()
- for required_td_elem in required_td_root:
- # Find the appropriate package name and version.
- if required_td_elem.tag == 'package':
- # <package name="bwa" version="0.5.9">
- required_td_package_name = required_td_elem.get( 'name', None )
- required_td_package_version = required_td_elem.get( 'version', None )
- # Check the database to see if we have a record for the required tool dependency (we may not which is ok). If we
- # find a record, we need to see if it is in an error state and if so handle it appropriately.
- required_tool_dependency = \
- tool_dependency_util.get_tool_dependency_by_name_version_type_repository( app,
- required_repository,
- required_td_package_name,
- required_td_package_version,
- 'package' )
- if required_td_package_name == package_name and required_td_package_version == package_version:
- # Get or create a database tool_dependency record with which the installed package on disk will be associated.
- tool_dependency = \
- tool_dependency_util.create_or_update_tool_dependency( app=app,
- tool_shed_repository=tool_shed_repository,
- name=package_name,
- version=package_version,
- type='package',
- status=app.install_model.ToolDependency.installation_status.NEVER_INSTALLED,
- set_status=True )
- # Create an env.sh file for the tool_dependency whose first line will source the env.sh file located in
- # the path defined by required_tool_dependency_env_file_path. It doesn't matter if the required env.sh
- # file currently exists..
- required_tool_dependency_env_file_path = \
- tool_dependency_util.get_required_repository_package_env_sh_path( app,
- package_name,
- package_version,
- required_repository )
- env_file_builder = EnvFileBuilder( tool_dependency.installation_directory( app ) )
- env_file_builder.append_line( action="source", value=required_tool_dependency_env_file_path )
- return_code = env_file_builder.return_code
- if return_code:
- error_message = 'Error defining env.sh file for package %s, return_code: %s' % \
- ( str( package_name ), str( return_code ) )
- tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- elif required_tool_dependency is not None and required_tool_dependency.in_error_state:
- error_message = "This tool dependency's required tool dependency %s version %s has status %s." % \
- ( str( required_tool_dependency.name ), str( required_tool_dependency.version ), str( required_tool_dependency.status ) )
- tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- else:
- tool_dependency = \
- tool_dependency_util.set_tool_dependency_attributes( app,
- tool_dependency=tool_dependency,
- status=app.install_model.ToolDependency.installation_status.INSTALLED )
- tool_dependencies.append( tool_dependency )
- return tool_dependencies
-
-def get_absolute_path_to_file_in_repository( repo_files_dir, file_name ):
- """Return the absolute path to a specified disk file contained in a repository."""
- stripped_file_name = strip_path( file_name )
- file_path = None
- for root, dirs, files in os.walk( repo_files_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == stripped_file_name:
- return os.path.abspath( os.path.join( root, name ) )
- return file_path
-
-def get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app, tool_shed_url, name, owner, changeset_revision ):
- sa_session = app.install_model.context
- # The protocol is not stored, but the port is if it exists.
- tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed_url )
- tool_shed_repository = sa_session.query( app.install_model.ToolShedRepository ) \
- .filter( and_( app.install_model.ToolShedRepository.table.c.tool_shed == tool_shed,
- app.install_model.ToolShedRepository.table.c.name == name,
- app.install_model.ToolShedRepository.table.c.owner == owner,
- app.install_model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
- .first()
- if tool_shed_repository:
- return tool_shed_repository
- # The tool_shed_repository must have been updated to a newer changeset revision than the one defined in the repository_dependencies.xml file,
- # so call the tool shed to get all appropriate newer changeset revisions.
- text = get_updated_changeset_revisions_from_tool_shed( app, tool_shed_url, name, owner, changeset_revision )
- if text:
- changeset_revisions = listify( text )
- for changeset_revision in changeset_revisions:
- tool_shed_repository = sa_session.query( app.install_model.ToolShedRepository ) \
- .filter( and_( app.install_model.ToolShedRepository.table.c.tool_shed == tool_shed,
- app.install_model.ToolShedRepository.table.c.name == name,
- app.install_model.ToolShedRepository.table.c.owner == owner,
- app.install_model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
- .first()
- if tool_shed_repository:
- return tool_shed_repository
- return None
-
-def get_updated_changeset_revisions_from_tool_shed( app, tool_shed_url, name, owner, changeset_revision ):
- """
- Get all appropriate newer changeset revisions for the repository defined by
- the received tool_shed_url / name / owner combination.
- """
- tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
- params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
- url = common_util.url_join( tool_shed_url,
- 'repository/updated_changeset_revisions%s' % params )
- text = common_util.tool_shed_get( app, tool_shed_url, url )
- return text
-
-
-def handle_complex_repository_dependency_for_package( app, elem, package_name, package_version, tool_shed_repository, from_tool_migration_manager=False ):
- """
- Inspect the repository defined by a complex repository dependency definition and take certain steps to enable installation
- of the received package name and version to proceed. The received elem is the <repository> tag set which defines the complex
- repository dependency. The received tool_shed_repository is the installed tool shed repository for which the tool dependency
- defined by the received package_name and package_version is being installed.
- """
- handled_tool_dependencies = []
- tool_shed = elem.attrib[ 'toolshed' ]
- # The protocol is not stored, but the port is if it exists.
- tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
- required_repository_name = elem.attrib[ 'name' ]
- required_repository_owner = elem.attrib[ 'owner' ]
- default_required_repository_changeset_revision = elem.attrib[ 'changeset_revision' ]
- required_repository = get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app,
- tool_shed,
- required_repository_name,
- required_repository_owner,
- default_required_repository_changeset_revision )
- tmp_filename = None
- if required_repository:
- required_repository_changeset_revision = required_repository.installed_changeset_revision
- # Define the installation directory for the required tool dependency package in the required repository.
- required_repository_package_install_dir = \
- tool_dependency_util.get_tool_dependency_install_dir( app=app,
- repository_name=required_repository_name,
- repository_owner=required_repository_owner,
- repository_changeset_revision=required_repository_changeset_revision,
- tool_dependency_type='package',
- tool_dependency_name=package_name,
- tool_dependency_version=package_version )
- # Define this dependent repository's tool dependency installation directory that will contain the env.sh file with a path to the
- # required repository's installed tool dependency package.
- dependent_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='package',
- tool_dependency_name=package_name,
- tool_dependency_version=package_version )
- if os.path.exists( dependent_install_dir ):
- # The install manager handles tool migration stages and the sync_database_with_file_system()
- # method handles two scenarios: (1) where a Galaxy file system environment related to installed
- # Tool Shed repositories and tool dependencies has somehow gotten out of sync with the Galaxy
- # database tables associated with these installed items, and (2) the Tool Shed's install and test
- # framework which installs repositories in 2 stages, those of type tool_dependency_definition
- # followed by those containing valid tools and tool functional test components. Neither of these
- # scenarios apply when the install manager is running.
- if from_tool_migration_manager:
- can_install_tool_dependency = True
- else:
- # Notice that we'll throw away the following tool_dependency if it can be installed.
- tool_dependency, can_install_tool_dependency = \
- tool_dependency_util.sync_database_with_file_system( app,
- tool_shed_repository,
- package_name,
- package_version,
- dependent_install_dir,
- tool_dependency_type='package' )
- if not can_install_tool_dependency:
- log.debug( "Tool dependency %s version %s cannot be installed (it was probably previously installed), " % \
- ( str( tool_dependency.name, str( tool_dependency.version ) ) ) )
- log.debug( "so appending it to the list of handled tool dependencies." )
- handled_tool_dependencies.append( tool_dependency )
- else:
- can_install_tool_dependency = True
- if can_install_tool_dependency:
- # Set this dependent repository's tool dependency env.sh file with a path to the required repository's installed tool dependency package.
- # We can get everything we need from the discovered installed required_repository.
- if required_repository.is_deactivated_or_installed:
- if not os.path.exists( required_repository_package_install_dir ):
- print 'Missing required tool dependency directory %s' % str( required_repository_package_install_dir )
- repo_files_dir = required_repository.repo_files_directory( app )
- tool_dependencies_config = get_absolute_path_to_file_in_repository( repo_files_dir, 'tool_dependencies.xml' )
- if tool_dependencies_config:
- config_to_use = tool_dependencies_config
- else:
- message = "Unable to locate required tool_dependencies.xml file for revision %s of installed repository %s owned by %s." % \
- ( str( required_repository.changeset_revision ), str( required_repository.name ), str( required_repository.owner ) )
- raise Exception( message )
- else:
- # Make a call to the tool shed to get the changeset revision to which the current value of required_repository_changeset_revision
- # should be updated if it's not current.
- text = get_updated_changeset_revisions_from_tool_shed( app=app,
- tool_shed_url=tool_shed,
- name=required_repository_name,
- owner=required_repository_owner,
- changeset_revision=required_repository_changeset_revision )
- if text:
- updated_changeset_revisions = listify( text )
- # The list of changeset revisions is in reverse order, so the newest will be first.
- required_repository_changeset_revision = updated_changeset_revisions[ 0 ]
- # Make a call to the tool shed to get the required repository's tool_dependencies.xml file.
- tmp_filename = create_temporary_tool_dependencies_config( app,
- tool_shed,
- required_repository_name,
- required_repository_owner,
- required_repository_changeset_revision )
- config_to_use = tmp_filename
- handled_tool_dependencies = create_tool_dependency_with_initialized_env_sh_file( app=app,
- dependent_install_dir=dependent_install_dir,
- tool_shed_repository=tool_shed_repository,
- required_repository=required_repository,
- package_name=package_name,
- package_version=package_version,
- tool_dependencies_config=config_to_use )
- suc.remove_file( tmp_filename )
- else:
- message = "Unable to locate required tool shed repository named %s owned by %s with revision %s." % \
- ( str( required_repository_name ), str( required_repository_owner ), str( default_required_repository_changeset_revision ) )
- raise Exception( message )
- return handled_tool_dependencies
-
-def install_and_build_package_via_fabric( app, tool_shed_repository, tool_dependency, actions_dict ):
- sa_session = app.install_model.context
- try:
- # There is currently only one fabric method.
- tool_dependency = fabric_util.install_and_build_package( app, tool_shed_repository, tool_dependency, actions_dict )
- except Exception, e:
- log.exception( 'Error installing tool dependency %s version %s.', str( tool_dependency.name ), str( tool_dependency.version ) )
- # Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
- # be left False here.
- error_message = '%s\n%s' % ( td_common_util.format_traceback(), str( e ) )
- tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- tool_dependency = tool_dependency_util.mark_tool_dependency_installed( app, tool_dependency )
- return tool_dependency
-
-def install_package( app, elem, tool_shed_repository, tool_dependencies=None, from_tool_migration_manager=False ):
- """
- Install a tool dependency package defined by the XML element elem. The value of tool_dependencies is
- a partial or full list of ToolDependency records associated with the tool_shed_repository.
- """
- sa_session = app.install_model.context
- tool_dependency = None
- # The value of package_name should match the value of the "package" type in the tool config's <requirements> tag set, but it's not required.
- package_name = elem.get( 'name', None )
- package_version = elem.get( 'version', None )
- if tool_dependencies and package_name and package_version:
- for package_elem in elem:
- if package_elem.tag == 'repository':
- # We have a complex repository dependency definition.
- rd_tool_dependencies = handle_complex_repository_dependency_for_package( app,
- package_elem,
- package_name,
- package_version,
- tool_shed_repository,
- from_tool_migration_manager=from_tool_migration_manager )
- for rd_tool_dependency in rd_tool_dependencies:
- if rd_tool_dependency.status == app.install_model.ToolDependency.installation_status.ERROR:
- # We'll log the error here, but continue installing packages since some may not require this dependency.
- print "Error installing tool dependency for required repository: %s" % str( rd_tool_dependency.error_message )
- elif package_elem.tag == 'install':
- # <install version="1.0">
- # Get the installation directory for tool dependencies that will be installed for the received tool_shed_repository.
- 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='package',
- tool_dependency_name=package_name,
- tool_dependency_version=package_version )
- if os.path.exists( install_dir ):
- # The install manager handles tool migration stages and the sync_database_with_file_system()
- # method handles two scenarios: (1) where a Galaxy file system environment related to installed
- # Tool Shed repositories and tool dependencies has somehow gotten out of sync with the Galaxy
- # database tables associated with these installed items, and (2) the Tool Shed's install and test
- # framework which installs repositories in 2 stages, those of type tool_dependency_definition
- # followed by those containing valid tools and tool functional test components. Neither of these
- # scenarios apply when the install manager is running.
- if from_tool_migration_manager:
- can_install_tool_dependency = True
- else:
- # Notice that we'll throw away the following tool_dependency if it can be installed.
- tool_dependency, can_install_tool_dependency = \
- tool_dependency_util.sync_database_with_file_system( app,
- tool_shed_repository,
- package_name,
- package_version,
- install_dir,
- tool_dependency_type='package' )
- if not can_install_tool_dependency:
- log.debug( "Tool dependency %s version %s cannot be installed (it was probably previously installed), so returning it." % \
- ( str( tool_dependency.name ), str( tool_dependency.version ) ) )
- return tool_dependency
- else:
- can_install_tool_dependency = True
- if can_install_tool_dependency:
- package_install_version = package_elem.get( 'version', '1.0' )
- 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=package_name,
- version=package_version,
- type='package',
- status=status,
- set_status=True )
- # Get the information about the current platform in case the tool dependency definition includes tag sets
- # for installing compiled binaries.
- platform_info_dict = tool_dependency_util.get_platform_info_dict()
- if package_install_version == '1.0':
- # Handle tool dependency installation using a fabric method included in the Galaxy framework.
- actions_elem_tuples = td_common_util.parse_package_elem( package_elem,
- platform_info_dict=platform_info_dict,
- include_after_install_actions=True )
- if actions_elem_tuples:
- # At this point we have a list of <actions> elems that are either defined within an <actions_group>
- # tag set with <actions> sub-elements that contains os and architecture attributes filtered by the
- # platform into which the appropriate compiled binary will be installed, or not defined within an
- # <actions_group> tag set and not filtered. Here is an example actions_elem_tuple.
- # [(True, [<Element 'actions' at 0x109293d10>)]
- binary_installed = False
- for actions_elem_tuple in actions_elem_tuples:
- in_actions_group, actions_elems = actions_elem_tuple
- if in_actions_group:
- # Platform matching is only performed inside <actions_group> tag sets, os and architecture
- # attributes are otherwise ignored.
- can_install_from_source = False
- for actions_elem in actions_elems:
- system = actions_elem.get( 'os' )
- architecture = actions_elem.get( 'architecture' )
- # If this <actions> element has the os and architecture attributes defined, then we only
- # want to process until a successful installation is achieved.
- if system and architecture:
- # If an <actions> tag has been defined that matches our current platform, and the
- # recipe specified within that <actions> tag has been successfully processed, skip
- # any remaining platform-specific <actions> tags. We cannot break out of the loop
- # here because there may be <action> tags at the end of the <actions_group> tag set
- # that must be processed.
- if binary_installed:
- continue
- # No platform-specific <actions> recipe has yet resulted in a successful installation.
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=actions_elem,
- action_elem=None )
- if tool_dependency.status == app.install_model.ToolDependency.installation_status.INSTALLED:
- # If an <actions> tag was found that matches the current platform, and the
- # install_via_fabric method did not result in an error state, set binary_installed
- # to True in order to skip any remaining platform-specific <actions> tags.
- binary_installed = True
- else:
- # Process the next matching <actions> tag, or any defined <actions> tags that do not
- # contain platform dependent recipes.
- log.debug( 'Error downloading binary for tool dependency %s version %s: %s' % \
- ( str( package_name ), str( package_version ), str( tool_dependency.error_message ) ) )
- else:
- if actions_elem.tag == 'actions':
- # We've reached an <actions> tag that defines the recipe for installing and compiling from
- # source. If binary installation failed, we proceed with the recipe.
- if not binary_installed:
- installation_directory = tool_dependency.installation_directory( app )
- if os.path.exists( installation_directory ):
- # Delete contents of installation directory if attempt at binary installation failed.
- installation_directory_contents = os.listdir( installation_directory )
- if installation_directory_contents:
- removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
- if removed:
- can_install_from_source = True
- else:
- log.debug( 'Error removing old files from installation directory %s: %s' % \
- ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
- else:
- can_install_from_source = True
- else:
- can_install_from_source = True
- if can_install_from_source:
- # We now know that binary installation was not successful, so proceed with the <actions>
- # tag set that defines the recipe to install and compile from source.
- log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % \
- str( tool_dependency.name ) )
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=actions_elem,
- action_elem=None )
- if actions_elem.tag == 'action' and tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
- # If the tool dependency is not in an error state, perform any final actions that have been
- # defined within the actions_group tag set, but outside of an <actions> tag, which defines
- # the recipe for installing and compiling from source.
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=None,
- action_elem=actions_elem )
- else:
- # Checks for "os" and "architecture" attributes are not made for any <actions> tag sets outside of
- # an <actions_group> tag set. If the attributes are defined, they will be ignored. All <actions> tags
- # outside of an <actions_group> tag set will always be processed.
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=actions_elems,
- action_elem=None )
- if tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
- log.debug( 'Tool dependency %s version %s has been installed in %s.' % \
- ( str( package_name ), str( package_version ), str( install_dir ) ) )
- else:
- error_message = 'Version %s of the %s package cannot be installed because ' % ( str( package_version ), str( package_name ) )
- error_message += 'the recipe for installing the package is missing either an <actions> tag set or an <actions_group> '
- error_message += 'tag set.'
- # Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
- # be left False here.
- tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- return tool_dependency
- else:
- raise NotImplementedError( 'Only install version 1.0 is currently supported (i.e., change your tag to be <install version="1.0">).' )
- elif package_elem.tag == 'readme':
- # Nothing to be done.
- continue
- #elif package_elem.tag == 'custom_fabfile':
- # # TODO: This is not yet supported or functionally correct...
- # # Handle tool dependency installation where the repository includes one or more custom fabric scripts.
- # if not fabric_version_checked:
- # check_fabric_version()
- # fabric_version_checked = True
- # fabfile_name = package_elem.get( 'name', None )
- # custom_fabfile_path = os.path.abspath( os.path.join( os.path.split( tool_dependencies_config )[ 0 ], fabfile_name ) )
- # print 'Installing tool dependencies via fabric script ', custom_fabfile_path
- return tool_dependency
-
-def install_via_fabric( app, tool_shed_repository, tool_dependency, install_dir, package_name=None, custom_fabfile_path=None,
- actions_elem=None, action_elem=None, **kwd ):
- """
- Parse a tool_dependency.xml file's <actions> tag set to gather information for installation using the
- fabric_util.install_and_build_package() method. The use of fabric is being eliminated, so some of these
- functions may need to be renamed at some point.
- """
- sa_session = app.install_model.context
- if not os.path.exists( install_dir ):
- os.makedirs( install_dir )
- actions_dict = dict( install_dir=install_dir )
- if package_name:
- actions_dict[ 'package_name' ] = package_name
- actions = []
- is_binary_download = False
- if actions_elem is not None:
- elems = actions_elem
- if elems.get( 'os' ) is not None and elems.get( 'architecture' ) is not None:
- is_binary_download = True
- elif action_elem is not None:
- # We were provided with a single <action> element to perform certain actions after a platform-specific tarball was downloaded.
- elems = [ action_elem ]
- else:
- elems = []
- recipe_manager = RecipeManager()
- tool_shed_repository_install_dir = fabric_util.get_tool_shed_repository_install_dir( app, tool_shed_repository )
- install_environment = InstallEnvironment( tool_shed_repository_install_dir, install_dir )
- for action_elem in elems:
- # Make sure to skip all comments, since they are now included in the XML tree.
- if action_elem.tag != 'action':
- continue
- action_dict = {}
- action_type = action_elem.get( 'type', None )
- if action_type is not None:
- action_dict = recipe_manager.prepare_step( app=app,
- tool_dependency=tool_dependency,
- action_type=action_type,
- action_elem=action_elem,
- action_dict=action_dict,
- install_environment=install_environment,
- is_binary_download=is_binary_download )
- action_tuple = ( action_type, action_dict )
- if action_type == 'set_environment':
- if action_tuple not in actions:
- actions.append( action_tuple )
- else:
- actions.append( action_tuple )
- if actions:
- actions_dict[ 'actions' ] = actions
- if custom_fabfile_path is not None:
- # TODO: this is not yet supported or functional, but when it is handle it using the fabric api.
- # execute_custom_fabric_script( app, elem, custom_fabfile_path, install_dir, package_name=package_name )
- raise Exception( 'Tool dependency installation using proprietary fabric scripts is not yet supported.' )
- else:
- tool_dependency = install_and_build_package_via_fabric( app, tool_shed_repository, tool_dependency, actions_dict )
- return tool_dependency
-
-def execute_custom_fabric_script( app, elem, custom_fabfile_path, install_dir, package_name=None, **kwd ):
- """
- TODO: Handle this using the fabric api.
- Parse a tool_dependency.xml file's fabfile <method> tag set to build the method parameters and execute the method.
- """
- if not os.path.exists( install_dir ):
- os.makedirs( install_dir )
- # Default value for env_dependency_path.
- env_dependency_path = install_dir
- method_name = elem.get( 'name', None )
- params_str = ''
- actions = []
- for param_elem in elem:
- param_name = param_elem.get( 'name' )
- if param_name:
- if param_name == 'actions':
- for action_elem in param_elem:
- actions.append( action_elem.text.replace( '$INSTALL_DIR', install_dir ) )
- if actions:
- params_str += 'actions=%s,' % encoding_util.tool_shed_encode( encoding_util.encoding_sep.join( actions ) )
- else:
- if param_elem.text:
- param_value = encoding_util.tool_shed_encode( param_elem.text )
- params_str += '%s=%s,' % ( param_name, param_value )
- if package_name:
- params_str += 'package_name=%s' % package_name
- else:
- params_str = params_str.rstrip( ',' )
- try:
- cmd = 'fab -f %s %s:%s' % ( custom_fabfile_path, method_name, params_str )
- returncode, message = run_subprocess( app, cmd )
- except Exception, e:
- return "Exception executing fabric script %s: %s. " % ( str( custom_fabfile_path ), str( e ) )
- if returncode:
- return message
- handle_environment_settings( app, tool_dependency, install_dir, cmd )
-
-def run_subprocess( app, cmd ):
- env = os.environ
- PYTHONPATH = env.get( 'PYTHONPATH', '' )
- if PYTHONPATH:
- env[ 'PYTHONPATH' ] = '%s:%s' % ( os.path.abspath( os.path.join( app.config.root, 'lib' ) ), PYTHONPATH )
- else:
- env[ 'PYTHONPATH' ] = os.path.abspath( os.path.join( app.config.root, 'lib' ) )
- message = ''
- tmp_name = tempfile.NamedTemporaryFile( prefix="tmp-toolshed-rs" ).name
- tmp_stderr = open( tmp_name, 'wb' )
- proc = subprocess.Popen( cmd, shell=True, env=env, stderr=tmp_stderr.fileno() )
- returncode = proc.wait()
- tmp_stderr.close()
- if returncode:
- tmp_stderr = open( tmp_name, 'rb' )
- message = '%s\n' % str( tmp_stderr.read() )
- tmp_stderr.close()
- suc.remove_file( tmp_name )
- return returncode, message
-
-def set_environment( app, elem, tool_shed_repository, attr_tups_of_dependencies_for_install ):
- """
- Create a ToolDependency to set an environment variable. This is different from the process used to
- set an environment variable that is associated with a package. An example entry in a tool_dependencies.xml
- file is::
-
- <set_environment version="1.0">
- <environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable>
- </set_environment>
- """
- # TODO: Add support for a repository dependency definition within this tool dependency type's tag set. This should look something like
- # the following. See the implementation of support for this in the tool dependency package type's method above.
- # This function is only called for set environment actions as defined below, not within an <install version="1.0"> tool
- # dependency type. Here is an example of the tag set this function does handle:
- # <action type="set_environment">
- # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR</environment_variable>
- # </action>
- # Here is an example of the tag set this function does not handle:
- # <set_environment version="1.0">
- # <repository toolshed="<tool shed>" name="<repository name>" owner="<repository owner>" changeset_revision="<changeset revision>" />
- # </set_environment>
- sa_session = app.install_model.context
- 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 )
- 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 )
- # The value of env_var_name must match the text value of at least 1 <requirement> tag in the tool config's <requirements> tag set whose
- # "type" attribute is "set_environment" (e.g., <requirement type="set_environment">R_SCRIPT_PATH</requirement>).
- env_var_action = env_var_elem.get( 'action', None )
- if env_var_name and env_var_action:
- # Tool dependencies of type "set_environmnet" always have the version attribute set to None.
- attr_tup = ( env_var_name, None, 'set_environment' )
- if attr_tup in attr_tups_of_dependencies_for_install:
- 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 )
- install_environment = InstallEnvironment( tool_shed_repository_install_dir=tool_shed_repository_install_dir,
- install_dir=install_dir )
- env_var_dict = td_common_util.create_env_var_dict( elem=env_var_elem,
- install_environment=install_environment )
- if env_var_dict:
- 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 )
- if env_var_version == '1.0':
- # Create this tool dependency's env.sh file.
- 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 ) ) )
- else:
- error_message = 'Only set_environment version 1.0 is currently supported (i.e., change your tag to be <set_environment version="1.0">).'
- 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 )
- tool_dependencies.append( tool_dependency )
- return tool_dependencies
-
-def strip_path( fpath ):
- if not fpath:
- return fpath
- try:
- file_path, file_name = os.path.split( fpath )
- except:
- file_name = fpath
- return file_name
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/recipe/asynchronous_reader.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/asynchronous_reader.py
@@ -0,0 +1,32 @@
+import logging
+import os
+import threading
+
+log = logging.getLogger( __name__ )
+
+
+class AsynchronousReader( threading.Thread ):
+ """
+ A helper class to implement asynchronous reading of a stream in a separate thread. Read lines are pushed
+ onto a queue to be consumed in another thread.
+ """
+
+ def __init__( self, fd, queue ):
+ threading.Thread.__init__( self )
+ self._fd = fd
+ self._queue = queue
+ self.lines = []
+
+ def run( self ):
+ """Read lines and put them on the queue."""
+ thread_lock = threading.Lock()
+ thread_lock.acquire()
+ for line in iter( self._fd.readline, '' ):
+ stripped_line = line.rstrip()
+ self.lines.append( stripped_line )
+ self._queue.put( stripped_line )
+ thread_lock.release()
+
+ def installation_complete( self ):
+ """Make sure there is more installation and compilation logging content expected."""
+ return not self.is_alive() and self._queue.empty()
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py
@@ -0,0 +1,95 @@
+import logging
+import os
+import stat
+
+log = logging.getLogger( __name__ )
+
+
+class EnvFileBuilder( object ):
+
+ def __init__( self, install_dir ):
+ self.install_dir = install_dir
+ self.return_code = 0
+
+ def append_line( self, make_executable=True, **kwd ):
+ env_var_dict = dict( **kwd )
+ env_entry, env_file = self.create_or_update_env_shell_file( self.install_dir, env_var_dict )
+ return_code = self.file_append( env_entry, env_file, make_executable=make_executable )
+ self.return_code = self.return_code or return_code
+ return self.return_code
+
+ @staticmethod
+ def create_or_update_env_shell_file( install_dir, env_var_dict ):
+ env_var_action = env_var_dict[ 'action' ]
+ env_var_value = env_var_dict[ 'value' ]
+ if env_var_action in [ 'prepend_to', 'set_to', 'append_to' ]:
+ env_var_name = env_var_dict[ 'name' ]
+ if env_var_action == 'prepend_to':
+ changed_value = '%s:$%s' % ( env_var_value, env_var_name )
+ elif env_var_action == 'set_to':
+ changed_value = '%s' % env_var_value
+ elif env_var_action == 'append_to':
+ changed_value = '$%s:%s' % ( env_var_name, env_var_value )
+ line = "%s=%s; export %s" % ( env_var_name, changed_value, env_var_name )
+ elif env_var_action == "source":
+ line = "if [ -f %s ] ; then . %s ; fi" % ( env_var_value, env_var_value )
+ else:
+ raise Exception( "Unknown shell file action %s" % env_var_action )
+ env_shell_file_path = os.path.join( install_dir, 'env.sh' )
+ return line, env_shell_file_path
+
+ def file_append( self, text, file_path, make_executable=True ):
+ """
+ Append a line to a file unless the line already exists in the file. This method creates the file if
+ it doesn't exist. If make_executable is True, the permissions on the file are set to executable by
+ the owner.
+ """
+ file_dir = os.path.dirname( file_path )
+ if not os.path.exists( file_dir ):
+ try:
+ os.makedirs( file_dir )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ if os.path.exists( file_path ):
+ try:
+ new_env_file_contents = []
+ env_file_contents = file( file_path, 'r' ).readlines()
+ # Clean out blank lines from the env.sh file.
+ for line in env_file_contents:
+ line = line.rstrip()
+ if line:
+ new_env_file_contents.append( line )
+ env_file_contents = new_env_file_contents
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ else:
+ env_file_handle = open( file_path, 'w' )
+ env_file_handle.close()
+ env_file_contents = []
+ if make_executable:
+ # Explicitly set the file's executable bits.
+ try:
+ os.chmod( file_path, int( '111', base=8 ) | os.stat( file_path )[ stat.ST_MODE ] )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ # Convert the received text to a list, in order to support adding one or more lines to the file.
+ if isinstance( text, basestring ):
+ text = [ text ]
+ for line in text:
+ line = line.rstrip()
+ if line and line not in env_file_contents:
+ env_file_contents.append( line )
+ try:
+ file( file_path, 'w' ).write( '\n'.join( env_file_contents ) )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ return 0
+
+ def handle_action_shell_file_paths( self, action_dict ):
+ shell_file_paths = action_dict.get( 'action_shell_file_paths', [] )
+ for shell_file_path in shell_file_paths:
+ self.append_line( action="source", value=shell_file_path )
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py
@@ -0,0 +1,273 @@
+import logging
+import os
+import Queue
+import shutil
+import subprocess
+import tempfile
+import threading
+import time
+from contextlib import contextmanager
+
+# TODO: eliminate the use of fabric here.
+from galaxy import eggs
+
+eggs.require( 'paramiko' )
+eggs.require( 'ssh' )
+eggs.require( 'Fabric' )
+
+from fabric.operations import _AttributeString
+from fabric import state
+from fabric.api import prefix
+
+from galaxy.util import DATABASE_MAX_STRING_SIZE
+from galaxy.util import DATABASE_MAX_STRING_SIZE_PRETTY
+from galaxy.util import shrink_string_by_size
+from galaxy.util import unicodify
+
+from tool_shed.galaxy_install.tool_dependencies import td_common_util
+from tool_shed.galaxy_install.tool_dependencies.recipe import asynchronous_reader
+
+log = logging.getLogger( __name__ )
+
+class InstallEnvironment( object ):
+ """Object describing the environment built up as part of the process of building and installing a package."""
+
+
+ def __init__( self, tool_shed_repository_install_dir, install_dir ):
+ """
+ The value of the received tool_shed_repository_install_dir is the root installation directory
+ of the repository containing the tool dependency, and the value of the received install_dir is
+ the root installation directory of the tool dependency.
+ """
+ self.env_shell_file_paths = []
+ self.install_dir = install_dir
+ self.tool_shed_repository_install_dir = tool_shed_repository_install_dir
+
+ def __call__( self ):
+ with settings( warn_only=True, **td_common_util.get_env_var_values( self ) ):
+ with prefix( self.__setup_environment() ):
+ yield
+
+ def add_env_shell_file_paths( self, paths ):
+ for path in paths:
+ self.env_shell_file_paths.append( str( path ) )
+
+ def build_command( self, command, action_type='shell_command' ):
+ """
+ Build command line for execution from simple command, but
+ configuring environment described by this object.
+ """
+ env_cmds = self.environment_commands( action_type )
+ return '\n'.join( env_cmds + [ command ] )
+
+ def close_file_descriptor( self, fd ):
+ """Attempt to close a file descriptor."""
+ start_timer = time.time()
+ error = ''
+ while True:
+ try:
+ fd.close()
+ break
+ except IOError, e:
+ # Undoubtedly close() was called during a concurrent operation on the same file object.
+ log.debug( 'Error closing file descriptor: %s' % str( e ) )
+ time.sleep( .5 )
+ current_wait_time = time.time() - start_timer
+ if current_wait_time >= 600:
+ error = 'Error closing file descriptor: %s' % str( e )
+ break
+ return error
+
+ def enqueue_output( self, stdout, stdout_queue, stderr, stderr_queue ):
+ """
+ This method places streamed stdout and stderr into a threaded IPC queue target. Received data
+ is printed and saved to that thread's queue. The calling thread can then retrieve the data using
+ thread.stdout and thread.stderr.
+ """
+ stdout_logger = logging.getLogger( 'install_environment.STDOUT' )
+ stderr_logger = logging.getLogger( 'install_environment.STDERR' )
+ for line in iter( stdout.readline, '' ):
+ output = line.rstrip()
+ stdout_logger.debug( output )
+ stdout_queue.put( output )
+ stdout_queue.put( None )
+ for line in iter( stderr.readline, '' ):
+ output = line.rstrip()
+ stderr_logger.debug( output )
+ stderr_queue.put( output )
+ stderr_queue.put( None )
+
+ def environment_commands( self, action_type ):
+ """Build a list of commands used to construct the environment described by this object."""
+ cmds = []
+ for env_shell_file_path in self.env_shell_file_paths:
+ if os.path.exists( env_shell_file_path ):
+ for env_setting in open( env_shell_file_path ):
+ cmds.append( env_setting.strip( '\n' ) )
+ else:
+ log.debug( 'Invalid file %s specified, ignoring %s action.' % ( str( env_shell_file_path ), str( action_type ) ) )
+ return cmds
+
+ def environment_dict( self, action_type='template_command' ):
+ env_vars = dict()
+ for env_shell_file_path in self.env_shell_file_paths:
+ if os.path.exists( env_shell_file_path ):
+ for env_setting in open( env_shell_file_path ):
+ env_string = env_setting.split( ';' )[ 0 ]
+ env_name, env_path = env_string.split( '=' )
+ env_vars[ env_name ] = env_path
+ else:
+ log.debug( 'Invalid file %s specified, ignoring template_command action.' % str( env_shell_file_path ) )
+ return env_vars
+
+ def handle_command( self, app, tool_dependency, cmd, return_output=False ):
+ """Handle a command and log the results."""
+ context = app.install_model.context
+ command = str( cmd )
+ output = self.handle_complex_command( command )
+ self.log_results( cmd, output, os.path.join( self.install_dir, td_common_util.INSTALLATION_LOG ) )
+ stdout = output.stdout
+ stderr = output.stderr
+ if len( stdout ) > DATABASE_MAX_STRING_SIZE:
+ print "Length of stdout > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY )
+ stdout = shrink_string_by_size( stdout, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True )
+ if len( stderr ) > DATABASE_MAX_STRING_SIZE:
+ print "Length of stderr > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY )
+ stderr = shrink_string_by_size( stderr, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True )
+ if output.return_code not in [ 0 ]:
+ tool_dependency.status = app.install_model.ToolDependency.installation_status.ERROR
+ if stderr:
+ tool_dependency.error_message = unicodify( stderr )
+ elif stdout:
+ tool_dependency.error_message = unicodify( stdout )
+ else:
+ # We have a problem if there was no stdout and no stderr.
+ tool_dependency.error_message = "Unknown error occurred executing shell command %s, return_code: %s" % \
+ ( str( cmd ), str( output.return_code ) )
+ context.add( tool_dependency )
+ context.flush()
+ if return_output:
+ return output
+ return output.return_code
+
+ def handle_complex_command( self, command ):
+ """
+ Wrap subprocess.Popen in such a way that the stderr and stdout from running a shell command will
+ be captured and logged in nearly real time. This is similar to fabric.local, but allows us to
+ retain control over the process. This method is named "complex" because it uses queues and
+ threads to execute a command while capturing and displaying the output.
+ """
+ # Launch the command as subprocess. A bufsize of 1 means line buffered.
+ process_handle = subprocess.Popen( str( command ),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ bufsize=1,
+ close_fds=False,
+ shell=True,
+ cwd=state.env[ 'lcwd' ] )
+ pid = process_handle.pid
+ # Launch the asynchronous readers of the process' stdout and stderr.
+ stdout_queue = Queue.Queue()
+ stdout_reader = asynchronous_reader.AsynchronousReader( process_handle.stdout, stdout_queue )
+ stdout_reader.start()
+ stderr_queue = Queue.Queue()
+ stderr_reader = asynchronous_reader.AsynchronousReader( process_handle.stderr, stderr_queue )
+ stderr_reader.start()
+ # Place streamed stdout and stderr into a threaded IPC queue target so it can
+ # be printed and stored for later retrieval when generating the INSTALLATION.log.
+ stdio_thread = threading.Thread( target=self.enqueue_output,
+ args=( process_handle.stdout,
+ stdout_queue,
+ process_handle.stderr,
+ stderr_queue ) )
+ thread_lock = threading.Lock()
+ thread_lock.acquire()
+ stdio_thread.start()
+ # Check the queues for output until there is nothing more to get.
+ start_timer = time.time()
+ while not stdout_reader.installation_complete() or not stderr_reader.installation_complete():
+ # Show what we received from standard output.
+ while not stdout_queue.empty():
+ try:
+ line = stdout_queue.get()
+ except Queue.Empty:
+ line = None
+ break
+ if line:
+ print line
+ start_timer = time.time()
+ else:
+ break
+ # Show what we received from standard error.
+ while not stderr_queue.empty():
+ try:
+ line = stderr_queue.get()
+ except Queue.Empty:
+ line = None
+ break
+ if line:
+ print line
+ start_timer = time.time()
+ else:
+ stderr_queue.task_done()
+ break
+ # Sleep a bit before asking the readers again.
+ time.sleep( .1 )
+ current_wait_time = time.time() - start_timer
+ if stdout_queue.empty() and stderr_queue.empty() and current_wait_time > td_common_util.NO_OUTPUT_TIMEOUT:
+ err_msg = "\nShutting down process id %s because it generated no output for the defined timeout period of %.1f seconds.\n" % \
+ ( pid, td_common_util.NO_OUTPUT_TIMEOUT )
+ stderr_reader.lines.append( err_msg )
+ process_handle.kill()
+ break
+ thread_lock.release()
+ # Wait until each of the threads we've started terminate. The following calls will block each thread
+ # until it terminates either normally, through an unhandled exception, or until the timeout occurs.
+ stdio_thread.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ stdout_reader.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ stderr_reader.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ # Close subprocess' file descriptors.
+ error = self.close_file_descriptor( process_handle.stdout )
+ error = self.close_file_descriptor( process_handle.stderr )
+ stdout = '\n'.join( stdout_reader.lines )
+ stderr = '\n'.join( stderr_reader.lines )
+ # Handle error condition (deal with stdout being None, too)
+ output = _AttributeString( stdout.strip() if stdout else "" )
+ errors = _AttributeString( stderr.strip() if stderr else "" )
+ # Make sure the process has finished.
+ process_handle.poll()
+ output.return_code = process_handle.returncode
+ output.stderr = errors
+ return output
+
+ def log_results( self, command, fabric_AttributeString, file_path ):
+ """Write attributes of fabric.operations._AttributeString to a specified log file."""
+ if os.path.exists( file_path ):
+ logfile = open( file_path, 'ab' )
+ else:
+ logfile = open( file_path, 'wb' )
+ logfile.write( "\n#############################################\n" )
+ logfile.write( '%s\nSTDOUT\n' % command )
+ logfile.write( str( fabric_AttributeString.stdout ) )
+ logfile.write( "\n#############################################\n" )
+ logfile.write( "\n#############################################\n" )
+ logfile.write( '%s\nSTDERR\n' % command )
+ logfile.write( str( fabric_AttributeString.stderr ) )
+ logfile.write( "\n#############################################\n" )
+ logfile.close()
+
+ @contextmanager
+ def make_tmp_dir( self ):
+ work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-mtd" )
+ yield work_dir
+ if os.path.exists( work_dir ):
+ try:
+ shutil.rmtree( work_dir )
+ except Exception, e:
+ log.exception( str( e ) )
+
+ def __setup_environment( self ):
+ return "&&".join( [ ". %s" % file for file in self.__valid_env_shell_file_paths() ] )
+
+ def __valid_env_shell_file_paths( self ):
+ return [ file for file in self.env_shell_file_paths if os.path.exists( file ) ]
This diff is so big that we needed to truncate the remainder.
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: first take on api for requesting roles(assigned and assignable) for permissions; do not use - needs to be tested on test
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/23bb24573f13/
Changeset: 23bb24573f13
User: martenson
Date: 2014-05-14 19:53:01
Summary: data libraries: first take on api for requesting roles(assigned and assignable) for permissions; do not use - needs to be tested on test
changes to UI, removed modal for dataset details, dissasembled into separate backbone view
Affected #: 20 files
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/security/__init__.py
--- a/lib/galaxy/security/__init__.py
+++ b/lib/galaxy/security/__init__.py
@@ -986,8 +986,8 @@
def dataset_is_private_to_user( self, trans, dataset ):
"""
- If the dataset object has exactly one access role and that is the
- current user's private role then we consider the dataset private.
+ If the LibraryDataset object has exactly one access role and that is
+ the current user's private role then we consider the dataset private.
"""
private_role = self.get_private_user_role( trans.user )
access_roles = dataset.library_dataset_dataset_association.get_access_roles( trans )
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/webapps/galaxy/api/folder_contents.py
--- a/lib/galaxy/webapps/galaxy/api/folder_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py
@@ -68,53 +68,39 @@
raise exceptions.InternalServerError( 'Error loading from the database.' )
current_user_roles = trans.get_current_user_roles()
- can_add_library_item = trans.user_is_admin() or trans.app.security_agent.can_add_library_item( current_user_roles, folder )
- if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ):
- if folder.parent_id is None:
- try:
- library = trans.sa_session.query( trans.app.model.Library ).filter( trans.app.model.Library.table.c.root_folder_id == decoded_folder_id ).one()
- except Exception:
- raise exceptions.InternalServerError( 'Error loading from the database.' )
- if trans.app.security_agent.library_is_unrestricted( library ):
- pass
- else:
- if trans.user:
- log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
- else:
- log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
- raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
+ # Special level of security on top of libraries.
+ if trans.app.security_agent.can_access_library( current_user_roles, folder.parent_library ):
+ pass
+ else:
+ if trans.user:
+ log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
else:
- if trans.user:
- log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
- else:
- log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
- raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
+ log.warning( "SECURITY: Anonymous user is trying to load restricted folder with ID of %s" % ( decoded_folder_id ) )
+ raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
- def build_path( folder ):
- """
- Search the path upwards recursively and load the whole route of
- names and ids for breadcrumb building purposes.
-
- :param folder: current folder for navigating up
- :param type: Galaxy LibraryFolder
-
- :returns: list consisting of full path to the library
- :type: list
- """
- path_to_root = []
- # We are almost in root
- if folder.parent_id is None:
- path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
- else:
- # We add the current folder and traverse up one folder.
- path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
- upper_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( folder.parent_id )
- path_to_root.extend( build_path( upper_folder ) )
- return path_to_root
-
- # Return the reversed path so it starts with the library node.
- full_path = build_path( folder )[::-1]
+ # if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ):
+ # log.debug('folder parent id: ' + str(folder.parent_id))
+ # if folder.parent_id is None:
+ # try:
+ # library = trans.sa_session.query( trans.app.model.Library ).filter( trans.app.model.Library.table.c.root_folder_id == decoded_folder_id ).one()
+ # except Exception:
+ # raise exceptions.InternalServerError( 'Error loading from the database.' )
+ # if trans.app.security_agent.library_is_unrestricted( library ):
+ # pass
+ # else:
+ # if trans.user:
+ # log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
+ # else:
+ # log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
+ # raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
+ # else:
+ # if trans.user:
+ # log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
+ # else:
+ # log.debug('PARENT ID IS NOT NONE')
+ # log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
+ # raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
folder_contents = []
update_time = ''
@@ -128,17 +114,42 @@
if content_item.api_type == 'folder':
encoded_id = 'F' + encoded_id
+ # Check whether user can modify current folder
+ can_modify = False
+ if trans.user_is_admin():
+ can_modify = True
+ elif trans.user:
+ can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, folder )
+ return_item.update( dict( can_modify=can_modify ) )
if content_item.api_type == 'file':
+ # Is the dataset public or private?
+ # When both are False the dataset is 'restricted'
+ is_private = False
+ is_unrestricted = False
+ if trans.app.security_agent.dataset_is_public( content_item.library_dataset_dataset_association.dataset ):
+ is_unrestricted = True
+ else:
+ is_unrestricted = False
+ if trans.user:
+ is_private = trans.app.security_agent.dataset_is_private_to_user( trans, content_item )
+
+ # Can user manage the permissions on the dataset?
+ can_manage = False
+ if trans.user_is_admin():
+ can_manage = True
+ elif trans.user:
+ can_manage = trans.app.security_agent.can_manage_dataset( current_user_roles, content_item.library_dataset_dataset_association.dataset )
+
+ nice_size = util.nice_size( int( content_item.library_dataset_dataset_association.get_size() ) )
+
library_dataset_dict = content_item.to_dict()
- library_dataset_dict[ 'is_unrestricted' ] = trans.app.security_agent.dataset_is_public( content_item.library_dataset_dataset_association.dataset )
- library_dataset_dict[ 'is_private' ] = trans.app.security_agent.dataset_is_private_to_user( trans, content_item )
-
return_item.update( dict( data_type=library_dataset_dict[ 'data_type' ],
- file_size=library_dataset_dict[ 'file_size' ],
date_uploaded=library_dataset_dict[ 'date_uploaded' ],
- is_unrestricted=library_dataset_dict[ 'is_unrestricted' ],
- is_private=library_dataset_dict[ 'is_private' ] ) )
+ is_unrestricted=is_unrestricted,
+ is_private=is_private,
+ can_manage=can_manage,
+ file_size=nice_size ) )
# For every item include the default meta-data
return_item.update( dict( id=encoded_id,
@@ -150,7 +161,42 @@
) )
folder_contents.append( return_item )
- return { 'metadata': { 'full_path': full_path, 'can_add_library_item': can_add_library_item, 'folder_name': folder.name }, 'folder_contents': folder_contents }
+ # Return the reversed path so it starts with the library node.
+ full_path = self.build_path( trans, folder )[ ::-1 ]
+
+ # Check whether user can add items to the current folder
+ can_add_library_item = trans.user_is_admin() or trans.app.security_agent.can_add_library_item( current_user_roles, folder )
+
+ # Check whether user can modify current folder
+ can_modify_folder = trans.app.security_agent.can_modify_library_item( current_user_roles, folder )
+
+ metadata = dict( full_path=full_path,
+ can_add_library_item=can_add_library_item,
+ can_modify_folder=can_modify_folder )
+ folder_container = dict( metadata=metadata, folder_contents=folder_contents )
+ return folder_container
+
+ def build_path( self, trans, folder ):
+ """
+ Search the path upwards recursively and load the whole route of
+ names and ids for breadcrumb building purposes.
+
+ :param folder: current folder for navigating up
+ :param type: Galaxy LibraryFolder
+
+ :returns: list consisting of full path to the library
+ :type: list
+ """
+ path_to_root = []
+ # We are almost in root
+ if folder.parent_id is None:
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ else:
+ # We add the current folder and traverse up one folder.
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ upper_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( folder.parent_id )
+ path_to_root.extend( self.build_path( trans, upper_folder ) )
+ return path_to_root
def _load_folder_contents( self, trans, folder, include_deleted ):
"""
@@ -291,14 +337,13 @@
:param encoded_folder_id: encoded id of Galaxy LibraryFolder
:type encoded_folder_id: encoded string
- :returns: last 16 chars of the encoded id in case it was Folder
- (had 'F' prepended)
+ :returns: encoded id of Folder (had 'F' prepended)
:type: string
:raises: MalformedId
"""
- if ( len( encoded_folder_id ) == 17 and encoded_folder_id.startswith( 'F' )):
- return encoded_folder_id[1:]
+ if ( ( len( encoded_folder_id ) % 16 == 1 ) and encoded_folder_id.startswith( 'F' ) ):
+ return encoded_folder_id[ 1: ]
else:
raise exceptions.MalformedId( 'Malformed folder id ( %s ) specified, unable to decode.' % str( encoded_folder_id ) )
@@ -307,11 +352,11 @@
"""
GET /api/folders/{encoded_folder_id}/
"""
- raise exceptions.NotImplemented( 'Showing the library folder content is not implemented.' )
+ raise exceptions.NotImplemented( 'Showing the library folder content is not implemented here.' )
@web.expose_api
def update( self, trans, id, library_id, payload, **kwd ):
"""
PUT /api/folders/{encoded_folder_id}/contents
"""
- raise exceptions.NotImplemented( 'Updating the library folder content is not implemented.' )
+ raise exceptions.NotImplemented( 'Updating the library folder content is not implemented here.' )
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/webapps/galaxy/api/lda_datasets.py
--- a/lib/galaxy/webapps/galaxy/api/lda_datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/lda_datasets.py
@@ -47,12 +47,68 @@
dataset = self.get_library_dataset( trans, id=id, check_ownership=False, check_accessible=True )
except Exception:
raise exceptions.ObjectNotFound( 'Requested dataset was not found.' )
+
+ # Build the full path for breadcrumb purposes.
+ full_path = self._build_path( trans, dataset.folder )
+ dataset_item = ( trans.security.encode_id( dataset.id ), dataset.name )
+ full_path.insert(0, dataset_item)
+ full_path = full_path[ ::-1 ]
+
+ nice_size = util.nice_size( int( dataset.library_dataset_dataset_association.get_size() ) )
+
+ date_uploaded = dataset.library_dataset_dataset_association.create_time.strftime( "%Y-%m-%d %I:%M %p" )
+
rval = trans.security.encode_all_ids( dataset.to_dict() )
rval[ 'deleted' ] = dataset.deleted
rval[ 'folder_id' ] = 'F' + rval[ 'folder_id' ]
+ rval[ 'full_path' ] = full_path
+ rval[ 'file_size' ] = nice_size
+ rval[ 'date_uploaded' ] = date_uploaded
return rval
@expose_api
+ def show_roles( self, trans, encoded_dataset_id, **kwd ):
+ """
+ show_roles( self, trans, id, **kwd ):
+ GET /api/libraries/datasets/{encoded_dataset_id}/permissions:
+ Displays information about current and available roles
+ for a given dataset permission.
+ """
+ current_user_roles = trans.get_current_user_roles()
+ page = int( kwd.get( 'page', None ) )
+ page_limit = int( kwd.get( 'page_limit', None ) )
+ query = kwd.get ( 'q', None )
+
+ if page is None:
+ page = 1
+
+ if page_limit is None:
+ page_limit = 10
+
+ try:
+ library_dataset = self.get_library_dataset( trans, id=encoded_dataset_id, check_ownership=False, check_accessible=False )
+ except Exception, e:
+ raise exceptions.ObjectNotFound( 'Requested dataset was not found.' + str(e) )
+ library = library_dataset.folder.parent_library
+ dataset = library_dataset.library_dataset_dataset_association.dataset
+
+ can_manage = trans.app.security_agent.can_manage_dataset( current_user_roles, dataset ) or trans.user_is_admin()
+ if not can_manage:
+ raise exceptions.InsufficientPermissionsException( 'You do not have proper permissions to access permissions.' )
+
+ cntrller = 'standard_user'
+ if trans.user_is_admin():
+ cntrller = 'library_admin'
+
+ roles = trans.app.security_agent.get_legitimate_roles( trans, library, cntrller )
+ total_roles = len( roles )
+ return_roles = []
+ for role in roles:
+ return_roles.append( dict( id=role.name, name=role.name, type=role.type ) )
+
+ return dict( roles=return_roles, page=page, page_limit=page_limit, total=total_roles )
+
+ @expose_api
def delete( self, trans, encoded_dataset_id, **kwd ):
"""
delete( self, trans, encoded_dataset_id, **kwd ):
@@ -107,7 +163,9 @@
:raises: MessageException, ItemDeletionException, ItemAccessibilityException, HTTPBadRequest, OSError, IOError, ObjectNotFound
"""
lddas = []
- datasets_to_download = kwd[ 'ldda_ids%5B%5D' ]
+ datasets_to_download = kwd.get( 'ldda_ids%5B%5D', None )
+ if datasets_to_download is None:
+ datasets_to_download = kwd.get( 'ldda_ids', None )
if ( datasets_to_download is not None ):
datasets_to_download = util.listify( datasets_to_download )
@@ -121,6 +179,8 @@
raise exceptions.InternalServerError( 'Internal error. ' + str( e.err_msg ) )
except Exception, e:
raise exceptions.InternalServerError( 'Unknown error. ' + str( e ) )
+ else:
+ raise exceptions.RequestParameterMissingException( 'Request has to contain a list of dataset ids to download.' )
if format in [ 'zip', 'tgz', 'tbz' ]:
# error = False
@@ -262,3 +322,25 @@
raise exceptions.InternalServerError( "This dataset contains no content." )
else:
raise exceptions.RequestParameterInvalidException( "Wrong format parameter specified" )
+
+ def _build_path( self, trans, folder ):
+ """
+ Search the path upwards recursively and load the whole route of
+ names and ids for breadcrumb building purposes.
+
+ :param folder: current folder for navigating up
+ :param type: Galaxy LibraryFolder
+
+ :returns: list consisting of full path to the library
+ :type: list
+ """
+ path_to_root = []
+ # We are almost in root
+ if folder.parent_id is None:
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ else:
+ # We add the current folder and traverse up one folder.
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ upper_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( folder.parent_id )
+ path_to_root.extend( self._build_path( trans, upper_folder ) )
+ return path_to_root
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -218,6 +218,12 @@
action='show',
conditions=dict( method=[ "GET" ] ) )
+ webapp.mapper.connect( 'show_legitimate_lda_roles',
+ '/api/libraries/datasets/:encoded_dataset_id/permissions',
+ controller='lda_datasets',
+ action='show_roles',
+ conditions=dict( method=[ "GET" ] ) )
+
webapp.mapper.connect( 'delete_lda_item',
'/api/libraries/datasets/:encoded_dataset_id',
controller='lda_datasets',
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/galaxy.library.js
--- a/static/scripts/galaxy.library.js
+++ b/static/scripts/galaxy.library.js
@@ -11,7 +11,8 @@
"mvc/library/library-folderlist-view",
"mvc/library/library-librarylist-view",
"mvc/library/library-librarytoolbar-view",
- "mvc/library/library-foldertoolbar-view"
+ "mvc/library/library-foldertoolbar-view",
+ "mvc/library/library-dataset-view"
],
function(mod_masthead,
mod_utils,
@@ -21,7 +22,8 @@
mod_folderlist_view,
mod_librarylist_view,
mod_librarytoolbar_view,
- mod_foldertoolbar_view
+ mod_foldertoolbar_view,
+ mod_library_dataset_view
) {
// ============================================================================
@@ -34,10 +36,11 @@
},
routes: {
- "" : "libraries",
- "folders/:id" : "folder_content",
- "folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
- "folders/:folder_id/download/:format" : "download"
+ "" : "libraries",
+ "folders/:id" : "folder_content",
+ "folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
+ "folders/:folder_id/datasets/:dataset_id/permissions" : "dataset_permissions",
+ "folders/:folder_id/download/:format" : "download"
},
back: function() {
@@ -80,14 +83,11 @@
this.library_router = new LibraryRouter();
this.library_router.on('route:libraries', function() {
- // initialize and render the toolbar first
Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
- // initialize and render libraries second
Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView();
});
this.library_router.on('route:folder_content', function(id) {
- // TODO maybe caching somewhere here, sessionstorage/localstorage?
if (Galaxy.libraries.folderToolbarView){
Galaxy.libraries.folderToolbarView.$el.unbind('click');
}
@@ -106,12 +106,10 @@
});
this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){
- // if (Galaxy.libraries.folderToolbarView){
- // 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});
- // }
+ new mod_library_dataset_view.LibraryDatasetView({id: dataset_id})
+ });
+ this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){
+ new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true})
});
Backbone.history.start({pushState: false});
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/mvc/library/library-dataset-view.js
--- /dev/null
+++ b/static/scripts/mvc/library/library-dataset-view.js
@@ -0,0 +1,556 @@
+define([
+ "libs/toastr",
+ "mvc/library/library-model",
+ 'mvc/ui/ui-select'
+ ],
+function(mod_toastr,
+ mod_library_model,
+ mod_select
+ ) {
+
+var LibraryDatasetView = Backbone.View.extend({
+ el: '#center',
+
+ model: null,
+
+ options: {
+
+ },
+
+ events: {
+ "click .toolbtn_modify_dataset" : "enableModification",
+ "click .toolbtn_cancel_modifications" : "render",
+ "click .toolbtn_change_permissions" : "showPermissions",
+ "click .toolbtn-download-dataset" : "downloadDataset",
+ "click .toolbtn-import-dataset" : "importIntoHistory",
+ "click .toolbtn-share-dataset" : "shareDataset"
+
+ },
+
+ initialize: function(options){
+ this.options = _.extend(this.options, options);
+ if (this.options.id){
+ this.fetchDataset();
+ }
+ },
+
+ fetchDataset: function(options){
+ this.options = _.extend(this.options, options);
+ this.model = new mod_library_model.Item({id:this.options.id});
+ var that = this;
+ this.model.fetch({
+ success: function() {
+ if (that.options.show_permissions){
+ that.showPermissions();
+ } else {
+ that.render();
+ }
+ },
+ error: function(model, response){
+ if (typeof response.responseJSON !== "undefined"){
+ 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 :(. Click this to go back.', '', {onclick: function() {Galaxy.libraries.library_router.back();}});
+ }
+ }
+ });
+ },
+
+ render: function(options){
+ $(".tooltip").remove();
+ this.options = _.extend(this.options, options);
+ var template = this.templateDataset();
+ this.$el.html(template({item: this.model}));
+ $(".peek").html(this.model.get("peek"));
+ $("#center [data-toggle]").tooltip();
+ },
+
+ enableModification: function(){
+ $(".tooltip").remove();
+ var template = this.templateModifyDataset();
+ this.$el.html(template({item: this.model}));
+ $(".peek").html(this.model.get("peek"));
+ $("#center [data-toggle]").tooltip();
+ },
+
+ downloadDataset: function(){
+ var url = '/api/libraries/datasets/download/uncompressed';
+ var data = {'ldda_ids' : this.id};
+ this.processDownload(url, data);
+ },
+
+ processDownload: function(url, data, method){
+ //url and data options required
+ if( url && data ){
+ //data can be string of parameters or array/object
+ data = typeof data == 'string' ? data : $.param(data);
+ //split params into form inputs
+ var inputs = '';
+ $.each(data.split('&'), function(){
+ var pair = this.split('=');
+ inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />';
+ });
+ //send request
+ $('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
+ .appendTo('body').submit().remove();
+
+ mod_toastr.info('Your download will begin soon');
+ }
+ },
+
+ importIntoHistory: function(){
+ this.refreshUserHistoriesList(function(self){
+ var template = self.templateBulkImportInModal();
+ self.modal = Galaxy.modal;
+ self.modal.show({
+ closing_events : true,
+ title : 'Import into History',
+ body : template({histories : self.histories.models}),
+ buttons : {
+ 'Import' : function() {self.importCurrentIntoHistory();},
+ 'Close' : function() {Galaxy.modal.hide();}
+ }
+ });
+ });
+ },
+
+ refreshUserHistoriesList: function(callback){
+ var self = this;
+ this.histories = new mod_library_model.GalaxyHistories();
+ this.histories.fetch({
+ success: function (){
+ callback(self);
+ },
+ error: function(model, response){
+ if (typeof response.responseJSON !== "undefined"){
+ mod_toastr.error(response.responseJSON.err_msg);
+ } else {
+ mod_toastr.error('An error ocurred :(');
+ }
+ }
+ });
+ },
+
+ importCurrentIntoHistory: function(){
+ var self = this;
+ var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val();
+ var historyItem = new mod_library_model.HistoryItem();
+ 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 : this.id, source : 'library' }, {
+ success : function(){
+ Galaxy.modal.hide();
+ mod_toastr.success('Dataset imported. Click this to start analysing it.', '', {onclick: function() {window.location='/';}});
+ },
+ error : function(model, response){
+ if (typeof response.responseJSON !== "undefined"){
+ mod_toastr.error('Dataset not imported. ' + response.responseJSON.err_msg);
+ } else {
+ mod_toastr.error('An error occured! Dataset not imported. Please try again.');
+ }
+ }
+ });
+ },
+
+ shareDataset: function(){
+ mod_toastr.info('Feature coming soon.');
+ },
+
+ showPermissions: function(){
+ $(".tooltip").remove();
+ var template = this.templateDatasetPermissions();
+ this.$el.html(template({item: this.model}));
+
+ var self = this;
+
+ this.access_perm = new mod_select.View({
+ css: 'access_perm',
+ multiple:true,
+ placeholder: 'Click to select a role',
+ container: self.$el.find('#access_perm'),
+ ajax: {
+ url: "/api/libraries/datasets/5969b1f7201f12ae/permissions",
+ dataType: 'json',
+ quietMillis: 100,
+ data: function (term, page) { // page is the one-based page number tracked by Select2
+ return {
+ q: term, //search term
+ page_limit: 10, // page size
+ page: page // page number
+ };
+ },
+ results: function (data, page) {
+ var more = (page * 10) < data.total; // whether or not there are more results available
+ // notice we return the value of more so Select2 knows if more results can be loaded
+ return {results: data.roles, more: more};
+ }
+ },
+ formatResult : function roleFormatResult(role) {
+ return role.name;
+ },
+
+ formatSelection: function roleFormatSelection(role) {
+ return role.name;
+ },
+ initSelection: function(element, callback) {
+ // the input tag has a value attribute preloaded that points to a preselected role's id
+ // this function resolves that id attribute to an object that select2 can render
+ // using its formatResult renderer - that way the role name is shown preselected
+ var data = [];
+ $(element.val().split(",")).each(function(i) {
+ var item = this.split(':');
+ data.push({
+ id: item[1],
+ name: item[1]
+ });
+ });
+ callback(data);
+ },
+ initialData: 'marten@bx.psu.edu:marten@bx.psu.edu',
+ dropdownCssClass: "bigdrop" // apply css that makes the dropdown taller
+ });
+ // this.access_perm.$el.append($('<option>', {value:"NEWVAL", text: "New Option Text"}));
+
+ // this.modify_perm = new mod_select.View({
+ // css: 'modify_perm',
+ // placeholder: 'Select a role',
+ // // onchange : function() {
+ // // self.model.set('access_perm', self.select_genome.value());
+ // // },
+ // data: [{id:'test',text:'testik'}, {id:'dududu', text:'dadada'}],
+ // container: self.$el.find('#modify_perm'),
+ // multiple: true
+ // // value: self.model.get('access_perm')
+ // });
+ // this.modify_perm.$el.append($('<option>', {value:"NEWVAL", text: "New Option Text"}));
+
+ // this.manage_perm = new mod_select.View({
+ // css: 'manage_perm',
+ // placeholder: 'Select a role',
+ // // onchange : function() {
+ // // self.model.set('access_perm', self.select_genome.value());
+ // // },
+ // data: [{id:'test',text:'testik'}, {id:'dududu', text:'dadada'}],
+ // container: self.$el.find('#manage_perm'),
+ // multiple: true
+ // // value: self.model.get('access_perm')
+ // });
+ // this.manage_perm.$el.append($('<option>', {value:"NEWVAL", text: "New Option Text"}));
+
+ $("#center [data-toggle]").tooltip();
+ },
+
+
+ templateDataset : function(){
+ var tmpl_array = [];
+ // CONTAINER START
+ tmpl_array.push('<div class="library_style_container">');
+
+ tmpl_array.push(' <div id="library_toolbar">');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Download dataset" class="btn btn-default toolbtn-download-dataset primary-button" type="button"><span class="fa fa-download"></span> Download</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import dataset into history" class="btn btn-default toolbtn-import-dataset primary-button" type="button"><span class="fa fa-book"></span> to History</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify dataset" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Change permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Share dataset" class="btn btn-default toolbtn-share-dataset primary-button" type="button"><span class="fa fa-share"></span> Share</span></button>');
+
+ tmpl_array.push(' </div>');
+
+ // BREADCRUMBS
+ tmpl_array.push('<ol class="breadcrumb">');
+ tmpl_array.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');
+ tmpl_array.push(' <% _.each(item.get("full_path"), function(path_item) { %>');
+ tmpl_array.push(' <% if (path_item[0] != item.id) { %>');
+ tmpl_array.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');
+ tmpl_array.push( '<% } else { %>');
+ tmpl_array.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</ol>');
+
+ tmpl_array.push('<div class="dataset_table">');
+
+ tmpl_array.push(' <table class="grid table table-striped table-condensed">');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("name")) %></td>');
+ tmpl_array.push(' </tr>');
+
+ tmpl_array.push(' <% if (item.get("data_type")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Data type</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("data_type")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("genome_build")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Genome build</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("genome_build")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("file_size")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Size</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("file_size")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("date_uploaded")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Date uploaded (UTC)</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("uploaded_by")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Uploaded by</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_data_lines")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Data Lines</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_comment_lines")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Comment Lines</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_columns")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Number of Columns</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_column_types")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Column Types</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("message")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Message</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("misc_blurb")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous blurb</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("misc_info")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous information</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' </table>');
+ tmpl_array.push(' <div>');
+ tmpl_array.push(' <pre class="peek">');
+ tmpl_array.push(' </pre>');
+ tmpl_array.push(' </div>');
+ tmpl_array.push('</div>');
+
+ // CONTAINER END
+ tmpl_array.push('</div>');
+
+ return _.template(tmpl_array.join(''));
+ },
+
+ templateModifyDataset : function(){
+ var tmpl_array = [];
+ // CONTAINER START
+ tmpl_array.push('<div class="library_style_container">');
+
+ tmpl_array.push(' <div id="library_toolbar">');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');
+
+ tmpl_array.push(' </div>');
+
+ // BREADCRUMBS
+ tmpl_array.push('<ol class="breadcrumb">');
+ tmpl_array.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');
+ tmpl_array.push(' <% _.each(item.get("full_path"), function(path_item) { %>');
+ tmpl_array.push(' <% if (path_item[0] != item.id) { %>');
+ tmpl_array.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');
+ tmpl_array.push( '<% } else { %>');
+ tmpl_array.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</ol>');
+
+ tmpl_array.push('<div class="dataset_table">');
+ tmpl_array.push('<p>For more editing options please import the dataset to history and use "Edit attributes" on it.</p>');
+ tmpl_array.push(' <table class="grid table table-striped table-condensed">');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');
+ tmpl_array.push(' <td><input class="input_dataset_name form-control" type="text" placeholder="name" value="<%= _.escape(item.get("name")) %>"></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Data type</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("data_type")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Genome build</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("genome_build")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Size</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("file_size")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Date uploaded (UTC)</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Uploaded by</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr scope="row">');
+ tmpl_array.push(' <th scope="row">Data Lines</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <th scope="row">Comment Lines</th>');
+ tmpl_array.push(' <% if (item.get("metadata_comment_lines") === "") { %>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');
+ tmpl_array.push(' <% } else { %>');
+ tmpl_array.push(' <td scope="row">unknown</td>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Number of Columns</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Column Types</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Message</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous information</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous blurb</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' </table>');
+ tmpl_array.push('<div>');
+ tmpl_array.push(' <pre class="peek">');
+ tmpl_array.push(' </pre>');
+ tmpl_array.push('</div>');
+ tmpl_array.push('</div>');
+
+ // CONTAINER END
+ tmpl_array.push('</div>');
+
+ return _.template(tmpl_array.join(''));
+ },
+
+ templateDatasetPermissions : function(){
+ var tmpl_array = [];
+ // CONTAINER START
+ tmpl_array.push('<div class="library_style_container">');
+
+ tmpl_array.push(' <div id="library_toolbar">');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');
+
+ tmpl_array.push(' </div>');
+
+ // BREADCRUMBS
+ tmpl_array.push('<ol class="breadcrumb">');
+ tmpl_array.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');
+ tmpl_array.push(' <% _.each(item.get("full_path"), function(path_item) { %>');
+ tmpl_array.push(' <% if (path_item[0] != item.id) { %>');
+ tmpl_array.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');
+ tmpl_array.push( '<% } else { %>');
+ tmpl_array.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</ol>');
+
+ tmpl_array.push('<h1><%= _.escape(item.get("name")) %></h1>');
+ tmpl_array.push('<div class="alert alert-success">You have rights to change permissions on this dataset. That means you can control who can access it, who can modify it and also appoint others that can manage permissions on it.</div>');
+ tmpl_array.push('<div class="dataset_table">');
+
+ tmpl_array.push('<h2>Basic permissions</h2>');
+ tmpl_array.push('<p>You can remove all access restrictions on this dataset. ');
+ tmpl_array.push('<button data-toggle="tooltip" data-placement="top" title="Everybody will be able to see the dataset." class="btn btn-default btn-remove-restrictions primary-button" type="button"><span class="fa fa-globe"></span> Remove restrictions</span></button>');
+ tmpl_array.push('</p>');
+
+ tmpl_array.push('<p>You can make this dataset private to you. ');
+ tmpl_array.push('<button data-toggle="tooltip" data-placement="top" title="Only you will be able to see the dataset." class="btn btn-default btn-make-private primary-button" type="button"><span class="fa fa-key"></span> Make private</span></button>');
+ tmpl_array.push('</p>');
+
+ tmpl_array.push('<h2>Advanced permissions</h2>');
+ tmpl_array.push('<p>You can assign any number of roles to any of the following three dataset permissions:</p>');
+ tmpl_array.push('<h3>Access Roles</h3>');
+ tmpl_array.push('<div class="alert alert-info">User has to have <strong>all these roles</strong> in order to see this dataset.</div>');
+ tmpl_array.push('<div id="access_perm" class="access_perm roles-selection"></div>');
+ tmpl_array.push('<h3>Modify Roles</h3>');
+ tmpl_array.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can modify the information about this dataset.</div>');
+ tmpl_array.push('<div id="modify_perm" class="modify_perm"></div>');
+ tmpl_array.push('<h3>Manage Roles</h3>');
+ tmpl_array.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can change permissions of this dataset.</div>');
+ tmpl_array.push('<div id="manage_perm" class="manage_perm"></div>');
+
+
+ tmpl_array.push('</div>');
+
+ // CONTAINER END
+ tmpl_array.push('</div>');
+
+ return _.template(tmpl_array.join(''));
+ },
+
+templateBulkImportInModal : function(){
+ var tmpl_array = [];
+
+ tmpl_array.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');
+ tmpl_array.push('Select history: ');
+ tmpl_array.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');
+ tmpl_array.push(' <% _.each(histories, function(history) { %>'); //history select box
+ tmpl_array.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</select>');
+ tmpl_array.push('</span>');
+
+ return _.template(tmpl_array.join(''));
+ }
+
+});
+
+return {
+ LibraryDatasetView: LibraryDatasetView
+};
+
+});
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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
@@ -4,12 +4,16 @@
"utils/utils",
"libs/toastr",
"mvc/library/library-model",
- "mvc/library/library-folderrow-view"],
+ "mvc/library/library-folderrow-view",
+ "mvc/library/library-dataset-view"
+ ],
function(mod_masthead,
mod_utils,
mod_toastr,
mod_library_model,
- mod_library_folderrow_view) {
+ mod_library_folderrow_view,
+ mod_library_dataset_view
+ ) {
var FolderListView = Backbone.View.extend({
el : '#folder_items_element',
@@ -42,16 +46,14 @@
},
fetchFolder: function(options){
- // this.options = _.defaults(this.options, options);
var options = options || {};
this.options.include_deleted = options.include_deleted;
var that = this;
this.collection = new mod_library_model.Folder();
- // start to listen if someone adds a model to the collection
+ // start to listen if someone modifies collection
this.listenTo(this.collection, 'add', this.renderOne);
-
this.listenTo(this.collection, 'remove', this.removeOne);
this.folderContainer = new mod_library_model.FolderContainer({id: this.options.id});
@@ -65,7 +67,12 @@
that.render();
that.addAll(folder_container.get('folder').models);
if (that.options.dataset_id){
- _.findWhere(that.rowViews, {id: that.options.dataset_id}).showDatasetDetails();
+ row = _.findWhere(that.rowViews, {id: that.options.dataset_id});
+ if (row) {
+ row.showDatasetDetails();
+ } else {
+ mod_toastr.error('Dataset not found. Showing folder instead.');
+ }
}
},
error: function(model, response){
@@ -109,7 +116,7 @@
var fetched_metadata = this.folderContainer.attributes.metadata;
fetched_metadata.contains_file = typeof this.collection.findWhere({type: 'file'}) !== 'undefined';
Galaxy.libraries.folderToolbarView.configureElements(fetched_metadata);
- $('.deleted_dataset').hover(function() {
+ $('.dataset').hover(function() {
$(this).find('.show_on_hover').show();
}, function () {
$(this).find('.show_on_hover').hide();
@@ -151,7 +158,7 @@
renderOne: function(model){
if (model.get('data_type') !== 'folder'){
this.options.contains_file = true;
- model.set('readable_size', this.size_to_string(model.get('file_size')));
+ // model.set('readable_size', this.size_to_string(model.get('file_size')));
}
model.set('folder_id', this.id);
var rowView = new mod_library_folderrow_view.FolderRowView(model);
@@ -161,7 +168,7 @@
this.$el.find('#first_folder_item').after(rowView.el);
- $('.deleted_dataset').hover(function() {
+ $('.dataset').hover(function() {
$(this).find('.show_on_hover').show();
}, function () {
$(this).find('.show_on_hover').hide();
@@ -213,21 +220,6 @@
}
},
- /**
- * convert size to nice string
- * @param {int} size
- * @return {string} readable representation of size with units
- */
- size_to_string : function (size){
- var unit = "";
- if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else
- if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else
- if (size >= 100000) { size = size / 100000; unit = "MB"; } else
- if (size >= 100) { size = size / 100; unit = "KB"; } else
- { size = size * 10; unit = "b"; }
- return (Math.round(size) / 10) + unit;
- },
-
/**
* User clicked the checkbox in the table heading
* @param {context} event
@@ -320,7 +312,7 @@
tmpl_array.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>');
tmpl_array.push(' <th><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>');
tmpl_array.push(' <th style="width:5%;">data type</th>');
- tmpl_array.push(' <th style="width:5%;">size</th>');
+ tmpl_array.push(' <th style="width:10%;">size</th>');
tmpl_array.push(' <th style="width:160px;">time updated (UTC)</th>');
tmpl_array.push(' <th style="width:10%;"></th> ');
tmpl_array.push(' </thead>');
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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
@@ -1,13 +1,14 @@
-// dependencies
define([
"galaxy.masthead",
"utils/utils",
"libs/toastr",
- "mvc/library/library-model"],
+ "mvc/library/library-model",
+ "mvc/library/library-dataset-view"],
function(mod_masthead,
mod_utils,
mod_toastr,
- mod_library_model) {
+ mod_library_model,
+ mod_library_dataset_view) {
// galaxy library row view
var FolderRowView = Backbone.View.extend({
@@ -15,7 +16,7 @@
lastSelectedHistory: '',
events: {
- 'click .undelete_dataset_btn' : 'undelete_dataset'
+ 'click .undelete_dataset_btn' : 'undelete_dataset'
},
options: {
@@ -27,9 +28,6 @@
},
render: function(folder_item){
- // if (typeof folder_item === 'undefined'){
- // folder_item = Galaxy.libraries.libraryFolderView.collection.get(this.$el.data('id'));
- // }
var template = null;
if (folder_item.get('type') === 'folder'){
this.options.type = 'folder';
@@ -47,172 +45,8 @@
return this;
},
- //show modal with current dataset info
showDatasetDetails : function(){
- var id = this.id;
-
- //create new item
- var item = new mod_library_model.Item();
- var histories = new mod_library_model.GalaxyHistories();
- item.id = id;
- var self = this;
-
- //fetch the dataset info
- item.fetch({
- success: function (item) {
- // TODO can start rendering here already
- //fetch user histories for import purposes
- histories.fetch({
- success: function (histories){
- self.renderModalAfterFetch(item, histories);
- },
- error: function(model, response){
- if (typeof response.responseJSON !== "undefined"){
- mod_toastr.error(response.responseJSON.err_msg);
- } else {
- mod_toastr.error('An error occured during fetching histories:(');
- }
- self.renderModalAfterFetch(item);
- }
- });
- },
- error: function(model, response){
- if (typeof response.responseJSON !== "undefined"){
- mod_toastr.error(response.responseJSON.err_msg);
- } else {
- mod_toastr.error('An error occured during loading dataset details :(');
- }
- }
- });
-},
-
- // show the current dataset in a modal
- renderModalAfterFetch : function(item, histories){
- var size = this.size_to_string(item.get('file_size'));
- var template = _.template(this.templateDatasetModal(), { item : item, size : size });
- // make modal
- var self = this;
- this.modal = Galaxy.modal;
- this.modal.show({
- closing_events : true,
- title : item.get('name'),
- body : template,
- buttons : {
- 'Import' : function() { self.importCurrentIntoHistory(); },
- 'Download' : function() { self.downloadCurrent(); },
- 'Close' : function() { self.modal.hide(); }
- },
- closing_callback : function(){
- var path_to_folder = Backbone.history.fragment.split('/datasets')[0];
- Galaxy.libraries.library_router.navigate('#' + path_to_folder, {trigger:true, replace:true});
- }
- });
-
- $(".peek").html(item.get("peek"));
-
- // show the import-into-history footer only if the request for histories succeeded
- if (typeof history.models !== undefined){
- var history_footer_tmpl = _.template(this.templateHistorySelectInModal(), {histories : histories.models});
- $(this.modal.elMain).find('.buttons').prepend(history_footer_tmpl);
- // preset last selected history if we know it
- if (self.lastSelectedHistory.length > 0) {
- $(this.modal.elMain).find('#dataset_import_single').val(self.lastSelectedHistory);
- }
- }
- },
-
- // TODO this is dup func, unify
- // convert size to nice string
- size_to_string : function (size){
- // identify unit
- var unit = "";
- if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else
- if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else
- if (size >= 100000) { size = size / 100000; unit = "MB"; } else
- if (size >= 100) { size = size / 100; unit = "KB"; } else
- { size = size * 10; unit = "b"; }
- // return formatted string
- return (Math.round(size) / 10) + unit;
- },
-
- // download dataset shown currently in modal
- downloadCurrent : function(){
- //disable the buttons
- this.modal.disableButton('Import');
- this.modal.disableButton('Download');
-
- var library_dataset_id = [];
- library_dataset_id.push($('#id_row').attr('data-id'));
- var url = '/api/libraries/datasets/download/uncompressed';
- var data = {'ldda_ids' : library_dataset_id};
-
- this.processDownload(url, data);
- this.modal.enableButton('Import');
- this.modal.enableButton('Download');
- },
-
- // TODO this is dup func, unify
- // create hidden form and submit through POST to initialize download
- processDownload: function(url, data, method){
- //url and data options required
- if( url && data ){
- //data can be string of parameters or array/object
- data = typeof data == 'string' ? data : $.param(data);
- //split params into form inputs
- var inputs = '';
- $.each(data.split('&'), function(){
- var pair = this.split('=');
- inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />';
- });
- //send request
- $('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
- .appendTo('body').submit().remove();
-
- mod_toastr.info('Your download will begin soon');
- }
- },
-
- // import dataset shown currently in modal into selected history
- importCurrentIntoHistory : function(){
- //disable the buttons
- this.modal.disableButton('Import');
- this.modal.disableButton('Download');
-
- var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val();
- this.lastSelectedHistory = history_id; //save selected history for further use
-
- var library_dataset_id = $('#id_row').attr('data-id');
- var historyItem = new mod_library_model.HistoryItem();
- 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. Click this to start analysing it.', '', {onclick: function() {window.location='/'}});
- //enable the buttons
- self.modal.enableButton('Import');
- self.modal.enableButton('Download');
- },
- error : function(model, response){
- if (typeof response.responseJSON !== "undefined"){
- mod_toastr.error('Dataset not imported. ' + response.responseJSON.err_msg);
- } else {
- mod_toastr.error('An error occured! Dataset not imported. Please try again.');
- }
- //enable the buttons
- self.modal.enableButton('Import');
- self.modal.enableButton('Download');
- }
- });
+ this.dataset_view = new mod_library_dataset_view.LibraryDatasetView({id: this.id});
},
/**
@@ -232,8 +66,8 @@
success : function(model, response){
Galaxy.libraries.folderListView.collection.remove(dataset_id);
var updated_dataset = new mod_library_model.Item(response);
- Galaxy.libraries.folderListView.collection.add(updated_dataset)
- mod_toastr.success('Dataset undeleted. Click this to see it.', '', {onclick: function() {that.showDatasetDetails()}});
+ Galaxy.libraries.folderListView.collection.add(updated_dataset);
+ mod_toastr.success('Dataset undeleted. Click this to see it.', '', {onclick: function() {that.showDatasetDetails();}});
},
error : function(model, response){
if (typeof response.responseJSON !== "undefined"){
@@ -255,14 +89,9 @@
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) { %>'); // empty folder
- // 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>');
- // print item count only if it is given
- // tmpl_array.push(' <td><% if (typeof content_item.get("item_count") !== "undefined") { _.escape(content_item.get("item_count")); print("item(s)") } %></td>');
tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push(' <td></td>');
tmpl_array.push('</tr>');
@@ -273,20 +102,20 @@
templateRowFile: function(){
tmpl_array = [];
- tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');
+ tmpl_array.push('<tr class="dataset_row light 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 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>'); // dataset
tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>'); // data type
- tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>'); // size
+ tmpl_array.push(' <td><%= _.escape(content_item.get("file_size")) %></td>'); // size
tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push(' <td>');
tmpl_array.push(' <% if (content_item.get("is_unrestricted")) { %><span data-toggle="tooltip" data-placement="top" title="Unrestricted dataset" style="color:grey;" class="fa fa-globe fa-lg"></span><% } %>');
tmpl_array.push(' <% if (content_item.get("is_private")) { %><span data-toggle="tooltip" data-placement="top" title="Private dataset" style="color:grey;" class="fa fa-key fa-lg"></span><% } %>');
- tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-group fa-lg"></span>');
- tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-shield fa-lg"></span><% } %>');
+ tmpl_array.push(' <% if (content_item.get("can_manage")) { %><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" class="primary-button btn-xs permissions-dataset-btn show_on_hover" title="Manage permissions" style="display:none;"><span class="fa fa-group"></span></button></a><% } %>');
tmpl_array.push(' </td>');
tmpl_array.push('</tr>');
@@ -296,94 +125,20 @@
templateRowDeletedFile: function(){
tmpl_array = [];
- tmpl_array.push('<tr class="active deleted_dataset" id="<%- content_item.id %>">');
+ tmpl_array.push('<tr class="active deleted_dataset 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></td>');
tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>'); // dataset
tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>'); // data type
- tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>'); // size
+ tmpl_array.push(' <td><%= _.escape(content_item.get("file_size")) %></td>'); // size
tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span><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; margin-left:1em;"><span class="fa fa-unlock"> Undelete</span></button></td>');
tmpl_array.push('</tr>');
return _.template(tmpl_array.join(''));
- },
-
-templateDatasetModal : function(){
- var tmpl_array = [];
-
- tmpl_array.push('<div class="modal_table">');
- tmpl_array.push(' <table class="grid table table-striped table-condensed">');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("name")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Data type</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("data_type")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Genome build</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("genome_build")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <th scope="row">Size</th>');
- tmpl_array.push(' <td><%= _.escape(size) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Date uploaded (UTC)</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Uploaded by</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr scope="row">');
- tmpl_array.push(' <th scope="row">Data Lines</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <th scope="row">Comment Lines</th>');
- tmpl_array.push(' <% if (item.get("metadata_comment_lines") === "") { %>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');
- tmpl_array.push(' <% } else { %>');
- tmpl_array.push(' <td scope="row">unknown</td>');
- tmpl_array.push(' <% } %>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Number of Columns</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Column Types</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Miscellaneous information</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' </table>');
- tmpl_array.push(' <pre class="peek">');
- tmpl_array.push(' </pre>');
- tmpl_array.push('</div>');
-
- return tmpl_array.join('');
-},
-
-templateHistorySelectInModal : function(){
- var tmpl_array = [];
-
- tmpl_array.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');
- tmpl_array.push('Select history: ');
- tmpl_array.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');
- tmpl_array.push(' <% _.each(histories, function(history) { %>'); //history select box
- tmpl_array.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');
- tmpl_array.push(' <% }); %>');
- tmpl_array.push('</select>');
- tmpl_array.push('</span>');
-
- return tmpl_array.join('');
-}
+ }
});
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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
@@ -519,16 +519,16 @@
// CONTAINER
tmpl_array.push('<div class="library_style_container">');
// TOOLBAR
- tmpl_array.push('<div id="library_folder_toolbar">');
+ tmpl_array.push('<div id="library_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(' <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(' <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>');
@@ -536,7 +536,7 @@
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(' <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">');
// library items will append here
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/mvc/library/library-librarytoolbar-view.js
--- a/static/scripts/mvc/library/library-librarytoolbar-view.js
+++ b/static/scripts/mvc/library/library-librarytoolbar-view.js
@@ -115,7 +115,7 @@
tmpl_array.push('<div class="library_style_container">');
// TOOLBAR
- tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');
+ tmpl_array.push(' <div id="toolbar_form">');
tmpl_array.push(' <% if(admin_user === true) { %>');
tmpl_array.push(' <div id="library_toolbar">');
tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Include deleted libraries"><input id="include_deleted_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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({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){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","mvc/library/library-dataset-view"],function(f,c,h,l,i,a,g,e,j,d){var m=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/datasets/:dataset_id/permissions":"dataset_permissions","folders/:folder_id/download/:format":"download"},back:function(){if(this.routesHit>1){window.history.back()}else{this.navigate("#",{trigger:true,replace:true})}}});var k=l.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 k({id:"global-lib-prefs"});this.library_router=new m();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new e.LibraryToolbarView();Galaxy.libraries.libraryListView=new g.LibraryListView()});this.library_router.on("route:folder_content",function(n){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}Galaxy.libraries.folderToolbarView=new j.FolderToolbarView({id:n});Galaxy.libraries.folderListView=new a.FolderListView({id:n})});this.library_router.on("route:download",function(n,o){if($("#folder_list_body").find(":checked").length===0){h.info("You have to select some datasets to download");Galaxy.libraries.library_router.navigate("folders/"+n,{trigger:true,replace:true})}else{Galaxy.libraries.folderToolbarView.download(n,o);Galaxy.libraries.library_router.navigate("folders/"+n,{trigger:false,replace:true})}});this.library_router.on("route:dataset_detail",function(o,n){new d.LibraryDatasetView({id:n})});this.library_router.on("route:dataset_permissions",function(o,n){new d.LibraryDatasetView({id:n,show_permissions:true})});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/packed/mvc/library/library-dataset-view.js
--- /dev/null
+++ b/static/scripts/packed/mvc/library/library-dataset-view.js
@@ -0,0 +1,1 @@
+define(["libs/toastr","mvc/library/library-model","mvc/ui/ui-select"],function(d,c,b){var a=Backbone.View.extend({el:"#center",model:null,options:{},events:{"click .toolbtn_modify_dataset":"enableModification","click .toolbtn_cancel_modifications":"render","click .toolbtn_change_permissions":"showPermissions","click .toolbtn-download-dataset":"downloadDataset","click .toolbtn-import-dataset":"importIntoHistory","click .toolbtn-share-dataset":"shareDataset"},initialize:function(e){this.options=_.extend(this.options,e);if(this.options.id){this.fetchDataset()}},fetchDataset:function(e){this.options=_.extend(this.options,e);this.model=new c.Item({id:this.options.id});var f=this;this.model.fetch({success:function(){if(f.options.show_permissions){f.showPermissions()}else{f.render()}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{d.error("An error ocurred :(. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(e){$(".tooltip").remove();this.options=_.extend(this.options,e);var f=this.templateDataset();this.$el.html(f({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},enableModification:function(){$(".tooltip").remove();var e=this.templateModifyDataset();this.$el.html(e({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},downloadDataset:function(){var e="/api/libraries/datasets/download/uncompressed";var f={ldda_ids:this.id};this.processDownload(e,f)},processDownload:function(f,g,h){if(f&&g){g=typeof g=="string"?g:$.param(g);var e="";$.each(g.split("&"),function(){var i=this.split("=");e+='<input type="hidden" name="'+i[0]+'" value="'+i[1]+'" />'});$('<form action="'+f+'" method="'+(h||"post")+'">'+e+"</form>").appendTo("body").submit().remove();d.info("Your download will begin soon")}},importIntoHistory:function(){this.refreshUserHistoriesList(function(e){var f=e.templateBulkImportInModal();e.modal=Galaxy.modal;e.modal.show({closing_events:true,title:"Import into History",body:f({histories:e.histories.models}),buttons:{Import:function(){e.importCurrentIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})},refreshUserHistoriesList:function(f){var e=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){f(e)},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg)}else{d.error("An error ocurred :(")}}})},importCurrentIntoHistory:function(){var f=this;var g=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();var h=new c.HistoryItem();h.url=h.urlRoot+g+"/contents";var e="/api/histories/"+g+"/set_as_current";$.ajax({url:e,type:"PUT"});h.save({content:this.id,source:"library"},{success:function(){Galaxy.modal.hide();d.success("Dataset imported. Click this to start analysing it.","",{onclick:function(){window.location="/"}})},error:function(j,i){if(typeof i.responseJSON!=="undefined"){d.error("Dataset not imported. "+i.responseJSON.err_msg)}else{d.error("An error occured! Dataset not imported. Please try again.")}}})},shareDataset:function(){d.info("Feature coming soon.")},showPermissions:function(){$(".tooltip").remove();var g=this.templateDatasetPermissions();this.$el.html(g({item:this.model}));var e=this;this.access_perm=new b.View({css:"access_perm",multiple:true,placeholder:"Click to select a role",container:e.$el.find("#access_perm"),ajax:{url:"/api/libraries/datasets/5969b1f7201f12ae/permissions",dataType:"json",quietMillis:100,data:function(i,j){return{q:i,page_limit:10,page:j}},results:function(k,j){var i=(j*10)<k.total;return{results:k.roles,more:i}}},formatResult:function f(i){return i.name},formatSelection:function h(i){return i.name},initSelection:function(i,k){var j=[];$(i.val().split(",")).each(function(l){var m=this.split(":");j.push({id:m[1],name:m[1]})});k(j)},initialData:"marten@bx.psu.edu:marten@bx.psu.edu",dropdownCssClass:"bigdrop"});$("#center [data-toggle]").tooltip()},templateDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push(' <div id="library_toolbar">');e.push(' <button data-toggle="tooltip" data-placement="top" title="Download dataset" class="btn btn-default toolbtn-download-dataset primary-button" type="button"><span class="fa fa-download"></span> Download</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Import dataset into history" class="btn btn-default toolbtn-import-dataset primary-button" type="button"><span class="fa fa-book"></span> to History</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Modify dataset" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Change permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Share dataset" class="btn btn-default toolbtn-share-dataset primary-button" type="button"><span class="fa fa-share"></span> Share</span></button>');e.push(" </div>");e.push('<ol class="breadcrumb">');e.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push(' <% _.each(item.get("full_path"), function(path_item) { %>');e.push(" <% if (path_item[0] != item.id) { %>");e.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push(" <% } %>");e.push(" <% }); %>");e.push("</ol>");e.push('<div class="dataset_table">');e.push(' <table class="grid table table-striped table-condensed">');e.push(" <tr>");e.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push(' <td><%= _.escape(item.get("name")) %></td>');e.push(" </tr>");e.push(' <% if (item.get("data_type")) { %>');e.push(" <tr>");e.push(' <th scope="row">Data type</th>');e.push(' <td><%= _.escape(item.get("data_type")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("genome_build")) { %>');e.push(" <tr>");e.push(' <th scope="row">Genome build</th>');e.push(' <td><%= _.escape(item.get("genome_build")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("file_size")) { %>');e.push(" <tr>");e.push(' <th scope="row">Size</th>');e.push(' <td><%= _.escape(item.get("file_size")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("date_uploaded")) { %>');e.push(" <tr>");e.push(' <th scope="row">Date uploaded (UTC)</th>');e.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("uploaded_by")) { %>');e.push(" <tr>");e.push(' <th scope="row">Uploaded by</th>');e.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_data_lines")) { %>');e.push(" <tr>");e.push(' <th scope="row">Data Lines</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_comment_lines")) { %>');e.push(" <tr>");e.push(' <th scope="row">Comment Lines</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_columns")) { %>');e.push(" <tr>");e.push(' <th scope="row">Number of Columns</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_column_types")) { %>');e.push(" <tr>");e.push(' <th scope="row">Column Types</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("message")) { %>');e.push(" <tr>");e.push(' <th scope="row">Message</th>');e.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("misc_blurb")) { %>');e.push(" <tr>");e.push(' <th scope="row">Miscellaneous blurb</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("misc_info")) { %>');e.push(" <tr>");e.push(' <th scope="row">Miscellaneous information</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(" </table>");e.push(" <div>");e.push(' <pre class="peek">');e.push(" </pre>");e.push(" </div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateModifyDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push(' <div id="library_toolbar">');e.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push(" </div>");e.push('<ol class="breadcrumb">');e.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push(' <% _.each(item.get("full_path"), function(path_item) { %>');e.push(" <% if (path_item[0] != item.id) { %>");e.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push(" <% } %>");e.push(" <% }); %>");e.push("</ol>");e.push('<div class="dataset_table">');e.push('<p>For more editing options please import the dataset to history and use "Edit attributes" on it.</p>');e.push(' <table class="grid table table-striped table-condensed">');e.push(" <tr>");e.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push(' <td><input class="input_dataset_name form-control" type="text" placeholder="name" value="<%= _.escape(item.get("name")) %>"></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Data type</th>');e.push(' <td><%= _.escape(item.get("data_type")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Genome build</th>');e.push(' <td><%= _.escape(item.get("genome_build")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Size</th>');e.push(' <td><%= _.escape(item.get("file_size")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Date uploaded (UTC)</th>');e.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Uploaded by</th>');e.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push(" </tr>");e.push(' <tr scope="row">');e.push(' <th scope="row">Data Lines</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push(" </tr>");e.push(' <th scope="row">Comment Lines</th>');e.push(' <% if (item.get("metadata_comment_lines") === "") { %>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push(" <% } else { %>");e.push(' <td scope="row">unknown</td>');e.push(" <% } %>");e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Number of Columns</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Column Types</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Message</th>');e.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Miscellaneous information</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Miscellaneous blurb</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push(" </tr>");e.push(" </table>");e.push("<div>");e.push(' <pre class="peek">');e.push(" </pre>");e.push("</div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateDatasetPermissions:function(){var e=[];e.push('<div class="library_style_container">');e.push(' <div id="library_toolbar">');e.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push(" </div>");e.push('<ol class="breadcrumb">');e.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push(' <% _.each(item.get("full_path"), function(path_item) { %>');e.push(" <% if (path_item[0] != item.id) { %>");e.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push(" <% } %>");e.push(" <% }); %>");e.push("</ol>");e.push('<h1><%= _.escape(item.get("name")) %></h1>');e.push('<div class="alert alert-success">You have rights to change permissions on this dataset. That means you can control who can access it, who can modify it and also appoint others that can manage permissions on it.</div>');e.push('<div class="dataset_table">');e.push("<h2>Basic permissions</h2>");e.push("<p>You can remove all access restrictions on this dataset. ");e.push('<button data-toggle="tooltip" data-placement="top" title="Everybody will be able to see the dataset." class="btn btn-default btn-remove-restrictions primary-button" type="button"><span class="fa fa-globe"></span> Remove restrictions</span></button>');e.push("</p>");e.push("<p>You can make this dataset private to you. ");e.push('<button data-toggle="tooltip" data-placement="top" title="Only you will be able to see the dataset." class="btn btn-default btn-make-private primary-button" type="button"><span class="fa fa-key"></span> Make private</span></button>');e.push("</p>");e.push("<h2>Advanced permissions</h2>");e.push("<p>You can assign any number of roles to any of the following three dataset permissions:</p>");e.push("<h3>Access Roles</h3>");e.push('<div class="alert alert-info">User has to have <strong>all these roles</strong> in order to see this dataset.</div>');e.push('<div id="access_perm" class="access_perm roles-selection"></div>');e.push("<h3>Modify Roles</h3>");e.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can modify the information about this dataset.</div>');e.push('<div id="modify_perm" class="modify_perm"></div>');e.push("<h3>Manage Roles</h3>");e.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can change permissions of this dataset.</div>');e.push('<div id="manage_perm" class="manage_perm"></div>');e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateBulkImportInModal:function(){var e=[];e.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');e.push("Select history: ");e.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');e.push(" <% _.each(histories, function(history) { %>");e.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');e.push(" <% }); %>");e.push("</select>");e.push("</span>");return _.template(e.join(""))}});return{LibraryDatasetView:a}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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+" 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").addClass("dark");g.find("a").removeClass("light").addClass("dark");g.find(".fa-file-o").removeClass("fa-file-o").addClass("fa-file")},makeWhiteRow:function(g){g.removeClass("dark").addClass("light");g.find("a").removeClass("dark").addClass("light");g.find(".fa-file").removeClass("fa-file").addClass("fa-file-o")},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><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 style="width:5%;">data type</th>');g.push(' <th style="width:5%;">size</th>');g.push(' <th style="width:160px;">time updated (UTC)</th>');g.push(' <th style="width:10%;"></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. If you expected something to show up please consult the <a href="https://wiki.galaxyproject.org/Admin/DataLibraries/LibrarySecurity">library security wikipage</a> or visit the <a href="https://biostar.usegalaxy.org/">Galaxy support site</a>.</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","mvc/library/library-dataset-view"],function(d,f,g,e,a,c){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(h){this.options=_.defaults(this.options||{},h);this.fetchFolder()},fetchFolder:function(h){var h=h||{};this.options.include_deleted=h.include_deleted;var i=this;this.collection=new e.Folder();this.listenTo(this.collection,"add",this.renderOne);this.listenTo(this.collection,"remove",this.removeOne);this.folderContainer=new e.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(j){i.folder_container=j;i.render();i.addAll(j.get("folder").models);if(i.options.dataset_id){row=_.findWhere(i.rowViews,{id:i.options.dataset_id});if(row){row.showDatasetDetails()}else{g.error("Dataset not found. Showing folder instead.")}}},error:function(k,j){if(typeof j.responseJSON!=="undefined"){g.error(j.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{g.error("An error ocurred :(. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(h){this.options=_.defaults(this.options,h);var i=this.templateFolder();var j=this.folderContainer.attributes.metadata.full_path;var k;if(j.length===1){k=0}else{k=j[j.length-2][0]}this.$el.html(i({path:this.folderContainer.attributes.metadata.full_path,id:this.options.id,upper_folder_id:k,order:this.sort}));$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},postRender:function(){var h=this.folderContainer.attributes.metadata;h.contains_file=typeof this.collection.findWhere({type:"file"})!=="undefined";Galaxy.libraries.folderToolbarView.configureElements(h);$(".dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},addAll:function(h){_.each(h.reverse(),function(i){Galaxy.libraries.folderListView.collection.add(i)});$("#center [data-toggle]").tooltip();this.checkEmptiness();this.postRender()},renderAll:function(){var h=this;_.each(this.collection.models.reverse(),function(i){h.renderOne(i)});this.postRender()},renderOne:function(i){if(i.get("data_type")!=="folder"){this.options.contains_file=true}i.set("folder_id",this.id);var h=new a.FolderRowView(i);this.rowViews[i.get("id")]=h;this.$el.find("#first_folder_item").after(h.el);$(".dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},removeOne:function(h){this.$el.find("#"+h.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(h){h.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(i,h){if(i==="name"){if(h==="asc"){return this.collection.sortByNameAsc()}else{if(h==="desc"){return this.collection.sortByNameDesc()}}}},selectAll:function(i){var h=i.target.checked;that=this;$(":checkbox","#folder_list_body").each(function(){this.checked=h;$row=$(this.parentElement.parentElement);if(h){that.makeDarkRow($row)}else{that.makeWhiteRow($row)}})},selectClickedRow:function(i){var k="";var h;var j;if(i.target.localName==="input"){k=i.target;h=$(i.target.parentElement.parentElement);j="input"}else{if(i.target.localName==="td"){k=$("#"+i.target.parentElement.id).find(":checkbox")[0];h=$(i.target.parentElement);j="td"}}if(k.checked){if(j==="td"){k.checked="";this.makeWhiteRow(h)}else{if(j==="input"){this.makeDarkRow(h)}}}else{if(j==="td"){k.checked="selected";this.makeDarkRow(h)}else{if(j==="input"){this.makeWhiteRow(h)}}}},makeDarkRow:function(h){h.removeClass("light").addClass("dark");h.find("a").removeClass("light").addClass("dark");h.find(".fa-file-o").removeClass("fa-file-o").addClass("fa-file")},makeWhiteRow:function(h){h.removeClass("dark").addClass("light");h.find("a").removeClass("dark").addClass("light");h.find(".fa-file").removeClass("fa-file").addClass("fa-file-o")},templateFolder:function(){var h=[];h.push('<ol class="breadcrumb">');h.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');h.push(" <% _.each(path, function(path_item) { %>");h.push(" <% if (path_item[0] != id) { %>");h.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');h.push("<% } else { %>");h.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');h.push(" <% } %>");h.push(" <% }); %>");h.push("</ol>");h.push('<table id="folder_table" class="grid table table-condensed">');h.push(" <thead>");h.push(' <th class="button_heading"></th>');h.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>');h.push(' <th><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>');h.push(' <th style="width:5%;">data type</th>');h.push(' <th style="width:10%;">size</th>');h.push(' <th style="width:160px;">time updated (UTC)</th>');h.push(' <th style="width:10%;"></th> ');h.push(" </thead>");h.push(' <tbody id="folder_list_body">');h.push(' <tr id="first_folder_item">');h.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>');h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" </tr>");h.push(" </tbody>");h.push("</table>");h.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. If you expected something to show up please consult the <a href="https://wiki.galaxyproject.org/Admin/DataLibraries/LibrarySecurity">library security wikipage</a> or visit the <a href="https://biostar.usegalaxy.org/">Galaxy support site</a>.</div>');return _.template(h.join(""))}});return{FolderListView:b}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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()}},closing_callback:function(){var l=Backbone.history.fragment.split("/datasets")[0];Galaxy.libraries.library_router.navigate("#"+l,{trigger:true,replace:true})}});$(".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(h){$(".tooltip").hide();var g=this;var f=$(h.target).closest("tr")[0].id;var i=Galaxy.libraries.folderListView.collection.get(f);i.url=i.urlRoot+i.id+"?undelete=true";i.destroy({success:function(k,j){Galaxy.libraries.folderListView.collection.remove(f);var l=new c.Item(j);Galaxy.libraries.folderListView.collection.add(l);e.success("Dataset undeleted. Click this to see it.","",{onclick:function(){g.showDatasetDetails()}})},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error("Dataset was not undeleted. "+j.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(" </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>");tmpl_array.push(' <% if (content_item.get("is_unrestricted")) { %><span data-toggle="tooltip" data-placement="top" title="Unrestricted dataset" style="color:grey;" class="fa fa-globe fa-lg"></span><% } %>');tmpl_array.push(' <% if (content_item.get("is_private")) { %><span data-toggle="tooltip" data-placement="top" title="Private dataset" style="color:grey;" class="fa fa-key fa-lg"></span><% } %>');tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-group fa-lg"></span>');tmpl_array.push(" <% } %>");tmpl_array.push(" </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></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><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span><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; margin-left:1em;"><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","mvc/library/library-dataset-view"],function(c,e,f,d,b){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .undelete_dataset_btn":"undelete_dataset"},options:{type:null},initialize:function(g){this.render(g)},render:function(g){var h=null;if(g.get("type")==="folder"){this.options.type="folder";h=this.templateRowFolder()}else{this.options.type="file";if(g.get("deleted")){h=this.templateRowDeletedFile()}else{h=this.templateRowFile()}}this.setElement(h({content_item:g}));this.$el.show();return this},showDatasetDetails:function(){this.dataset_view=new b.LibraryDatasetView({id:this.id})},undelete_dataset:function(i){$(".tooltip").hide();var h=this;var g=$(i.target).closest("tr")[0].id;var j=Galaxy.libraries.folderListView.collection.get(g);j.url=j.urlRoot+j.id+"?undelete=true";j.destroy({success:function(l,k){Galaxy.libraries.folderListView.collection.remove(g);var m=new d.Item(k);Galaxy.libraries.folderListView.collection.add(m);f.success("Dataset undeleted. Click this to see it.","",{onclick:function(){h.showDatasetDetails()}})},error:function(l,k){if(typeof k.responseJSON!=="undefined"){f.error("Dataset was not undeleted. "+k.responseJSON.err_msg)}else{f.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(" </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 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 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("file_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td>");tmpl_array.push(' <% if (content_item.get("is_unrestricted")) { %><span data-toggle="tooltip" data-placement="top" title="Unrestricted dataset" style="color:grey;" class="fa fa-globe fa-lg"></span><% } %>');tmpl_array.push(' <% if (content_item.get("is_private")) { %><span data-toggle="tooltip" data-placement="top" title="Private dataset" style="color:grey;" class="fa fa-key fa-lg"></span><% } %>');tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-shield fa-lg"></span><% } %>');tmpl_array.push(' <% if (content_item.get("can_manage")) { %><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" class="primary-button btn-xs permissions-dataset-btn show_on_hover" title="Manage permissions" style="display:none;"><span class="fa fa-group"></span></button></a><% } %>');tmpl_array.push(" </td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowDeletedFile:function(){tmpl_array=[];tmpl_array.push('<tr class="active deleted_dataset 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></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("file_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></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><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; margin-left:1em;"><span class="fa fa-unlock"> Undelete</span></button></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))}});return{FolderRowView:a}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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 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
+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_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
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/packed/mvc/library/library-librarytoolbar-view.js
--- a/static/scripts/packed/mvc/library/library-librarytoolbar-view.js
+++ b/static/scripts/packed/mvc/library/library-librarytoolbar-view.js
@@ -1,1 +1,1 @@
-define(["libs/toastr","mvc/library/library-model"],function(b,a){var c=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},render:function(){var f=this.templateToolBar();var e=false;var d=true;if(Galaxy.currUser){e=Galaxy.currUser.isAdmin();d=Galaxy.currUser.isAnonymous()}this.$el.html(f({admin_user:e,anon_user:d}));if(e){this.$el.find("#include_deleted_chk")[0].checked=Galaxy.libraries.preferences.get("with_deleted")}},show_library_modal:function(e){e.preventDefault();e.stopPropagation();var d=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){d.create_new_library_event()},Close:function(){d.modal.hide()}}})},create_new_library_event:function(){var f=this.serialize_new_library();if(this.validate_new_library(f)){var e=new a.Library();var d=this;e.save(f,{success:function(g){Galaxy.libraries.libraryListView.collection.add(g);d.modal.hide();d.clear_library_modal();Galaxy.libraries.libraryListView.render();b.success("Library created")},error:function(h,g){if(typeof g.responseJSON!=="undefined"){b.error(g.responseJSON.err_msg)}else{b.error("An error occured :(")}}})}else{b.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(d){return d.name!==""},check_include_deleted:function(d){if(d.target.checked){Galaxy.libraries.preferences.set({with_deleted:true});Galaxy.libraries.libraryListView.render()}else{Galaxy.libraries.preferences.set({with_deleted:false});Galaxy.libraries.libraryListView.render()}},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');tmpl_array.push(" <% if(admin_user === true) { %>");tmpl_array.push(' <div id="library_toolbar">');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Include deleted libraries"><input id="include_deleted_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Create New Library"><button id="create_new_library_btn" class="primary-button btn-xs" type="button"><span class="fa fa-plus"></span> New Library</button><span>');tmpl_array.push(" </div>");tmpl_array.push(" <% } %>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="libraries_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_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(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")}});return{LibraryToolbarView:c}});
\ No newline at end of file
+define(["libs/toastr","mvc/library/library-model"],function(b,a){var c=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},render:function(){var f=this.templateToolBar();var e=false;var d=true;if(Galaxy.currUser){e=Galaxy.currUser.isAdmin();d=Galaxy.currUser.isAnonymous()}this.$el.html(f({admin_user:e,anon_user:d}));if(e){this.$el.find("#include_deleted_chk")[0].checked=Galaxy.libraries.preferences.get("with_deleted")}},show_library_modal:function(e){e.preventDefault();e.stopPropagation();var d=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){d.create_new_library_event()},Close:function(){d.modal.hide()}}})},create_new_library_event:function(){var f=this.serialize_new_library();if(this.validate_new_library(f)){var e=new a.Library();var d=this;e.save(f,{success:function(g){Galaxy.libraries.libraryListView.collection.add(g);d.modal.hide();d.clear_library_modal();Galaxy.libraries.libraryListView.render();b.success("Library created")},error:function(h,g){if(typeof g.responseJSON!=="undefined"){b.error(g.responseJSON.err_msg)}else{b.error("An error occured :(")}}})}else{b.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(d){return d.name!==""},check_include_deleted:function(d){if(d.target.checked){Galaxy.libraries.preferences.set({with_deleted:true});Galaxy.libraries.libraryListView.render()}else{Galaxy.libraries.preferences.set({with_deleted:false});Galaxy.libraries.libraryListView.render()}},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push(' <div id="toolbar_form">');tmpl_array.push(" <% if(admin_user === true) { %>");tmpl_array.push(' <div id="library_toolbar">');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Include deleted libraries"><input id="include_deleted_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Create New Library"><button id="create_new_library_btn" class="primary-button btn-xs" type="button"><span class="fa fa-plus"></span> New Library</button><span>');tmpl_array.push(" </div>");tmpl_array.push(" <% } %>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="libraries_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_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(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")}});return{LibraryToolbarView:c}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1305,18 +1305,21 @@
tr.dark td{background-color:#d6b161;color:white}
tr.dark:hover td{background-color:#ebd4a4;color:white}
a.dark{color:white}
-.modal_table tr{border-bottom:1px solid #5f6990 !important}
-.modal_table th{border:none !important}
-.modal_table td{border:none !important}
+.dataset_table tr{border-bottom:1px solid #5f6990 !important}
+.dataset_table th{border:none !important}
+.dataset_table td{border:none !important}
th.button_heading{width:2em}
-#library_folder_toolbar{margin-bottom:1em}#library_folder_toolbar span{margin-right:0.2em}
+.bigdrop.select2-container .select2-results{max-height:300px}
+.bigdrop .select2-results{max-height:300px}
+.select2-container-multi{width:100%}
+.roles-selection{width:66%}
#library_toolbar{margin-bottom:1em}#library_toolbar span{margin-right:0.2em}
img.expanderIcon{padding-right:4px}
input.datasetCheckbox,li,ul{padding:0;margin:0}
.rowTitle{padding:2px}
ul{list-style:none}
.libraryTitle th{text-align:left}
-pre.peek{background:white;color:black;width:100%;overflow:auto}
+pre.peek{background:white;color:black;overflow:auto}
pre.peek th{color:white;background:#ebd9b2}
span.expandLink{padding-left:12px;display:inline-block;vertical-align:middle;background:url(../images/silk/resultset_next.png) no-repeat}
.folderRow.expanded span.expandLink{background:url(../images/silk/resultset_bottom.png) no-repeat}
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/style/blue/library.css
--- a/static/style/blue/library.css
+++ b/static/style/blue/library.css
@@ -16,18 +16,21 @@
tr.dark td{background-color:#d6b161;color:white}
tr.dark:hover td{background-color:#ebd4a4;color:white}
a.dark{color:white}
-.modal_table tr{border-bottom:1px solid #5f6990 !important}
-.modal_table th{border:none !important}
-.modal_table td{border:none !important}
+.dataset_table tr{border-bottom:1px solid #5f6990 !important}
+.dataset_table th{border:none !important}
+.dataset_table td{border:none !important}
th.button_heading{width:2em}
-#library_folder_toolbar{margin-bottom:1em}#library_folder_toolbar span{margin-right:0.2em}
+.bigdrop.select2-container .select2-results{max-height:300px}
+.bigdrop .select2-results{max-height:300px}
+.select2-container-multi{width:100%}
+.roles-selection{width:66%}
#library_toolbar{margin-bottom:1em}#library_toolbar span{margin-right:0.2em}
img.expanderIcon{padding-right:4px}
input.datasetCheckbox,li,ul{padding:0;margin:0}
.rowTitle{padding:2px}
ul{list-style:none}
.libraryTitle th{text-align:left}
-pre.peek{background:white;color:black;width:100%;overflow:auto}
+pre.peek{background:white;color:black;overflow:auto}
pre.peek th{color:white;background:#ebd9b2}
span.expandLink{padding-left:12px;display:inline-block;vertical-align:middle;background:url(../images/silk/resultset_next.png) no-repeat}
.folderRow.expanded span.expandLink{background:url(../images/silk/resultset_bottom.png) no-repeat}
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/style/src/less/library.less
--- a/static/style/src/less/library.less
+++ b/static/style/src/less/library.less
@@ -80,7 +80,7 @@
color: white;
}
-.modal_table{
+.dataset_table{
tr {
border-bottom: 1px solid #5f6990 !important;
}
@@ -97,12 +97,19 @@
width: 2em;
}
-#library_folder_toolbar {
- margin-bottom: 1em;
- span {
- margin-right: 0.2em;
- }
+.bigdrop.select2-container .select2-results {
+ max-height: 300px;
}
+.bigdrop .select2-results {
+ max-height: 300px;
+}
+.select2-container-multi{
+ width: 100%;
+}
+.roles-selection {
+ width: 66%;
+}
+
#library_toolbar {
margin-bottom: 1em;
span {
@@ -135,7 +142,7 @@
pre.peek {
background: white;
color: black;
- width: 100%;
+ // width: 100%;
overflow: auto;
}
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 templates/webapps/galaxy/galaxy.panels.mako
--- a/templates/webapps/galaxy/galaxy.panels.mako
+++ b/templates/webapps/galaxy/galaxy.panels.mako
@@ -31,6 +31,7 @@
${h.js(
'libs/jquery/jquery',
'libs/jquery/jquery-ui',
+ "libs/jquery/select2",
'libs/bootstrap',
'libs/underscore',
'libs/backbone/backbone',
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: extended ui-select module to support multiple inputs and on-demand ajax loading of paginated data
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b027397c99c6/
Changeset: b027397c99c6
User: martenson
Date: 2014-05-14 19:50:15
Summary: extended ui-select module to support multiple inputs and on-demand ajax loading of paginated data
Affected #: 2 files
diff -r 882f51a4d9dced2ce731c5b4afa5bed9623933c2 -r b027397c99c639d5b200b88649c6e7ca75a292f8 static/scripts/mvc/ui/ui-select.js
--- a/static/scripts/mvc/ui/ui-select.js
+++ b/static/scripts/mvc/ui/ui-select.js
@@ -11,10 +11,13 @@
{
// options
optionsDefault: {
- css : '',
- placeholder : 'No data available',
- data : [],
- value : null
+ css : '',
+ placeholder : 'No data available',
+ data : [],
+ value : null,
+ multiple : false,
+ minimumInputLength : 0,
+ initialData : ''
},
// initialize
@@ -40,17 +43,19 @@
// refresh
this._refresh();
- // initial value
- if (this.options.value) {
- this._setValue(this.options.value);
- }
-
- // add change event
- var self = this;
- if (this.options.onchange) {
- this.$el.on('change', function() {
- self.options.onchange(self.value());
- });
+ if (!this.options.multiple){
+ // initial value
+ if (this.options.value) {
+ this._setValue(this.options.value);
+ }
+
+ // add change event
+ var self = this;
+ if (this.options.onchange) {
+ this.$el.on('change', function() {
+ self.options.onchange(self.value());
+ });
+ }
}
},
@@ -142,18 +147,33 @@
// refresh
_refresh: function() {
- // selected
- var selected = this._getValue();
-
- // add select2 data
- this.$el.select2({
- data : this.select_data,
- containerCssClass : this.options.css,
- placeholder : this.options.placeholder
- });
-
- // select previous value (if exists)
- this._setValue(selected);
+ // add select2 data based on type of input
+ if (!this.options.multiple){
+ var selected = this._getValue();
+ var select_opt = {
+ data : this.select_data,
+ containerCssClass : this.options.css,
+ placeholder : this.options.placeholder,
+ };
+ this.$el.select2(select_opt);
+ // select previous value (if exists)
+ this._setValue(selected);
+ } else {
+ var select_opt = {
+ multiple : this.options.multiple,
+ containerCssClass : this.options.css,
+ placeholder : this.options.placeholder,
+ minimumInputLength : this.options.minimumInputLength,
+ ajax : this.options.ajax,
+ dropdownCssClass : this.options.dropdownCssClass,
+ escapeMarkup : this.options.escapeMarkup,
+ formatResult : this.options.formatResult,
+ formatSelection : this.options.formatSelection,
+ initSelection : this.options.initSelection,
+ initialData : this.options.initialData
+ };
+ this.$el.select2(select_opt);
+ }
},
// get index
@@ -186,8 +206,8 @@
},
// element
- _template: function() {
- return '<input type="hidden"/>';
+ _template: function(options) {
+ return '<input type="hidden" value="' + this.options.initialData + '"/>';
}
});
diff -r 882f51a4d9dced2ce731c5b4afa5bed9623933c2 -r b027397c99c639d5b200b88649c6e7ca75a292f8 static/scripts/packed/mvc/ui/ui-select.js
--- a/static/scripts/packed/mvc/ui/ui-select.js
+++ b/static/scripts/packed/mvc/ui/ui-select.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{css:"",placeholder:"No data available",data:[],value:null},initialize:function(d){this.options=a.merge(d,this.optionsDefault);this.setElement(this._template(this.options));if(!this.options.container){console.log("ui-select::initialize() : container not specified.");return}this.options.container.append(this.$el);this.select_data=this.options.data;this._refresh();if(this.options.value){this._setValue(this.options.value)}var c=this;if(this.options.onchange){this.$el.on("change",function(){c.options.onchange(c.value())})}},value:function(c){var d=this._getValue();if(c!==undefined){this._setValue(c)}var e=this._getValue();if((e!=d&&this.options.onchange)){this.options.onchange(e)}return e},text:function(){return this.$el.select2("data").text},disabled:function(){return !this.$el.select2("enable")},enable:function(){this.$el.select2("enable",true)},disable:function(){this.$el.select2("enable",false)},add:function(c){this.select_data.push({id:c.id,text:c.text});this._refresh()},del:function(d){var c=this._getIndex(d);if(c!=-1){this.select_data.splice(c,1);this._refresh()}},remove:function(){this.$el.select2("destroy")},update:function(c){this.select_data=[];for(var d in c.data){this.select_data.push(c.data[d])}this._refresh()},_refresh:function(){var c=this._getValue();this.$el.select2({data:this.select_data,containerCssClass:this.options.css,placeholder:this.options.placeholder});this._setValue(c)},_getIndex:function(d){for(var c in this.select_data){if(this.select_data[c].id==d){return c}}return -1},_getValue:function(){return this.$el.select2("val")},_setValue:function(d){var c=this._getIndex(d);if(c==-1){if(this.select_data.length>0){d=this.select_data[0].id}}this.$el.select2("val",d)},_template:function(){return'<input type="hidden"/>'}});return{View:b}});
\ No newline at end of file
+define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{css:"",placeholder:"No data available",data:[],value:null,multiple:false,minimumInputLength:0,initialData:""},initialize:function(d){this.options=a.merge(d,this.optionsDefault);this.setElement(this._template(this.options));if(!this.options.container){console.log("ui-select::initialize() : container not specified.");return}this.options.container.append(this.$el);this.select_data=this.options.data;this._refresh();if(!this.options.multiple){if(this.options.value){this._setValue(this.options.value)}var c=this;if(this.options.onchange){this.$el.on("change",function(){c.options.onchange(c.value())})}}},value:function(c){var d=this._getValue();if(c!==undefined){this._setValue(c)}var e=this._getValue();if((e!=d&&this.options.onchange)){this.options.onchange(e)}return e},text:function(){return this.$el.select2("data").text},disabled:function(){return !this.$el.select2("enable")},enable:function(){this.$el.select2("enable",true)},disable:function(){this.$el.select2("enable",false)},add:function(c){this.select_data.push({id:c.id,text:c.text});this._refresh()},del:function(d){var c=this._getIndex(d);if(c!=-1){this.select_data.splice(c,1);this._refresh()}},remove:function(){this.$el.select2("destroy")},update:function(c){this.select_data=[];for(var d in c.data){this.select_data.push(c.data[d])}this._refresh()},_refresh:function(){if(!this.options.multiple){var d=this._getValue();var c={data:this.select_data,containerCssClass:this.options.css,placeholder:this.options.placeholder,};this.$el.select2(c);this._setValue(d)}else{var c={multiple:this.options.multiple,containerCssClass:this.options.css,placeholder:this.options.placeholder,minimumInputLength:this.options.minimumInputLength,ajax:this.options.ajax,dropdownCssClass:this.options.dropdownCssClass,escapeMarkup:this.options.escapeMarkup,formatResult:this.options.formatResult,formatSelection:this.options.formatSelection,initSelection:this.options.initSelection,initialData:this.options.initialData};this.$el.select2(c)}},_getIndex:function(d){for(var c in this.select_data){if(this.select_data[c].id==d){return c}}return -1},_getValue:function(){return this.$el.select2("val")},_setValue:function(d){var c=this._getIndex(d);if(c==-1){if(this.select_data.length>0){d=this.select_data[0].id}}this.$el.select2("val",d)},_template:function(c){return'<input type="hidden" value="'+this.options.initialData+'"/>'}});return{View:b}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Fix for when hours_between_check is defined in ini.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/882f51a4d9dc/
Changeset: 882f51a4d9dc
User: dan
Date: 2014-05-14 18:04:47
Summary: Fix for when hours_between_check is defined in ini.
Affected #: 1 file
diff -r 8b8b08da7231d3ea2bf7ccb6585a20f7e0c64cad -r 882f51a4d9dced2ce731c5b4afa5bed9623933c2 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -108,6 +108,8 @@
self.manage_dependency_relationships = string_as_bool( kwargs.get( 'manage_dependency_relationships', False ) )
self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
self.hours_between_check = kwargs.get( 'hours_between_check', 12 )
+ if isinstance( self.hours_between_check, basestring ):
+ self.hours_between_check = float( self.hours_between_check )
try:
if isinstance( self.hours_between_check, int ):
if self.hours_between_check < 1 or self.hours_between_check > 24:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Allow for an arbitrary number of tool_data_table_config_path files to be defined in ini file. Values are comma separated.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8b8b08da7231/
Changeset: 8b8b08da7231
User: dan
Date: 2014-05-14 17:52:20
Summary: Allow for an arbitrary number of tool_data_table_config_path files to be defined in ini file. Values are comma separated.
Affected #: 2 files
diff -r 6b86b4186c455317cba726c7ad6579a030922421 -r 8b8b08da7231d3ea2bf7ccb6585a20f7e0c64cad lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -102,7 +102,7 @@
self.shed_tool_data_path = resolve_path( self.shed_tool_data_path, self.root )
else:
self.shed_tool_data_path = self.tool_data_path
- self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root )
+ self.tool_data_table_config_path = [ resolve_path( x, self.root ) for x in kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ).split( ',' ) ]
self.shed_tool_data_table_config = resolve_path( kwargs.get( 'shed_tool_data_table_config', 'shed_tool_data_table_conf.xml' ), self.root )
self.enable_tool_shed_check = string_as_bool( kwargs.get( 'enable_tool_shed_check', False ) )
self.manage_dependency_relationships = string_as_bool( kwargs.get( 'manage_dependency_relationships', False ) )
diff -r 6b86b4186c455317cba726c7ad6579a030922421 -r 8b8b08da7231d3ea2bf7ccb6585a20f7e0c64cad lib/galaxy/tools/data/__init__.py
--- a/lib/galaxy/tools/data/__init__.py
+++ b/lib/galaxy/tools/data/__init__.py
@@ -56,19 +56,22 @@
3. When a tool shed repository that includes a tool_data_table_conf.xml.sample file is being installed into a local
Galaxy instance. In this case, we have 2 entry types to handle, files whose root tag is <tables>, for example:
"""
- tree = util.parse_xml( config_filename )
- root = tree.getroot()
table_elems = []
- for table_elem in root.findall( 'table' ):
- table = ToolDataTable.from_elem( table_elem, tool_data_path, from_shed_config )
- table_elems.append( table_elem )
- if table.name not in self.data_tables:
- self.data_tables[ table.name ] = table
- log.debug( "Loaded tool data table '%s'", table.name )
- else:
- log.debug( "Loading another instance of data table '%s', attempting to merge content.", table.name )
- self.data_tables[ table.name ].merge_tool_data_table( table, allow_duplicates=False ) #only merge content, do not persist to disk, do not allow duplicate rows when merging
- # FIXME: This does not account for an entry with the same unique build ID, but a different path.
+ if not isinstance( config_filename, list ):
+ config_filename = [ config_filename ]
+ for filename in config_filename:
+ tree = util.parse_xml( filename )
+ root = tree.getroot()
+ for table_elem in root.findall( 'table' ):
+ table = ToolDataTable.from_elem( table_elem, tool_data_path, from_shed_config )
+ table_elems.append( table_elem )
+ if table.name not in self.data_tables:
+ self.data_tables[ table.name ] = table
+ log.debug( "Loaded tool data table '%s'", table.name )
+ else:
+ log.debug( "Loading another instance of data table '%s', attempting to merge content.", table.name )
+ self.data_tables[ table.name ].merge_tool_data_table( table, allow_duplicates=False ) #only merge content, do not persist to disk, do not allow duplicate rows when merging
+ # FIXME: This does not account for an entry with the same unique build ID, but a different path.
return table_elems
def add_new_entries_from_config_file( self, config_filename, tool_data_path, shed_tool_data_table_config, persist=False ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Bugfix for updating history dataset collection name.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6b86b4186c45/
Changeset: 6b86b4186c45
User: jmchilton
Date: 2014-05-14 12:26:21
Summary: Bugfix for updating history dataset collection name.
Thanks to Bjoern for the bug report.
This attribute had been DatasetCollection in earlier versions of this code and the update code was only partially cut-over to use the new location for name (on HistoryDatasetCollectionAssociation).
Affected #: 2 files
diff -r e0d69ca8be55cd8cfd863ad7f128e95a42eabfd3 -r 6b86b4186c455317cba726c7ad6579a030922421 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -2636,20 +2636,8 @@
return new_collection
def set_from_dict( self, new_data ):
- editable_keys = ( 'name' )
- changed = {}
-
- # unknown keys are ignored here
- for key in [ k for k in new_data.keys() if k in editable_keys ]:
- new_val = new_data[ key ]
- old_val = self.__getattribute__( key )
- if new_val == old_val:
- continue
-
- self.__setattr__( key, new_val )
- changed[ key ] = new_val
-
- return changed
+ # Nothing currently editable in this class.
+ return {}
class DatasetCollectionInstance( object, HasName ):
diff -r e0d69ca8be55cd8cfd863ad7f128e95a42eabfd3 -r 6b86b4186c455317cba726c7ad6579a030922421 test/api/test_history_contents.py
--- a/test/api/test_history_contents.py
+++ b/test/api/test_history_contents.py
@@ -128,12 +128,28 @@
dataset_collection = show_response.json()
assert dataset_collection[ "deleted" ]
- def __show( self, hda ):
- show_response = self._get( "histories/%s/contents/%s" % ( self.history_id, hda[ "id" ] ) )
+ def test_update_dataset_collection( self ):
+ payload = self.dataset_collection_populator.create_pair_payload(
+ self.history_id,
+ type="dataset_collection"
+ )
+ dataset_collection_response = self._post( "histories/%s/contents" % self.history_id, payload )
+ self._assert_status_code_is( dataset_collection_response, 200 )
+ hdca = dataset_collection_response.json()
+ update_url = self._api_url( "histories/%s/contents/dataset_collections/%s" % ( self.history_id, hdca[ "id" ] ), use_key=True )
+ # Awkward json.dumps required here because of https://trello.com/c/CQwmCeG6
+ body = json.dumps( dict( name="newnameforpair" ) )
+ update_response = put_request( update_url, data=body )
+ self._assert_status_code_is( update_response, 200 )
+ show_response = self.__show( hdca )
+ assert str( show_response.json()[ "name" ] ) == "newnameforpair"
+
+ def __show( self, contents ):
+ show_response = self._get( "histories/%s/contents/%ss/%s" % ( self.history_id, contents["history_content_type"], contents[ "id" ] ) )
return show_response
def __count_contents( self, history_id=None, **kwds ):
- if history_id == None:
+ if history_id is None:
history_id = self.history_id
contents_response = self._get( "histories/%s/contents" % history_id, kwds )
return len( contents_response.json() )
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