mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge galaxy/galaxy-central default branch.
This commit is contained in:
@@ -60,6 +60,10 @@ class MalformedId( MessageException ):
|
||||
status_code = 400
|
||||
err_code = error_codes.MALFORMED_ID
|
||||
|
||||
class UnknownContentsType( MessageException ):
|
||||
status_code = 400
|
||||
err_code = error_codes.UNKNOWN_CONTENTS_TYPE
|
||||
|
||||
class RequestParameterMissingException( MessageException ):
|
||||
status_code = 400
|
||||
err_code = error_codes.USER_REQUEST_MISSING_PARAMETER
|
||||
|
||||
@@ -49,6 +49,11 @@
|
||||
"code": 400009,
|
||||
"message": "The id of the resource is malformed."
|
||||
},
|
||||
{
|
||||
"name": "UNKNOWN_CONTENTS_TYPE",
|
||||
"code": 400010,
|
||||
"message": "The request contains unknown type of contents."
|
||||
},
|
||||
{
|
||||
"name": "USER_NO_API_KEY",
|
||||
"code": 403001,
|
||||
|
||||
@@ -4,6 +4,7 @@ from galaxy.model.item_attrs import Dictifiable
|
||||
from galaxy.util.bunch import Bunch
|
||||
from galaxy.util import asbool
|
||||
from tool_shed.util import common_util
|
||||
from urlparse import urljoin
|
||||
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
@@ -73,6 +74,12 @@ class ToolShedRepository( object ):
|
||||
def can_reinstall_or_activate( self ):
|
||||
return self.deleted
|
||||
|
||||
def get_sharable_url( self, app ):
|
||||
tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, self.tool_shed )
|
||||
if tool_shed_url:
|
||||
return urljoin( tool_shed_url, 'view/%s/%s' % ( self.owner, self.name ) )
|
||||
return tool_shed_url
|
||||
|
||||
def get_shed_config_filename( self ):
|
||||
shed_config_filename = None
|
||||
if self.metadata:
|
||||
|
||||
@@ -28,7 +28,9 @@ ${message}
|
||||
-----------------------------------------------------------------------------
|
||||
job id: ${job_id}
|
||||
tool id: ${job_tool_id}
|
||||
tool version: ${tool_version}
|
||||
job pid or drm id: ${job_runner_external_id}
|
||||
job tool version: ${job_tool_version}
|
||||
-----------------------------------------------------------------------------
|
||||
job command line:
|
||||
${job_command_line}
|
||||
@@ -86,7 +88,9 @@ class ErrorReporter( object ):
|
||||
history_item_name=hda.get_display_name(),
|
||||
history_view_link=history_view_link,
|
||||
job_id=job.id,
|
||||
tool_version=job.tool_version,
|
||||
job_tool_id=job.tool_id,
|
||||
job_tool_version=hda.tool_version,
|
||||
job_runner_external_id=job.job_runner_external_id,
|
||||
job_command_line=job.command_line,
|
||||
job_stderr=util.unicodify( job.stderr ),
|
||||
|
||||
@@ -979,7 +979,7 @@ class SelectToolParameter( ToolParameter ):
|
||||
if option[2]:
|
||||
# Found selected option.
|
||||
value = option[1]
|
||||
d[ 'value' ] = options
|
||||
d[ 'value' ] = value
|
||||
|
||||
return d
|
||||
|
||||
|
||||
@@ -86,7 +86,14 @@ def populate_tag_payload( payload=None, tool=None ):
|
||||
def populate_tool_payload( payload=None, tool=None ):
|
||||
payload = populate_tag_payload( payload=payload, tool=tool )
|
||||
payload[ 'title' ] = 'Need help with "%s" tool' % ( tool.name )
|
||||
payload[ 'content' ] = '<br /><hr /><p>Tool name: %s</br>Tool version: %s</br>Tool ID: %s</p>' % ( tool.name, tool.version, tool.id )
|
||||
tool_url = None
|
||||
if tool.tool_shed_repository:
|
||||
tool_url = tool.tool_shed_repository.get_sharable_url( tool.app )
|
||||
if tool_url:
|
||||
tool_url = '</br>ToolShed URL: <a href="%s">%s</a>' % ( tool_url, tool_url )
|
||||
if not tool_url:
|
||||
tool_url = ''
|
||||
payload[ 'content' ] = '<br /><hr /><p>Tool name: %s</br>Tool version: %s</br>Tool ID: %s%s</p></br>' % ( tool.name, tool.version, tool.id, tool_url )
|
||||
return payload
|
||||
|
||||
def determine_cookie_domain( galaxy_hostname, biostar_hostname ):
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
"""
|
||||
API operations on the contents of a folder.
|
||||
API operations on the contents of a library folder.
|
||||
"""
|
||||
import logging
|
||||
from galaxy import web
|
||||
from galaxy import exceptions
|
||||
from galaxy.web import _future_expose_api as expose_api
|
||||
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
|
||||
from sqlalchemy.orm.exc import MultipleResultsFound
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
from galaxy.web.base.controller import BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems
|
||||
|
||||
import logging
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems ):
|
||||
@@ -12,7 +17,111 @@ class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrary
|
||||
Class controls retrieval, creation and updating of folder contents.
|
||||
"""
|
||||
|
||||
def load_folder_contents( self, trans, folder ):
|
||||
@expose_api_anonymous
|
||||
def index( self, trans, folder_id, **kwd ):
|
||||
"""
|
||||
GET /api/folders/{encoded_folder_id}/contents
|
||||
Displays a collection (list) of a folder's contents (files and folders).
|
||||
Encoded folder ID is prepended with 'F' if it is a folder as opposed to a data set which does not have it.
|
||||
Full path is provided in response as a separate object providing data for breadcrumb path building.
|
||||
"""
|
||||
|
||||
if ( len( folder_id ) == 17 and folder_id.startswith( 'F' ) ):
|
||||
try:
|
||||
decoded_folder_id = trans.security.decode_id( folder_id[ 1: ] )
|
||||
except TypeError:
|
||||
raise exceptions.MalformedId( 'Malformed folder id ( %s ) specified, unable to decode.' % str( folder_id ) )
|
||||
else:
|
||||
raise exceptions.MalformedId( 'Malformed folder id ( %s ) specified, unable to decode.' % str( folder_id ) )
|
||||
|
||||
try:
|
||||
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).filter( trans.app.model.LibraryFolder.table.c.id == decoded_folder_id ).one()
|
||||
except MultipleResultsFound:
|
||||
raise exceptions.InconsistentDatabase( 'Multiple folders with same id found.' )
|
||||
except NoResultFound:
|
||||
raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
|
||||
except Exception:
|
||||
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 == 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_public( library, contents=False ):
|
||||
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.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 ) )
|
||||
|
||||
def build_path( folder ):
|
||||
"""
|
||||
Search the path upwards recursively and load the whole route of names and ids for breadcrumb building purposes.
|
||||
"""
|
||||
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]
|
||||
|
||||
folder_contents = []
|
||||
time_updated = ''
|
||||
time_created = ''
|
||||
# Go through every accessible item in the folder and include its meta-data.
|
||||
for content_item in self._load_folder_contents( trans, folder ):
|
||||
if trans.app.security_agent.can_access_library_item( current_user_roles, content_item, trans.user ):
|
||||
return_item = {}
|
||||
encoded_id = trans.security.encode_id( content_item.id )
|
||||
time_updated = content_item.update_time.strftime( "%Y-%m-%d %I:%M %p" )
|
||||
time_created = content_item.create_time.strftime( "%Y-%m-%d %I:%M %p" )
|
||||
|
||||
# For folder return also hierarchy values
|
||||
if content_item.api_type == 'folder':
|
||||
encoded_id = 'F' + encoded_id
|
||||
return_item.update ( dict ( item_count = content_item.item_count ) )
|
||||
|
||||
if content_item.api_type == 'file':
|
||||
library_dataset_dict = content_item.to_dict()
|
||||
library_dataset_dict['data_type']
|
||||
library_dataset_dict['file_size']
|
||||
library_dataset_dict['date_uploaded']
|
||||
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'] ) )
|
||||
|
||||
# For every item return also the default meta-data
|
||||
return_item.update( dict( id = encoded_id,
|
||||
type = content_item.api_type,
|
||||
name = content_item.name,
|
||||
time_updated = time_updated,
|
||||
time_created = time_created
|
||||
) )
|
||||
folder_contents.append( return_item )
|
||||
|
||||
return { 'metadata' : { 'full_path' : full_path, 'can_add_library_item': can_add_library_item }, 'folder_contents' : folder_contents }
|
||||
|
||||
def _load_folder_contents( self, trans, folder ):
|
||||
"""
|
||||
Loads all contents of the folder (folders and data sets) but only in the first level.
|
||||
"""
|
||||
@@ -33,101 +142,12 @@ class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrary
|
||||
content_items.append( dataset )
|
||||
return content_items
|
||||
|
||||
@web.expose_api
|
||||
def index( self, trans, folder_id, **kwd ):
|
||||
"""
|
||||
GET /api/folders/{encoded_folder_id}/contents
|
||||
Displays a collection (list) of a folder's contents (files and folders).
|
||||
Encoded folder ID is prepended with 'F' if it is a folder as opposed to a data set which does not have it.
|
||||
Full path is provided as a separate object in response providing data for breadcrumb path building.
|
||||
"""
|
||||
folder_container = []
|
||||
current_user_roles = trans.get_current_user_roles()
|
||||
|
||||
if ( folder_id.startswith( 'F' ) ):
|
||||
try:
|
||||
decoded_folder_id = trans.security.decode_id( folder_id[1:] )
|
||||
except TypeError:
|
||||
trans.response.status = 400
|
||||
return "Malformed folder id ( %s ) specified, unable to decode." % str( folder_id )
|
||||
|
||||
try:
|
||||
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( decoded_folder_id )
|
||||
except:
|
||||
folder = None
|
||||
log.error( "FolderContentsController.index: Unable to retrieve folder with ID: %s" % folder_id )
|
||||
|
||||
# We didn't find the folder or user does not have an access to it.
|
||||
if not folder:
|
||||
trans.response.status = 400
|
||||
return "Invalid folder id ( %s ) specified." % str( folder_id )
|
||||
|
||||
if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ):
|
||||
log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, folder.id ) )
|
||||
trans.response.status = 400
|
||||
return "Invalid folder id ( %s ) specified." % str( folder_id )
|
||||
|
||||
def build_path( folder ):
|
||||
"""
|
||||
Search the path upwards recursively and load the whole route of names and ids for breadcrumb purposes.
|
||||
"""
|
||||
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]
|
||||
folder_container.append( dict( full_path = full_path ) )
|
||||
|
||||
folder_contents = []
|
||||
time_updated = ''
|
||||
time_created = ''
|
||||
# Go through every item in the folder and include its meta-data.
|
||||
for content_item in self.load_folder_contents( trans, folder ):
|
||||
return_item = {}
|
||||
encoded_id = trans.security.encode_id( content_item.id )
|
||||
time_updated = content_item.update_time.strftime( "%Y-%m-%d %I:%M %p" )
|
||||
time_created = content_item.create_time.strftime( "%Y-%m-%d %I:%M %p" )
|
||||
|
||||
# For folder return also hierarchy values
|
||||
if content_item.api_type == 'folder':
|
||||
encoded_id = 'F' + encoded_id
|
||||
return_item.update ( dict ( item_count = content_item.item_count ) )
|
||||
|
||||
if content_item.api_type == 'file':
|
||||
library_dataset_dict = content_item.to_dict()
|
||||
library_dataset_dict['data_type']
|
||||
library_dataset_dict['file_size']
|
||||
library_dataset_dict['date_uploaded']
|
||||
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'] ) )
|
||||
|
||||
# For every item return also the default meta-data
|
||||
return_item.update( dict( id = encoded_id,
|
||||
type = content_item.api_type,
|
||||
name = content_item.name,
|
||||
time_updated = time_updated,
|
||||
time_created = time_created
|
||||
) )
|
||||
folder_contents.append( return_item )
|
||||
# Put the data in the container
|
||||
folder_container.append( dict( folder_contents = folder_contents ) )
|
||||
return folder_container
|
||||
|
||||
@web.expose_api
|
||||
def show( self, trans, id, library_id, **kwd ):
|
||||
"""
|
||||
GET /api/folders/{encoded_folder_id}/
|
||||
"""
|
||||
pass
|
||||
raise exceptions.NotImplemented( 'Showing the library folder content is not implemented.' )
|
||||
|
||||
@web.expose_api
|
||||
def create( self, trans, library_id, payload, **kwd ):
|
||||
@@ -136,11 +156,11 @@ class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrary
|
||||
Creates a new folder. This should be superseded by the
|
||||
LibraryController.
|
||||
"""
|
||||
pass
|
||||
raise exceptions.NotImplemented( 'Creating the library folder content is not implemented.' )
|
||||
|
||||
@web.expose_api
|
||||
def update( self, trans, id, library_id, payload, **kwd ):
|
||||
"""
|
||||
PUT /api/folders/{encoded_folder_id}/contents
|
||||
"""
|
||||
pass
|
||||
raise exceptions.NotImplemented( 'Updating the library folder content is not implemented.' )
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
"""
|
||||
API operations on folders
|
||||
API operations on library folders
|
||||
"""
|
||||
import logging, os, string, shutil, urllib, re, socket, traceback
|
||||
import os, string, shutil, urllib, re, socket, traceback
|
||||
from galaxy import datatypes, jobs, web, security
|
||||
from galaxy.web import _future_expose_api as expose_api
|
||||
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
|
||||
from galaxy.web.base.controller import BaseAPIController,UsesLibraryMixin,UsesLibraryMixinItems
|
||||
from galaxy.util.sanitize_html import sanitize_html
|
||||
|
||||
from cgi import escape, FieldStorage
|
||||
from paste.httpexceptions import HTTPBadRequest
|
||||
|
||||
import logging
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
class FoldersController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems ):
|
||||
@@ -18,9 +21,9 @@ class FoldersController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinIt
|
||||
"""
|
||||
GET /api/folders/
|
||||
This would normally display a list of folders. However, that would
|
||||
be across multiple libraries, so it's not implemented yet.
|
||||
be across multiple libraries, so it's not implemented.
|
||||
"""
|
||||
pass
|
||||
raise exceptions.NotImplemented( 'Listing all accessible library folders is not implemented.' )
|
||||
|
||||
@web.expose_api
|
||||
def show( self, trans, id, **kwd ):
|
||||
|
||||
@@ -188,8 +188,7 @@ class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociatio
|
||||
hda_dict[ 'display_apps' ] = self.get_display_apps( trans, hda )
|
||||
return hda_dict
|
||||
|
||||
#TODO: allow anon users to copy hdas, ldas
|
||||
@expose_api
|
||||
@expose_api_anonymous
|
||||
def create( self, trans, history_id, payload, **kwd ):
|
||||
"""
|
||||
create( self, trans, history_id, payload, **kwd )
|
||||
@@ -434,10 +433,7 @@ class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociatio
|
||||
return validated_payload
|
||||
|
||||
def __handle_unknown_contents_type( self, trans, contents_type ):
|
||||
# TODO: raise a message exception instead of setting status and returning dict.
|
||||
trans.response.status = 400
|
||||
return { 'error': 'Unknown contents type %s' % type }
|
||||
|
||||
raise exceptions.UnknownContentsType('Unknown contents type: %s' % type)
|
||||
|
||||
class HDAManager( object ):
|
||||
|
||||
|
||||
@@ -12,9 +12,13 @@ import tempfile
|
||||
import urllib
|
||||
import urllib2
|
||||
import zipfile
|
||||
from paste.httpexceptions import HTTPBadRequest
|
||||
from galaxy import util, web
|
||||
from galaxy.exceptions import ItemAccessibilityException, MessageException, ItemDeletionException, ObjectNotFound
|
||||
from galaxy import exceptions
|
||||
from galaxy.web import _future_expose_api as expose_api
|
||||
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
|
||||
# from paste.httpexceptions import HTTPBadRequest
|
||||
from galaxy import util
|
||||
from galaxy import web
|
||||
# from galaxy.exceptions import ItemAccessibilityException, MessageException, ItemDeletionException, ObjectNotFound
|
||||
from galaxy.security import Action
|
||||
from galaxy.util.streamball import StreamBall
|
||||
from galaxy.web.base.controller import BaseAPIController, UsesVisualizationMixin
|
||||
@@ -24,7 +28,7 @@ log = logging.getLogger( __name__ )
|
||||
|
||||
class LibraryDatasetsController( BaseAPIController, UsesVisualizationMixin ):
|
||||
|
||||
@web.expose_api
|
||||
@expose_api_anonymous
|
||||
def show( self, trans, id, **kwd ):
|
||||
"""
|
||||
show( self, trans, id, **kwd )
|
||||
@@ -41,19 +45,20 @@ class LibraryDatasetsController( BaseAPIController, UsesVisualizationMixin ):
|
||||
try:
|
||||
dataset = self.get_library_dataset( trans, id = id, check_ownership=False, check_accessible=True )
|
||||
except Exception, e:
|
||||
trans.response.status = 500
|
||||
return str( e )
|
||||
try:
|
||||
rval = dataset.to_dict()
|
||||
except Exception, e:
|
||||
rval = "Error in dataset API at listing contents: " + str( e )
|
||||
log.error( rval + ": %s" % str(e), exc_info=True )
|
||||
trans.response.status = 500
|
||||
return "Error in dataset API at listing contents: " + str( e )
|
||||
raise exceptions.ObjectNotFound( 'Requested dataset was not found.' )
|
||||
# trans.response.status = 500
|
||||
# return str( e )
|
||||
# try:
|
||||
rval = dataset.to_dict()
|
||||
# except Exception, e:
|
||||
# rval = "Error in dataset API at listing contents: " + str( e )
|
||||
# log.error( rval + ": %s" % str(e), exc_info=True )
|
||||
# trans.response.status = 500
|
||||
# return "Error in dataset API at listing contents: " + str( e )
|
||||
|
||||
rval['id'] = trans.security.encode_id(rval['id']);
|
||||
rval['ldda_id'] = trans.security.encode_id(rval['ldda_id']);
|
||||
rval['folder_id'] = 'f' + trans.security.encode_id(rval['folder_id'])
|
||||
rval['folder_id'] = 'F' + trans.security.encode_id(rval['folder_id'])
|
||||
return rval
|
||||
|
||||
@web.expose
|
||||
|
||||
@@ -7,7 +7,7 @@ from galaxy import exceptions
|
||||
from galaxy.web import _future_expose_api as expose_api
|
||||
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
|
||||
from galaxy.model.orm import and_, not_, or_
|
||||
from galaxy.web.base.controller import BaseAPIController, url_for
|
||||
from galaxy.web.base.controller import BaseAPIController
|
||||
|
||||
import logging
|
||||
log = logging.getLogger( __name__ )
|
||||
@@ -61,7 +61,6 @@ class LibrariesController( BaseAPIController ):
|
||||
if trans.app.security_agent.library_is_public( library, contents=False ):
|
||||
item[ 'public' ] = True
|
||||
current_user_roles = trans.get_current_user_roles()
|
||||
# can_user_add = trans.app.security_agent.can_add_library_item( current_user_roles, library.root_folder )
|
||||
if not trans.user_is_admin():
|
||||
item['can_user_add'] = trans.app.security_agent.can_add_library_item( current_user_roles, library )
|
||||
item['can_user_modify'] = trans.app.security_agent.can_modify_library_item( current_user_roles, library )
|
||||
@@ -98,7 +97,7 @@ class LibrariesController( BaseAPIController ):
|
||||
deleted = util.string_as_bool( deleted )
|
||||
try:
|
||||
decoded_library_id = trans.security.decode_id( library_id )
|
||||
except Exception:
|
||||
except TypeError:
|
||||
raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
|
||||
try:
|
||||
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
|
||||
@@ -144,7 +143,14 @@ class LibrariesController( BaseAPIController ):
|
||||
library.root_folder = root_folder
|
||||
trans.sa_session.add_all( ( library, root_folder ) )
|
||||
trans.sa_session.flush()
|
||||
return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
|
||||
|
||||
item = library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
|
||||
item['can_user_add'] = True
|
||||
item['can_user_modify'] = True
|
||||
item['can_user_manage'] = True
|
||||
if trans.app.security_agent.library_is_public( library, contents=False ):
|
||||
item[ 'public' ] = True
|
||||
return item
|
||||
|
||||
@expose_api
|
||||
def update( self, trans, id, **kwd ):
|
||||
|
||||
@@ -17,8 +17,7 @@ import logging
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
|
||||
class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems,
|
||||
UsesHistoryDatasetAssociationMixin ):
|
||||
class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems, UsesHistoryDatasetAssociationMixin ):
|
||||
|
||||
@expose_api
|
||||
def index( self, trans, library_id, **kwd ):
|
||||
|
||||
@@ -284,7 +284,7 @@ def app_factory( global_conf, **kwargs ):
|
||||
# ====================
|
||||
|
||||
# Handle displaying tool help images and README file images contained in repositories installed from the tool shed.
|
||||
webapp.add_route( '/admin_toolshed/static/images/:repository_id/:image_file',
|
||||
webapp.add_route( '/admin_toolshed/static/images/:repository_id/{image_file:.+?}',
|
||||
controller='admin_toolshed',
|
||||
action='display_image_in_repository',
|
||||
repository_id=None,
|
||||
|
||||
@@ -16,6 +16,7 @@ from tool_shed.util import common_install_util
|
||||
from tool_shed.util import data_manager_util
|
||||
from tool_shed.util import datatype_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import metadata_util
|
||||
from tool_shed.util import readme_util
|
||||
from tool_shed.util import repository_dependency_util
|
||||
@@ -1851,7 +1852,7 @@ class AdminToolshed( AdminGalaxy ):
|
||||
repo_files_dir = os.path.abspath( os.path.join( tool_path, relative_install_dir, name ) )
|
||||
else:
|
||||
repo_files_dir = os.path.abspath( os.path.join( relative_install_dir, name ) )
|
||||
repo = hg.repository( suc.get_configured_ui(), path=repo_files_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), path=repo_files_dir )
|
||||
repository_clone_url = os.path.join( tool_shed_url, 'repos', owner, name )
|
||||
repository_util.pull_repository( repo, repository_clone_url, latest_ctx_rev )
|
||||
suc.update_repository( repo, latest_ctx_rev )
|
||||
|
||||
@@ -13,6 +13,7 @@ import tool_shed.repository_types.util as rt_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.galaxy_install import repository_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import import_util
|
||||
from tool_shed.util import metadata_util
|
||||
from tool_shed.util import repository_maintenance_util
|
||||
@@ -49,7 +50,7 @@ class RepositoriesController( BaseAPIController ):
|
||||
log.debug( error_message )
|
||||
return []
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
ordered_installable_revisions = suc.get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True )
|
||||
return ordered_installable_revisions
|
||||
else:
|
||||
@@ -133,7 +134,7 @@ class RepositoriesController( BaseAPIController ):
|
||||
# The changeset_revision column in the repository_metadata table has been updated with a new
|
||||
# value value, so find the changeset_revision to which we need to update.
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
new_changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
|
||||
encoded_repository_id,
|
||||
|
||||
@@ -6,6 +6,7 @@ from galaxy import util
|
||||
from galaxy.model.orm import and_, not_, select
|
||||
from galaxy.web.base.controller import BaseAPIController, HTTPBadRequest
|
||||
from tool_shed.util import export_util
|
||||
from tool_shed.util import hg_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
|
||||
from galaxy import eggs
|
||||
@@ -168,7 +169,7 @@ class RepositoryRevisionsController( BaseAPIController ):
|
||||
# The changeset_revision column in the repository_metadata table has been updated with a new
|
||||
# value value, so find the changeset_revision to which we need to update.
|
||||
repo_dir = repository_dependency.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
new_changeset_revision = suc.get_next_downloadable_changeset_revision( repository_dependency,
|
||||
repo,
|
||||
changeset_revision )
|
||||
|
||||
@@ -19,6 +19,7 @@ from tool_shed.util import common_util
|
||||
from tool_shed.util import container_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import export_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import import_util
|
||||
from tool_shed.util import metadata_util
|
||||
from tool_shed.util import readme_util
|
||||
@@ -719,7 +720,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
status = kwd.get( 'status', 'done' )
|
||||
commit_message = kwd.get( 'commit_message', 'Deleted selected files' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
# Update repository files for browsing.
|
||||
suc.update_repository( repo )
|
||||
changeset_revision = repository.tip( trans.app )
|
||||
@@ -891,9 +892,9 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_revision = kwd.get( 'changeset_revision', None )
|
||||
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
# Default to the current changeset revision.
|
||||
update_to_ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
update_to_ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
latest_changeset_revision = changeset_revision
|
||||
from_update_manager = kwd.get( 'from_update_manager', False )
|
||||
if from_update_manager:
|
||||
@@ -937,10 +938,10 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
update_to_changeset_hash = None
|
||||
for changeset in repo.changelog:
|
||||
changeset_hash = str( repo.changectx( changeset ) )
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_hash )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_hash )
|
||||
if update_to_changeset_hash:
|
||||
if changeset_hash == repository.tip( trans.app ):
|
||||
update_to_ctx = suc.get_changectx_for_changeset( repo, changeset_hash )
|
||||
update_to_ctx = hg_util.get_changectx_for_changeset( repo, changeset_hash )
|
||||
latest_changeset_revision = changeset_hash
|
||||
break
|
||||
else:
|
||||
@@ -949,7 +950,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_hash )
|
||||
if repository_metadata:
|
||||
# We found a RepositoryMetadata record.
|
||||
update_to_ctx = suc.get_changectx_for_changeset( repo, changeset_hash )
|
||||
update_to_ctx = hg_util.get_changectx_for_changeset( repo, changeset_hash )
|
||||
latest_changeset_revision = changeset_hash
|
||||
break
|
||||
else:
|
||||
@@ -1213,7 +1214,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
else:
|
||||
containers_dict = None
|
||||
export_repository_dependencies_check_box = None
|
||||
revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
return trans.fill_template( "/webapps/tool_shed/repository/export_repository.mako",
|
||||
changeset_revision=changeset_revision,
|
||||
containers_dict=containers_dict,
|
||||
@@ -1466,9 +1467,9 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
has_repository_dependencies_only_if_compiling_contained_td = has_galaxy_utilities_dict[ 'has_repository_dependencies_only_if_compiling_contained_td' ]
|
||||
includes_workflows = has_galaxy_utilities_dict[ 'includes_workflows' ]
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
# Default to the received changeset revision and ctx_rev.
|
||||
update_to_ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
update_to_ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
ctx_rev = str( update_to_ctx.rev() )
|
||||
latest_changeset_revision = changeset_revision
|
||||
update_dict = dict( changeset_revision=changeset_revision,
|
||||
@@ -1497,7 +1498,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
has_repository_dependencies = False
|
||||
has_repository_dependencies_only_if_compiling_contained_td = False
|
||||
changeset_hash = str( repo.changectx( changeset ) )
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_hash )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_hash )
|
||||
if update_to_changeset_hash:
|
||||
update_to_repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
|
||||
trans.security.encode_id( repository.id ),
|
||||
@@ -1515,10 +1516,10 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
# We found a RepositoryMetadata record.
|
||||
if changeset_hash == repository.tip( trans.app ):
|
||||
# The current ctx is the repository tip, so use it.
|
||||
update_to_ctx = suc.get_changectx_for_changeset( repo, changeset_hash )
|
||||
update_to_ctx = hg_util.get_changectx_for_changeset( repo, changeset_hash )
|
||||
latest_changeset_revision = changeset_hash
|
||||
else:
|
||||
update_to_ctx = suc.get_changectx_for_changeset( repo, update_to_changeset_hash )
|
||||
update_to_ctx = hg_util.get_changectx_for_changeset( repo, update_to_changeset_hash )
|
||||
latest_changeset_revision = update_to_changeset_hash
|
||||
break
|
||||
elif not update_to_changeset_hash and changeset_hash == changeset_revision:
|
||||
@@ -1544,8 +1545,8 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_revision = kwd[ 'changeset_revision' ]
|
||||
repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
return str( ctx.rev() )
|
||||
return ''
|
||||
@@ -1560,8 +1561,8 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
def get_file_from_changeset_revision( self, repo_files_dir, changeset_revision, file_name, dir ):
|
||||
"""Return file_name from the received changeset_revision of the repository manifest."""
|
||||
stripped_file_name = suc.strip_path( file_name )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_files_dir )
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_files_dir )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
named_tmp_file = suc.get_named_tmpfile_from_ctx( ctx, file_name, dir )
|
||||
return named_tmp_file
|
||||
|
||||
@@ -1604,7 +1605,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
trans.model.Repository.table.c.user_id == user.id ) ):
|
||||
repository = repository_metadata.repository
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
latest_downloadable_changeset_revsion = suc.get_latest_downloadable_changeset_revision( trans, repository, repo )
|
||||
if repository_metadata.changeset_revision == latest_downloadable_changeset_revsion:
|
||||
# We'll display only the test run for the latest installable revision in the rss feed.
|
||||
@@ -1672,7 +1673,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
if repository_name is not None and repository_owner is not None:
|
||||
repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
|
||||
if repository:
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
return suc.get_latest_downloadable_changeset_revision( trans, repository, repo )
|
||||
return suc.INITIAL_CHANGELOG_HASH
|
||||
|
||||
@@ -1855,7 +1856,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_revision = kwd[ 'changeset_revision' ]
|
||||
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
tool_version_dicts = []
|
||||
for changeset in repo.changelog:
|
||||
current_changeset_revision = str( repo.changectx( changeset ) )
|
||||
@@ -1880,7 +1881,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
repository_id = trans.security.encode_id( repository.id )
|
||||
repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( trans, repository )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
|
||||
if not repository_metadata:
|
||||
# The received changeset_revision is no longer associated with metadata, so get the next changeset_revision in the repository
|
||||
@@ -1889,7 +1890,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
repo,
|
||||
after_changeset_revision=changeset_revision )
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
repo_info_dict = repository_util.create_repo_info_dict( trans=trans,
|
||||
repository_clone_url=repository_clone_url,
|
||||
changeset_revision=changeset_revision,
|
||||
@@ -2165,7 +2166,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
repository_type = kwd.get( 'repository_type', str( repository.type ) )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
repo_name = kwd.get( 'repo_name', repository.name )
|
||||
changeset_revision = kwd.get( 'changeset_revision', repository.tip( trans.app ) )
|
||||
description = kwd.get( 'description', repository.description )
|
||||
@@ -2317,7 +2318,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
selected_value=changeset_revision,
|
||||
add_id_to_name=False,
|
||||
downloadable=False )
|
||||
revision_label = suc.get_revision_label( trans, repository, repository.tip( trans.app ), include_date=False )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, repository.tip( trans.app ), include_date=False )
|
||||
repository_metadata = None
|
||||
metadata = None
|
||||
is_malicious = False
|
||||
@@ -2326,7 +2327,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
if changeset_revision != suc.INITIAL_CHANGELOG_HASH:
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
|
||||
if repository_metadata:
|
||||
revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=False )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=False )
|
||||
metadata = repository_metadata.metadata
|
||||
is_malicious = repository_metadata.malicious
|
||||
else:
|
||||
@@ -2337,7 +2338,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
if previous_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, previous_changeset_revision )
|
||||
if repository_metadata:
|
||||
revision_label = suc.get_revision_label( trans, repository, previous_changeset_revision, include_date=False )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, previous_changeset_revision, include_date=False )
|
||||
metadata = repository_metadata.metadata
|
||||
is_malicious = repository_metadata.malicious
|
||||
changeset_revision = previous_changeset_revision
|
||||
@@ -2443,7 +2444,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
# There is no repository_metadata defined for the changeset_revision, so see if it was defined
|
||||
# in a previous changeset in the changelog.
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
previous_changeset_revision = \
|
||||
suc.get_previous_metadata_changeset_revision( repository,
|
||||
repo,
|
||||
@@ -2520,7 +2521,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_revision = kwd.get( 'changeset_revision', None )
|
||||
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
# Get the next installable changeset_revision beyond the received changeset_revision.
|
||||
changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
|
||||
if changeset_revision:
|
||||
@@ -2540,7 +2541,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
status = kwd.get( 'status', 'done' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, repository_id )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
changeset_revision = kwd.get( 'changeset_revision', repository.tip( trans.app ) )
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
|
||||
if repository_metadata:
|
||||
@@ -2577,7 +2578,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
repository_metadata_id = None
|
||||
metadata = None
|
||||
repository_dependencies = None
|
||||
revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
changeset_revision_select_field = grids_util.build_changeset_revision_select_field( trans,
|
||||
repository,
|
||||
selected_value=changeset_revision,
|
||||
@@ -2607,7 +2608,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_revision = kwd.get( 'changeset_revision', None )
|
||||
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
# Get the lower bound changeset revision.
|
||||
lower_bound_changeset_revision = suc.get_previous_metadata_changeset_revision( repository, repo, changeset_revision, downloadable=True )
|
||||
# Build the list of changeset revision hashes.
|
||||
@@ -2633,7 +2634,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
status='error' ) )
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
changeset_revision = repository.tip( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
if repository.user == trans.user:
|
||||
return trans.response.send_redirect( web.url_for( controller='repository',
|
||||
action='browse_repositories',
|
||||
@@ -2651,7 +2652,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_revision,
|
||||
metadata_only=True )
|
||||
repository_type_select_field = rt_util.build_repository_type_select_field( trans, repository=repository )
|
||||
revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
return trans.fill_template( '/webapps/tool_shed/repository/rate_repository.mako',
|
||||
repository=repository,
|
||||
metadata=metadata,
|
||||
@@ -2702,7 +2703,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
commit_message = kwd.get( 'commit_message', 'Deleted selected files' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
selected_files_to_delete = kwd.get( 'selected_files_to_delete', '' )
|
||||
if kwd.get( 'select_files_to_delete_button', False ):
|
||||
if selected_files_to_delete:
|
||||
@@ -2742,7 +2743,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
# Update the repository files for browsing.
|
||||
suc.update_repository( repo )
|
||||
# Get the new repository tip.
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
if tip == repository.tip( trans.app ):
|
||||
message += 'No changes to repository. '
|
||||
kwd[ 'message' ] = message
|
||||
@@ -2931,7 +2932,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
if not repository_metadata:
|
||||
# Get updates to the received changeset_revision if any exist.
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
upper_bound_changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
|
||||
if upper_bound_changeset_revision:
|
||||
changeset_revision = upper_bound_changeset_revision
|
||||
@@ -2971,7 +2972,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
trans.security.encode_id( repository.id ),
|
||||
changeset_revision )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
tool_shed_status_dict = {}
|
||||
# Handle repository deprecation.
|
||||
tool_shed_status_dict[ 'repository_deprecated' ] = str( repository.deprecated )
|
||||
@@ -3063,7 +3064,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
message = kwd.get( 'message', '' )
|
||||
status = kwd.get( 'status', 'done' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
changesets = []
|
||||
for changeset in repo.changelog:
|
||||
ctx = repo.changectx( changeset )
|
||||
@@ -3074,7 +3075,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
change_dict = { 'ctx' : ctx,
|
||||
'rev' : str( ctx.rev() ),
|
||||
'date' : date,
|
||||
'display_date' : suc.get_readable_ctx_date( ctx ),
|
||||
'display_date' : hg_util.get_readable_ctx_date( ctx ),
|
||||
'description' : ctx.description(),
|
||||
'files' : ctx.files(),
|
||||
'user' : ctx.user(),
|
||||
@@ -3098,8 +3099,8 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
message = kwd.get( 'message', '' )
|
||||
status = kwd.get( 'status', 'done' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
ctx = suc.get_changectx_for_changeset( repo, ctx_str )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, ctx_str )
|
||||
if ctx is None:
|
||||
message = "Repository does not include changeset revision '%s'." % str( ctx_str )
|
||||
status = 'error'
|
||||
@@ -3129,7 +3130,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans, id, ctx_str, metadata_only=True )
|
||||
# For rendering the prev button.
|
||||
if ctx_parent:
|
||||
ctx_parent_date = suc.get_readable_ctx_date( ctx_parent )
|
||||
ctx_parent_date = hg_util.get_readable_ctx_date( ctx_parent )
|
||||
ctx_parent_rev = ctx_parent.rev()
|
||||
if ctx_parent_rev < 0:
|
||||
prev = None
|
||||
@@ -3138,7 +3139,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
else:
|
||||
prev = None
|
||||
if ctx_child:
|
||||
ctx_child_date = suc.get_readable_ctx_date( ctx_child )
|
||||
ctx_child_date = hg_util.get_readable_ctx_date( ctx_child )
|
||||
ctx_child_rev = ctx_child.rev()
|
||||
next = "<b>%s:%s</b> <i>(%s)</i>" % ( ctx_child_rev, ctx_child, ctx_child_date )
|
||||
else:
|
||||
@@ -3187,7 +3188,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
message = kwd.get( 'message', '' )
|
||||
status = kwd.get( 'status', 'done' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, repository, webapp_model=trans.model )
|
||||
changeset_revision = kwd.get( 'changeset_revision', repository.tip( trans.app ) )
|
||||
display_reviews = kwd.get( 'display_reviews', False )
|
||||
@@ -3221,7 +3222,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
selected_value=changeset_revision,
|
||||
add_id_to_name=False,
|
||||
downloadable=False )
|
||||
revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=False )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=False )
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
|
||||
if repository_metadata:
|
||||
metadata = repository_metadata.metadata
|
||||
@@ -3277,13 +3278,13 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ):
|
||||
render_repository_actions_for = kwd.get( 'render_repository_actions_for', 'tool_shed' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, repository_id )
|
||||
repo_files_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_files_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_files_dir )
|
||||
tool_metadata_dict = {}
|
||||
tool_lineage = []
|
||||
tool = None
|
||||
guid = None
|
||||
original_tool_data_path = trans.app.config.tool_data_path
|
||||
revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=False )
|
||||
revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=False )
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
|
||||
if repository_metadata:
|
||||
repository_metadata_id = trans.security.encode_id( repository_metadata.id )
|
||||
|
||||
@@ -7,6 +7,7 @@ from galaxy.model.orm import and_
|
||||
from galaxy.webapps.tool_shed.util import ratings_util
|
||||
from tool_shed.util.container_util import STRSEP
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import review_util
|
||||
from galaxy.util.odict import odict
|
||||
import tool_shed.grids.repository_review_grids as repository_review_grids
|
||||
@@ -72,8 +73,8 @@ class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
|
||||
status = kwd.get( 'status', 'done' )
|
||||
review = review_util.get_review( trans, kwd[ 'id' ] )
|
||||
repository = review.repository
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, review.changeset_revision )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
rev, changeset_revision_label = hg_util.get_rev_label_from_changeset_revision( repo, review.changeset_revision )
|
||||
return trans.fill_template( '/webapps/tool_shed/repository_review/browse_review.mako',
|
||||
repository=repository,
|
||||
changeset_revision_label=changeset_revision_label,
|
||||
@@ -232,7 +233,7 @@ class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
|
||||
for component in review_util.get_components( trans ):
|
||||
components_dict[ component.name ] = dict( component=component, component_review=None )
|
||||
repository = review.repository
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
for component_review in review.component_reviews:
|
||||
if component_review and component_review.component:
|
||||
component_name = component_review.component.name
|
||||
@@ -337,7 +338,7 @@ class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
|
||||
name='revision_approved',
|
||||
selected_value=selected_value,
|
||||
for_component=False )
|
||||
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, review.changeset_revision )
|
||||
rev, changeset_revision_label = hg_util.get_rev_label_from_changeset_revision( repo, review.changeset_revision )
|
||||
return trans.fill_template( '/webapps/tool_shed/repository_review/edit_review.mako',
|
||||
repository=repository,
|
||||
review=review,
|
||||
@@ -470,7 +471,7 @@ class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
|
||||
if repository_id:
|
||||
repository = suc.get_repository_in_tool_shed( trans, repository_id )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
metadata_revision_hashes = [ metadata_revision.changeset_revision for metadata_revision in repository.metadata_revisions ]
|
||||
reviewed_revision_hashes = [ review.changeset_revision for review in repository.reviews ]
|
||||
reviews_dict = odict()
|
||||
@@ -478,7 +479,7 @@ class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
|
||||
ctx = repo.changectx( changeset )
|
||||
changeset_revision = str( ctx )
|
||||
if changeset_revision in metadata_revision_hashes or changeset_revision in reviewed_revision_hashes:
|
||||
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
rev, changeset_revision_label = hg_util.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
if changeset_revision in reviewed_revision_hashes:
|
||||
# Find the review for this changeset_revision
|
||||
repository_reviews = review_util.get_reviews_by_repository_id_changeset_revision( trans, repository_id, changeset_revision )
|
||||
@@ -517,9 +518,9 @@ class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
|
||||
changeset_revision = kwd.get( 'changeset_revision', None )
|
||||
repository = suc.get_repository_in_tool_shed( trans, repository_id )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
installable = changeset_revision in [ metadata_revision.changeset_revision for metadata_revision in repository.metadata_revisions ]
|
||||
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
rev, changeset_revision_label = hg_util.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
reviews = review_util.get_reviews_by_repository_id_changeset_revision( trans, repository_id, changeset_revision )
|
||||
return trans.fill_template( '/webapps/tool_shed/repository_review/reviews_of_changeset_revision.mako',
|
||||
repository=repository,
|
||||
@@ -582,9 +583,9 @@ class RepositoryReviewController( BaseUIController, ratings_util.ItemRatings ):
|
||||
status = kwd.get( 'status', 'done' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, kwd[ 'id' ] )
|
||||
changeset_revision = kwd.get( 'changeset_revision', None )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
previous_reviews_dict = review_util.get_previous_repository_reviews( trans, repository, changeset_revision )
|
||||
rev, changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
rev, changeset_revision_label = hg_util.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
return trans.fill_template( '/webapps/tool_shed/repository_review/select_previous_review.mako',
|
||||
repository=repository,
|
||||
changeset_revision=changeset_revision,
|
||||
|
||||
@@ -11,6 +11,7 @@ from galaxy.datatypes import checkers
|
||||
import tool_shed.repository_types.util as rt_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.util import commit_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import metadata_util
|
||||
from tool_shed.util import repository_dependency_util
|
||||
from tool_shed.util import tool_dependency_util
|
||||
@@ -39,7 +40,7 @@ class UploadController( BaseUIController ):
|
||||
repository_id = kwd.get( 'repository_id', '' )
|
||||
repository = suc.get_repository_in_tool_shed( trans, repository_id )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
uncompress_file = util.string_as_bool( kwd.get( 'uncompress_file', 'true' ) )
|
||||
remove_repo_files_not_in_tar = util.string_as_bool( kwd.get( 'remove_repo_files_not_in_tar', 'true' ) )
|
||||
uploaded_file = None
|
||||
@@ -63,7 +64,7 @@ class UploadController( BaseUIController ):
|
||||
repo_url = 'http%s' % url[ len( 'hg' ): ]
|
||||
repo_url = repo_url.encode( 'ascii', 'replace' )
|
||||
try:
|
||||
commands.clone( suc.get_configured_ui(), repo_url, uploaded_directory )
|
||||
commands.clone( hg_util.get_configured_ui(), repo_url, uploaded_directory )
|
||||
except Exception, e:
|
||||
message = 'Error uploading via mercurial clone: %s' % suc.to_html_string( str( e ) )
|
||||
status = 'error'
|
||||
@@ -323,7 +324,7 @@ class UploadController( BaseUIController ):
|
||||
def upload_directory( self, trans, repository, uploaded_directory, upload_point, remove_repo_files_not_in_tar,
|
||||
commit_message, new_repo_alert ):
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
undesirable_dirs_removed = 0
|
||||
undesirable_files_removed = 0
|
||||
if upload_point is not None:
|
||||
@@ -387,7 +388,7 @@ class UploadController( BaseUIController ):
|
||||
def upload_tar( self, trans, repository, tar, uploaded_file, upload_point, remove_repo_files_not_in_tar, commit_message, new_repo_alert ):
|
||||
# Upload a tar archive of files.
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
undesirable_dirs_removed = 0
|
||||
undesirable_files_removed = 0
|
||||
ok, message = commit_util.check_archive( repository, tar )
|
||||
|
||||
@@ -15,6 +15,7 @@ from tool_shed.util import container_util
|
||||
from tool_shed.util import data_manager_util
|
||||
from tool_shed.util import datatype_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import repository_dependency_util
|
||||
from tool_shed.util import metadata_util
|
||||
from tool_shed.util import tool_dependency_util
|
||||
@@ -186,7 +187,7 @@ def get_repair_dict( trans, repository ):
|
||||
def get_repo_info_dict( trans, repository_id, changeset_revision ):
|
||||
repository = suc.get_repository_in_tool_shed( trans, repository_id )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( trans, repository )
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
|
||||
repository_id,
|
||||
@@ -225,7 +226,7 @@ def get_repo_info_dict( trans, repository_id, changeset_revision ):
|
||||
has_repository_dependencies_only_if_compiling_contained_td = False
|
||||
includes_tool_dependencies = False
|
||||
includes_tools_for_display_in_tool_panel = False
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
repo_info_dict = create_repo_info_dict( trans=trans,
|
||||
repository_clone_url=repository_clone_url,
|
||||
changeset_revision=changeset_revision,
|
||||
@@ -574,7 +575,7 @@ def install_tool_shed_repository( trans, tool_shed_repository, repo_info_dict, t
|
||||
current_changeset_revision = changeset_revision_dict.get( 'changeset_revision', None )
|
||||
current_ctx_rev = changeset_revision_dict.get( 'ctx_rev', None )
|
||||
if current_ctx_rev != ctx_rev:
|
||||
repo = hg.repository( suc.get_configured_ui(), path=os.path.abspath( install_dir ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), path=os.path.abspath( install_dir ) )
|
||||
pull_repository( repo, repository_clone_url, current_changeset_revision )
|
||||
suc.update_repository( repo, ctx_rev=current_ctx_rev )
|
||||
handle_repository_contents( trans,
|
||||
@@ -804,7 +805,7 @@ def populate_containers_dict_for_new_install( trans, tool_shed_url, tool_path, r
|
||||
|
||||
def pull_repository( repo, repository_clone_url, ctx_rev ):
|
||||
"""Pull changes from a remote repository to a local one."""
|
||||
commands.pull( suc.get_configured_ui(), repo, source=repository_clone_url, rev=[ ctx_rev ] )
|
||||
commands.pull( hg_util.get_configured_ui(), repo, source=repository_clone_url, rev=[ ctx_rev ] )
|
||||
|
||||
def repair_tool_shed_repository( trans, repository, repo_info_dict ):
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ from galaxy.web.framework.helpers import time_ago
|
||||
from galaxy.webapps.tool_shed import model
|
||||
from galaxy.model.orm import and_
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.grids.repository_grids import CategoryGrid
|
||||
from tool_shed.grids.repository_grids import RepositoryGrid
|
||||
|
||||
@@ -425,9 +426,11 @@ class RepositoryMetadataGrid( grids.Grid ):
|
||||
|
||||
def get_value( self, trans, grid, repository_metadata ):
|
||||
repository = repository_metadata.repository
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
ctx = suc.get_changectx_for_changeset( repo, repository_metadata.changeset_revision )
|
||||
return suc.get_revision_label( trans, repository, repository_metadata.changeset_revision, include_date=True )
|
||||
return hg_util.get_revision_label( trans,
|
||||
repository,
|
||||
repository_metadata.changeset_revision,
|
||||
include_date=True,
|
||||
include_hash=True )
|
||||
|
||||
|
||||
class ToolsColumn( grids.TextColumn ):
|
||||
|
||||
@@ -6,6 +6,7 @@ from galaxy.model.orm import and_
|
||||
from galaxy.model.orm import or_
|
||||
from galaxy.util import json
|
||||
from galaxy.util import listify
|
||||
from tool_shed.util import hg_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
import tool_shed.grids.util as grids_util
|
||||
import tool_shed.repository_types.util as rt_util
|
||||
@@ -116,7 +117,7 @@ class RepositoryGrid( grids.Grid ):
|
||||
def get_value( self, trans, grid, repository ):
|
||||
"""Display the current repository heads."""
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
heads = suc.get_repository_heads( repo )
|
||||
multiple_heads = len( heads ) > 1
|
||||
if multiple_heads:
|
||||
@@ -124,7 +125,7 @@ class RepositoryGrid( grids.Grid ):
|
||||
else:
|
||||
heads_str = ''
|
||||
for ctx in heads:
|
||||
heads_str += '%s<br/>' % suc.get_revision_label_from_ctx( ctx, include_date=True )
|
||||
heads_str += '%s<br/>' % hg_util.get_revision_label_from_ctx( ctx, include_date=True )
|
||||
heads_str.rstrip( '<br/>' )
|
||||
if multiple_heads:
|
||||
heads_str += '</font>'
|
||||
@@ -1338,7 +1339,7 @@ class RepositoryMetadataGrid( grids.Grid ):
|
||||
def get_value( self, trans, grid, repository_metadata ):
|
||||
repository = repository_metadata.repository
|
||||
changeset_revision = repository_metadata.changeset_revision
|
||||
changeset_revision_label = suc.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
changeset_revision_label = hg_util.get_revision_label( trans, repository, changeset_revision, include_date=True )
|
||||
return changeset_revision_label
|
||||
|
||||
|
||||
@@ -1482,7 +1483,7 @@ class RepositoryDependenciesGrid( RepositoryMetadataGrid ):
|
||||
changeset_revision )
|
||||
if not required_repository_metadata:
|
||||
repo_dir = required_repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
updated_changeset_revision = suc.get_next_downloadable_changeset_revision( required_repository, repo, changeset_revision )
|
||||
required_repository_metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
|
||||
required_repository_id,
|
||||
@@ -2029,7 +2030,7 @@ def get_latest_downloadable_repository_metadata( trans, repository ):
|
||||
tool_dependency_definition.
|
||||
"""
|
||||
encoded_repository_id = trans.security.encode_id( repository.id )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
tip_ctx = str( repo.changectx( repo.changelog.tip() ) )
|
||||
repository_metadata = None
|
||||
try:
|
||||
@@ -2077,7 +2078,7 @@ def get_latest_repository_metadata( trans, repository ):
|
||||
tool_dependency_definition.
|
||||
"""
|
||||
encoded_repository_id = trans.security.encode_id( repository.id )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
tip_ctx = str( repo.changectx( repo.changelog.tip() ) )
|
||||
try:
|
||||
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, tip_ctx )
|
||||
|
||||
@@ -6,6 +6,7 @@ from galaxy.model.orm import and_
|
||||
from galaxy.model.orm import or_
|
||||
from tool_shed.grids.repository_grids import RepositoryGrid
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import metadata_util
|
||||
|
||||
from galaxy import eggs
|
||||
@@ -66,10 +67,10 @@ class RepositoriesWithReviewsGrid( RepositoryGrid ):
|
||||
# Restrict to revisions that have been reviewed.
|
||||
if repository.reviews:
|
||||
rval = ''
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
for review in repository.reviews:
|
||||
changeset_revision = review.changeset_revision
|
||||
rev, label = suc.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
rev, label = hg_util.get_rev_label_from_changeset_revision( repo, changeset_revision )
|
||||
rval += '<a href="manage_repository_reviews_of_revision?id=%s&changeset_revision=%s">%s</a><br/>' % \
|
||||
( trans.security.encode_id( repository.id ), changeset_revision, label )
|
||||
return rval
|
||||
@@ -85,9 +86,11 @@ class RepositoriesWithReviewsGrid( RepositoryGrid ):
|
||||
rval = ''
|
||||
for repository_metadata in repository_metadata_revisions:
|
||||
rev, label, changeset_revision = \
|
||||
metadata_util.get_rev_label_changeset_revision_from_repository_metadata( trans,
|
||||
repository_metadata,
|
||||
repository=repository )
|
||||
hg_util.get_rev_label_changeset_revision_from_repository_metadata( trans,
|
||||
repository_metadata,
|
||||
repository=repository,
|
||||
include_date=True,
|
||||
include_hash=False )
|
||||
rval += '<a href="manage_repository_reviews_of_revision?id=%s&changeset_revision=%s">%s</a><br/>' % \
|
||||
( trans.security.encode_id( repository.id ), changeset_revision, label )
|
||||
return rval
|
||||
@@ -308,7 +311,11 @@ class RepositoryReviewsByUserGrid( grids.Grid ):
|
||||
rval += 'edit_review'
|
||||
else:
|
||||
rval +='browse_review'
|
||||
revision_label = suc.get_revision_label( trans, review.repository, review.changeset_revision, include_date=True )
|
||||
revision_label = hg_util.get_revision_label( trans,
|
||||
review.repository,
|
||||
review.changeset_revision,
|
||||
include_date=True,
|
||||
include_hash=False )
|
||||
rval += '?id=%s">%s</a>' % ( encoded_review_id, revision_label )
|
||||
return rval
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
import os
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
import tool_shed.util.metadata_util as metadata_util
|
||||
from tool_shed.util import hg_util
|
||||
from galaxy.web.form_builder import SelectField
|
||||
from galaxy.util.bunch import Bunch
|
||||
|
||||
@@ -96,9 +96,11 @@ def build_changeset_revision_select_field( trans, repository, selected_value=Non
|
||||
repository_metadata_revisions = repository.metadata_revisions
|
||||
for repository_metadata in repository_metadata_revisions:
|
||||
rev, label, changeset_revision = \
|
||||
metadata_util.get_rev_label_changeset_revision_from_repository_metadata( trans,
|
||||
repository_metadata,
|
||||
repository=repository )
|
||||
hg_util.get_rev_label_changeset_revision_from_repository_metadata( trans,
|
||||
repository_metadata,
|
||||
repository=repository,
|
||||
include_date=True,
|
||||
include_hash=False )
|
||||
changeset_tups.append( ( rev, label, changeset_revision ) )
|
||||
refresh_on_change_values.append( changeset_revision )
|
||||
# Sort options by the revision label. Even though the downloadable_revisions query sorts by update_time,
|
||||
|
||||
@@ -14,6 +14,7 @@ eggs.require( 'mercurial' )
|
||||
|
||||
import ConfigParser
|
||||
import galaxy.webapps.tool_shed.config as tool_shed_config
|
||||
from tool_shed.util import hg_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
import logging
|
||||
import shutil
|
||||
@@ -109,7 +110,7 @@ def check_and_update_repository_metadata( app, info_only=False, verbosity=1 ):
|
||||
if tool_dicts is not None:
|
||||
# Clone the repository up to the changeset revision we're checking.
|
||||
repo_dir = repository.repo_path( app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-cafr" )
|
||||
cloned_ok, error_message = suc.clone_repository( repo_dir, work_dir, changeset_revision )
|
||||
if cloned_ok:
|
||||
@@ -368,7 +369,7 @@ def should_set_do_not_test_flag( app, repository, changeset_revision, testable_r
|
||||
"""
|
||||
if not testable_revision:
|
||||
repo_dir = repository.repo_path( app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
changeset_revisions = suc.get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True )
|
||||
if len( changeset_revisions ) > 1:
|
||||
latest_downloadable_revision = changeset_revisions[ -1 ]
|
||||
|
||||
@@ -12,6 +12,7 @@ from galaxy.util import json
|
||||
from galaxy.util.odict import odict
|
||||
from galaxy.web import url_for
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import tool_util
|
||||
from tool_shed.util import xml_util
|
||||
import tool_shed.repository_types.util as rt_util
|
||||
@@ -156,7 +157,7 @@ def handle_complex_repository_dependency_elem( trans, elem, sub_elem_index, sub_
|
||||
def handle_directory_changes( trans, repository, full_path, filenames_in_archive, remove_repo_files_not_in_tar, new_repo_alert,
|
||||
commit_message, undesirable_dirs_removed, undesirable_files_removed ):
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
content_alert_str = ''
|
||||
files_to_remove = []
|
||||
filenames_in_archive = [ os.path.join( full_path, name ) for name in filenames_in_archive ]
|
||||
@@ -342,7 +343,7 @@ def handle_repository_dependency_elem( trans, elem, unpopulate=False ):
|
||||
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
|
||||
if repository:
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
lastest_installable_changeset_revision = suc.get_latest_downloadable_changeset_revision( trans, repository, repo )
|
||||
if lastest_installable_changeset_revision != suc.INITIAL_CHANGELOG_HASH:
|
||||
elem.attrib[ 'changeset_revision' ] = lastest_installable_changeset_revision
|
||||
|
||||
@@ -14,6 +14,7 @@ from tool_shed.util import commit_util
|
||||
from tool_shed.util import common_install_util
|
||||
from tool_shed.util import common_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import repository_dependency_util
|
||||
from tool_shed.util import xml_util
|
||||
|
||||
@@ -37,7 +38,7 @@ class ExportedRepositoryRegistry( object ):
|
||||
|
||||
def archive_repository_revision( trans, ui, repository, archive_dir, changeset_revision ):
|
||||
'''Create an un-versioned archive of a repository.'''
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
options_dict = suc.get_mercurial_default_options_dict( 'archive' )
|
||||
options_dict[ 'rev' ] = changeset_revision
|
||||
error_message = ''
|
||||
@@ -233,8 +234,8 @@ def get_repo_info_dicts( trans, tool_shed_url, repository_id, changeset_revision
|
||||
key_rd_dicts_to_be_processed=None,
|
||||
all_repository_dependencies=None,
|
||||
handled_key_rd_dicts=None )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
repo_info_dict = {}
|
||||
# Cast unicode to string.
|
||||
repo_info_dict[ str( repository.name ) ] = ( str( repository.description ),
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from time import gmtime
|
||||
from time import strftime
|
||||
|
||||
from galaxy import eggs
|
||||
eggs.require( 'mercurial' )
|
||||
|
||||
from mercurial import cmdutil
|
||||
from mercurial import commands
|
||||
from mercurial import hg
|
||||
from mercurial import ui
|
||||
|
||||
def get_changectx_for_changeset( repo, changeset_revision, **kwd ):
|
||||
"""Retrieve a specified changectx from a repository."""
|
||||
for changeset in repo.changelog:
|
||||
ctx = repo.changectx( changeset )
|
||||
if str( ctx ) == changeset_revision:
|
||||
return ctx
|
||||
return None
|
||||
|
||||
def get_configured_ui():
|
||||
"""Configure any desired ui settings."""
|
||||
_ui = ui.ui()
|
||||
# The following will suppress all messages. This is
|
||||
# the same as adding the following setting to the repo
|
||||
# hgrc file' [ui] section:
|
||||
# quiet = True
|
||||
_ui.setconfig( 'ui', 'quiet', True )
|
||||
return _ui
|
||||
|
||||
def get_readable_ctx_date( ctx ):
|
||||
"""Convert the date of the changeset (the received ctx) to a human-readable date."""
|
||||
t, tz = ctx.date()
|
||||
date = datetime( *gmtime( float( t ) - tz )[ :6 ] )
|
||||
ctx_date = date.strftime( "%Y-%m-%d" )
|
||||
return ctx_date
|
||||
|
||||
def get_revision_label( trans, repository, changeset_revision, include_date=True, include_hash=True ):
|
||||
"""
|
||||
Return a string consisting of the human read-able changeset rev and the changeset revision string
|
||||
which includes the revision date if the receive include_date is True.
|
||||
"""
|
||||
repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
return get_revision_label_from_ctx( ctx, include_date=include_date, include_hash=include_hash )
|
||||
else:
|
||||
if include_hash:
|
||||
return "-1:%s" % changeset_revision
|
||||
else:
|
||||
return "-1"
|
||||
|
||||
def get_rev_label_changeset_revision_from_repository_metadata( trans, repository_metadata, repository=None,
|
||||
include_date=True, include_hash=True ):
|
||||
if repository is None:
|
||||
repository = repository_metadata.repository
|
||||
repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
changeset_revision = repository_metadata.changeset_revision
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
rev = '%04d' % ctx.rev()
|
||||
if include_date:
|
||||
changeset_revision_date = get_readable_ctx_date( ctx )
|
||||
if include_hash:
|
||||
label = "%s:%s (%s)" % ( str( ctx.rev() ), changeset_revision, changeset_revision_date )
|
||||
else:
|
||||
label = "%s (%s)" % ( str( ctx.rev() ), changeset_revision_date )
|
||||
else:
|
||||
if include_hash:
|
||||
label = "%s:%s" % ( str( ctx.rev() ), changeset_revision )
|
||||
else:
|
||||
label = "%s" % str( ctx.rev() )
|
||||
else:
|
||||
rev = '-1'
|
||||
if include_hash:
|
||||
label = "-1:%s" % changeset_revision
|
||||
else:
|
||||
label = "-1"
|
||||
return rev, label, changeset_revision
|
||||
|
||||
def get_revision_label_from_ctx( ctx, include_date=True, include_hash=True ):
|
||||
if include_date:
|
||||
if include_hash:
|
||||
return '%s:%s <i><font color="#666666">(%s)</font></i>' % \
|
||||
( str( ctx.rev() ), str( ctx ), str( get_readable_ctx_date( ctx ) ) )
|
||||
else:
|
||||
return '%s <i><font color="#666666">(%s)</font></i>' % \
|
||||
( str( ctx.rev() ), str( get_readable_ctx_date( ctx ) ) )
|
||||
else:
|
||||
if include_hash:
|
||||
return '%s:%s' % ( str( ctx.rev() ), str( ctx ) )
|
||||
else:
|
||||
return '%s' % str( ctx.rev() )
|
||||
|
||||
def get_rev_label_from_changeset_revision( repo, changeset_revision, include_date=True, include_hash=True ):
|
||||
"""
|
||||
Given a changeset revision hash, return two strings, the changeset rev and the changeset revision hash
|
||||
which includes the revision date if the receive include_date is True.
|
||||
"""
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
rev = '%04d' % ctx.rev()
|
||||
label = get_revision_label_from_ctx( ctx, include_date=include_date )
|
||||
else:
|
||||
rev = '-1'
|
||||
label = "-1:%s" % changeset_revision
|
||||
return rev, label
|
||||
@@ -8,6 +8,7 @@ from galaxy import util
|
||||
from galaxy.datatypes import checkers
|
||||
from tool_shed.util import commit_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import metadata_util
|
||||
from tool_shed.util import xml_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
@@ -212,7 +213,7 @@ def import_repository_archive( trans, repository, repository_archive_dict ):
|
||||
archive_file_path = os.path.join( file_path, archive_file_name )
|
||||
archive = tarfile.open( archive_file_path, 'r:*' )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
undesirable_dirs_removed = 0
|
||||
undesirable_files_removed = 0
|
||||
ok, error_message = commit_util.check_archive( repository, archive )
|
||||
|
||||
@@ -15,6 +15,7 @@ from tool_shed.repository_types.metadata import TipOnly
|
||||
from tool_shed.util import common_util
|
||||
from tool_shed.util import common_install_util
|
||||
from tool_shed.util import container_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import readme_util
|
||||
from tool_shed.util import tool_dependency_util
|
||||
from tool_shed.util import tool_util
|
||||
@@ -347,7 +348,7 @@ def create_or_update_repository_metadata( trans, id, repository, changeset_revis
|
||||
# changeset revision in the received repository's changelog (up to the received changeset revision) to see if it is contained in the
|
||||
# skip_tool_test table. If it is, but is not associated with a repository_metadata record, reset that skip_tool_test record to the
|
||||
# newly created repository_metadata record.
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
for changeset in repo.changelog:
|
||||
changeset_hash = str( repo.changectx( changeset ) )
|
||||
skip_tool_test = suc.get_skip_tool_test_by_changeset_revision( trans, changeset_hash )
|
||||
@@ -1048,7 +1049,7 @@ def generate_workflow_metadata( relative_path, exported_workflow_dict, metadata_
|
||||
def get_latest_repository_metadata( trans, decoded_repository_id, downloadable=False ):
|
||||
"""Get last metadata defined for a specified repository from the database."""
|
||||
repository = trans.sa_session.query( trans.model.Repository ).get( decoded_repository_id )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
if downloadable:
|
||||
changeset_revision = suc.get_latest_downloadable_changeset_revision( trans, repository, repo )
|
||||
else:
|
||||
@@ -1121,21 +1122,6 @@ def get_repository_metadata_revisions_for_review( repository, reviewed=True ):
|
||||
repository_metadata_revisions.append( metadata_revision )
|
||||
return repository_metadata_revisions
|
||||
|
||||
def get_rev_label_changeset_revision_from_repository_metadata( trans, repository_metadata, repository=None ):
|
||||
if repository is None:
|
||||
repository = repository_metadata.repository
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
changeset_revision = repository_metadata.changeset_revision
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
changeset_revision_date = suc.get_readable_ctx_date( ctx )
|
||||
rev = '%04d' % ctx.rev()
|
||||
label = "%s:%s (%s)" % ( str( ctx.rev() ), changeset_revision, changeset_revision_date )
|
||||
else:
|
||||
rev = '-1'
|
||||
label = "-1:%s" % changeset_revision
|
||||
return rev, label, changeset_revision
|
||||
|
||||
def get_sample_files_from_disk( repository_files_dir, tool_path=None, relative_install_dir=None,
|
||||
resetting_all_metadata_on_repository=False ):
|
||||
if resetting_all_metadata_on_repository:
|
||||
@@ -1294,7 +1280,7 @@ def handle_repository_elem( app, repository_elem, only_if_compiling_contained_td
|
||||
log.debug( error_message )
|
||||
is_valid = False
|
||||
return repository_dependency_tup, is_valid, error_message
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( app ) )
|
||||
# The received changeset_revision may be None since defining it in the dependency definition is optional.
|
||||
# If this is the case, the default will be to set it's value to the repository dependency tip revision.
|
||||
# This probably occurs only when handling circular dependency definitions.
|
||||
@@ -1360,7 +1346,7 @@ def is_level_one_certified( trans, repository ):
|
||||
"""
|
||||
if repository.deleted:
|
||||
return ( None, False )
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
# Get the latest installable changeset revision since that is all that is currently configured for testing.
|
||||
latest_installable_changeset_revision = suc.get_latest_downloadable_changeset_revision( trans, repository, repo )
|
||||
if latest_installable_changeset_revision not in [ None, suc.INITIAL_CHANGELOG_HASH ]:
|
||||
@@ -1797,7 +1783,7 @@ def reset_all_metadata_on_repository_in_tool_shed( trans, id ):
|
||||
repository = suc.get_repository_in_tool_shed( trans, id )
|
||||
log.debug( "Resetting all metadata on repository: %s" % repository.name )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( trans, repository )
|
||||
# The list of changeset_revisions refers to repository_metadata records that have been created or updated. When the following loop
|
||||
# completes, we'll delete all repository_metadata records for this repository that do not have a changeset_revision value in this list.
|
||||
@@ -1978,7 +1964,7 @@ def set_repository_metadata( trans, repository, content_alert_str='', **kwd ):
|
||||
encoded_id = trans.security.encode_id( repository.id )
|
||||
repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( trans, repository )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app,
|
||||
repository=repository,
|
||||
changeset_revision=repository.tip( trans.app ),
|
||||
|
||||
@@ -9,6 +9,7 @@ from galaxy.util import rst_to_html
|
||||
from galaxy.util import unicodify
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.util import common_util
|
||||
from tool_shed.util import hg_util
|
||||
|
||||
eggs.require( 'mercurial' )
|
||||
|
||||
@@ -25,7 +26,7 @@ def build_readme_files_dict( trans, repository, changeset_revision, metadata, to
|
||||
if trans.webapp.name == 'galaxy':
|
||||
can_use_disk_files = True
|
||||
else:
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
latest_downloadable_changeset_revision = suc.get_latest_downloadable_changeset_revision( trans, repository, repo )
|
||||
can_use_disk_files = changeset_revision == latest_downloadable_changeset_revision
|
||||
readme_files_dict = {}
|
||||
@@ -74,7 +75,7 @@ def build_readme_files_dict( trans, repository, changeset_revision, metadata, to
|
||||
readme_files_dict[ readme_file_name ] = text_of_reasonable_length
|
||||
else:
|
||||
# We must be in the tool shed and have an old changeset_revision, so we need to retrieve the file contents from the repository manifest.
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
fctx = suc.get_file_context_from_ctx( ctx, readme_file_name )
|
||||
if fctx and fctx not in [ 'DELETED' ]:
|
||||
|
||||
@@ -9,6 +9,7 @@ from tool_shed.util import common_util
|
||||
from tool_shed.util import common_install_util
|
||||
from tool_shed.util import container_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import metadata_util
|
||||
from tool_shed.util import tool_util
|
||||
|
||||
@@ -532,7 +533,7 @@ def get_updated_changeset_revisions_for_repository_dependencies( trans, key_rd_d
|
||||
else:
|
||||
# The repository changeset_revision is no longer installable, so see if there's been an update.
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, rd_changeset_revision )
|
||||
repository_metadata = metadata_util.get_repository_metadata_by_repository_id_changeset_revision( trans,
|
||||
trans.security.encode_id( repository.id ),
|
||||
|
||||
@@ -3,6 +3,7 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import import_util
|
||||
from galaxy import util
|
||||
from galaxy.web.form_builder import build_select_field
|
||||
@@ -47,7 +48,7 @@ def create_hgrc_file( trans, repository ):
|
||||
# Since we support both http and https, we set push_ssl to False to override the default (which is True) in the mercurial api. The hg
|
||||
# purge extension purges all files and directories not being tracked by mercurial in the current repository. It'll remove unknown files
|
||||
# and empty directories. This is not currently used because it is not supported in the mercurial API.
|
||||
repo = hg.repository( suc.get_configured_ui(), path=repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), path=repository.repo_path( trans.app ) )
|
||||
fp = repo.opener( 'hgrc', 'wb' )
|
||||
fp.write( '[paths]\n' )
|
||||
fp.write( 'default = .\n' )
|
||||
@@ -83,7 +84,7 @@ def create_repository( trans, name, type, description, long_description, user_id
|
||||
if not os.path.exists( repository_path ):
|
||||
os.makedirs( repository_path )
|
||||
# Create the local repository.
|
||||
repo = hg.repository( suc.get_configured_ui(), repository_path, create=True )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository_path, create=True )
|
||||
# Add an entry in the hgweb.config file for the local repository.
|
||||
lhs = "repos/%s/%s" % ( repository.user.username, repository.name )
|
||||
trans.app.hgweb_config_manager.add_entry( lhs, repository_path )
|
||||
|
||||
@@ -3,6 +3,7 @@ import os
|
||||
from galaxy import eggs
|
||||
from galaxy.model.orm import and_
|
||||
from galaxy.util.odict import odict
|
||||
from tool_shed.util import hg_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
|
||||
eggs.require( 'mercurial' )
|
||||
@@ -58,13 +59,13 @@ def get_components( trans ):
|
||||
|
||||
def get_previous_repository_reviews( trans, repository, changeset_revision ):
|
||||
"""Return an ordered dictionary of repository reviews up to and including the received changeset revision."""
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
reviewed_revision_hashes = [ review.changeset_revision for review in repository.reviews ]
|
||||
previous_reviews_dict = odict()
|
||||
for changeset in suc.reversed_upper_bounded_changelog( repo, changeset_revision ):
|
||||
previous_changeset_revision = str( repo.changectx( changeset ) )
|
||||
if previous_changeset_revision in reviewed_revision_hashes:
|
||||
previous_rev, previous_changeset_revision_label = suc.get_rev_label_from_changeset_revision( repo, previous_changeset_revision )
|
||||
previous_rev, previous_changeset_revision_label = hg_util.get_rev_label_from_changeset_revision( repo, previous_changeset_revision )
|
||||
revision_reviews = get_reviews_by_repository_id_changeset_revision( trans,
|
||||
trans.security.encode_id( repository.id ),
|
||||
previous_changeset_revision )
|
||||
@@ -93,7 +94,7 @@ def get_reviews_by_repository_id_changeset_revision( trans, repository_id, chang
|
||||
|
||||
def has_previous_repository_reviews( trans, repository, changeset_revision ):
|
||||
"""Determine if a repository has a changeset revision review prior to the received changeset revision."""
|
||||
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
reviewed_revision_hashes = [ review.changeset_revision for review in repository.reviews ]
|
||||
for changeset in suc.reversed_upper_bounded_changelog( repo, changeset_revision ):
|
||||
previous_changeset_revision = str( repo.changectx( changeset ) )
|
||||
|
||||
@@ -4,9 +4,6 @@ import re
|
||||
import shutil
|
||||
import string
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
from time import gmtime
|
||||
from time import strftime
|
||||
from galaxy import util
|
||||
from galaxy.util import asbool
|
||||
from galaxy.util import json
|
||||
@@ -19,6 +16,7 @@ from galaxy.model.orm import or_
|
||||
import sqlalchemy.orm.exc
|
||||
from tool_shed.util import common_util
|
||||
from tool_shed.util import encoding_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import xml_util
|
||||
import tool_shed.repository_types.util as rt_util
|
||||
from xml.etree import ElementTree as XmlET
|
||||
@@ -143,7 +141,7 @@ def changeset_is_malicious( trans, id, changeset_revision, **kwd ):
|
||||
|
||||
def changeset_is_valid( app, repository, changeset_revision ):
|
||||
"""Make sure a changeset hash is valid for a specified repository."""
|
||||
repo = hg.repository( get_configured_ui(), repository.repo_path( app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( app ) )
|
||||
for changeset in repo.changelog:
|
||||
changeset_hash = str( repo.changectx( changeset ) )
|
||||
if changeset_revision == changeset_hash:
|
||||
@@ -167,7 +165,7 @@ def check_or_update_tool_shed_status_for_installed_repository( trans, repository
|
||||
def clone_repository( repository_clone_url, repository_file_dir, ctx_rev ):
|
||||
"""Clone the repository up to the specified changeset_revision. No subsequent revisions will be present in the cloned repository."""
|
||||
try:
|
||||
commands.clone( get_configured_ui(),
|
||||
commands.clone( hg_util.get_configured_ui(),
|
||||
str( repository_clone_url ),
|
||||
dest=str( repository_file_dir ),
|
||||
pull=True,
|
||||
@@ -469,14 +467,6 @@ def get_category_by_name( trans, name ):
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
return None
|
||||
|
||||
def get_changectx_for_changeset( repo, changeset_revision, **kwd ):
|
||||
"""Retrieve a specified changectx from a repository."""
|
||||
for changeset in repo.changelog:
|
||||
ctx = repo.changectx( changeset )
|
||||
if str( ctx ) == changeset_revision:
|
||||
return ctx
|
||||
return None
|
||||
|
||||
def get_config( config_file, repo, ctx, dir ):
|
||||
"""Return the latest version of config_filename from the repository manifest."""
|
||||
config_file = strip_path( config_file )
|
||||
@@ -496,16 +486,6 @@ def get_config_from_disk( config_file, relative_install_dir ):
|
||||
return os.path.abspath( os.path.join( root, name ) )
|
||||
return None
|
||||
|
||||
def get_configured_ui():
|
||||
"""Configure any desired ui settings."""
|
||||
_ui = ui.ui()
|
||||
# The following will suppress all messages. This is
|
||||
# the same as adding the following setting to the repo
|
||||
# hgrc file' [ui] section:
|
||||
# quiet = True
|
||||
_ui.setconfig( 'ui', 'quiet', True )
|
||||
return _ui
|
||||
|
||||
def get_ctx_rev( app, tool_shed_url, name, owner, changeset_revision ):
|
||||
"""
|
||||
Send a request to the tool shed to retrieve the ctx_rev for a repository defined by the
|
||||
@@ -539,7 +519,7 @@ def get_current_repository_metadata_for_changeset_revision( trans, repository, c
|
||||
if repository_metadata:
|
||||
return repository_metadata
|
||||
# The installable changeset_revision may have been changed because it was "moved ahead" in the repository changelog.
|
||||
repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
updated_changeset_revision = get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision=changeset_revision )
|
||||
if updated_changeset_revision:
|
||||
repository_metadata = get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, updated_changeset_revision )
|
||||
@@ -590,7 +570,7 @@ def get_dependent_downloadable_revisions( trans, repository_metadata ):
|
||||
# record, so updates must be necessary.
|
||||
defined_repository = get_repository_by_name_and_owner( trans.app, name, owner )
|
||||
defined_repo_dir = defined_repository.repo_path( trans.app )
|
||||
defined_repo = hg.repository( get_configured_ui(), defined_repo_dir )
|
||||
defined_repo = hg.repository( hg_util.get_configured_ui(), defined_repo_dir )
|
||||
updated_changeset_revision = \
|
||||
get_next_downloadable_changeset_revision( defined_repository,
|
||||
defined_repo,
|
||||
@@ -799,7 +779,7 @@ def get_ordered_metadata_changeset_revisions( repository, repo, downloadable=Tru
|
||||
changeset_tups = []
|
||||
for repository_metadata in metadata_revisions:
|
||||
changeset_revision = repository_metadata.changeset_revision
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
rev = '%04d' % ctx.rev()
|
||||
else:
|
||||
@@ -913,13 +893,6 @@ def get_query_for_setting_metadata_on_repositories( trans, my_writable=False, or
|
||||
return trans.install_model.context.query( trans.install_model.ToolShedRepository ) \
|
||||
.filter( trans.install_model.ToolShedRepository.table.c.uninstalled == False )
|
||||
|
||||
def get_readable_ctx_date( ctx ):
|
||||
"""Convert the date of the changeset (the received ctx) to a human-readable date."""
|
||||
t, tz = ctx.date()
|
||||
date = datetime( *gmtime( float( t ) - tz )[ :6 ] )
|
||||
ctx_date = date.strftime( "%Y-%m-%d" )
|
||||
return ctx_date
|
||||
|
||||
def get_repo_info_tuple_contents( repo_info_tuple ):
|
||||
"""Take care in handling the repo_info_tuple as it evolves over time as new tool shed features are introduced."""
|
||||
if len( repo_info_tuple ) == 6:
|
||||
@@ -1211,38 +1184,6 @@ def get_reversed_changelog_changesets( repo ):
|
||||
reversed_changelog.insert( 0, changeset )
|
||||
return reversed_changelog
|
||||
|
||||
def get_revision_label( trans, repository, changeset_revision, include_date=True ):
|
||||
"""
|
||||
Return a string consisting of the human read-able changeset rev and the changeset revision string
|
||||
which includes the revision date if the receive include_date is True.
|
||||
"""
|
||||
repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) )
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
return get_revision_label_from_ctx( ctx, include_date=include_date )
|
||||
else:
|
||||
return "-1:%s" % changeset_revision
|
||||
|
||||
def get_revision_label_from_ctx( ctx, include_date=True ):
|
||||
if include_date:
|
||||
return '%s:%s <i><font color="#666666">(%s)</font></i>' % \
|
||||
( str( ctx.rev() ), str( ctx ), str( get_readable_ctx_date( ctx ) ) )
|
||||
return '%s:%s' % ( str( ctx.rev() ), str( ctx ) )
|
||||
|
||||
def get_rev_label_from_changeset_revision( repo, changeset_revision, include_date=True ):
|
||||
"""
|
||||
Given a changeset revision hash, return two strings, the changeset rev and the changeset revision hash
|
||||
which includes the revision date if the receive include_date is True.
|
||||
"""
|
||||
ctx = get_changectx_for_changeset( repo, changeset_revision )
|
||||
if ctx:
|
||||
rev = '%04d' % ctx.rev()
|
||||
label = get_revision_label_from_ctx( ctx, include_date=include_date )
|
||||
else:
|
||||
rev = '-1'
|
||||
label = "-1:%s" % changeset_revision
|
||||
return rev, label
|
||||
|
||||
def get_shed_tool_conf_dict( app, shed_tool_conf ):
|
||||
"""Return the in-memory version of the shed_tool_conf file, which is stored in the config_elems entry in the shed_tool_conf_dict associated with the file."""
|
||||
for index, shed_tool_conf_dict in enumerate( app.toolbox.shed_tool_confs ):
|
||||
@@ -1434,7 +1375,7 @@ def get_updated_changeset_revisions( trans, name, owner, changeset_revision ):
|
||||
"""
|
||||
repository = get_repository_by_name_and_owner( trans.app, name, owner )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
# Get the upper bound changeset revision.
|
||||
upper_bound_changeset_revision = get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
|
||||
# Build the list of changeset revision hashes defining each available update up to, but excluding, upper_bound_changeset_revision.
|
||||
@@ -1487,7 +1428,7 @@ def handle_email_alerts( trans, repository, content_alert_str='', new_repo_alert
|
||||
that was included in the change set.
|
||||
"""
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
sharable_link = generate_sharable_link_for_repository_in_tool_shed( trans, repository, changeset_revision=None )
|
||||
smtp_server = trans.app.config.smtp_server
|
||||
if smtp_server and ( new_repo_alert or repository.email_alerts ):
|
||||
@@ -1510,7 +1451,7 @@ def handle_email_alerts( trans, repository, content_alert_str='', new_repo_alert
|
||||
template = new_repo_email_alert_template
|
||||
else:
|
||||
template = email_alert_template
|
||||
display_date = get_readable_ctx_date( ctx )
|
||||
display_date = hg_util.get_readable_ctx_date( ctx )
|
||||
admin_body = string.Template( template ).safe_substitute( host=trans.request.host,
|
||||
sharable_link=sharable_link,
|
||||
repository_name=repository.name,
|
||||
@@ -1859,7 +1800,7 @@ def update_repository( repo, ctx_rev=None ):
|
||||
# I = ignored
|
||||
# It would be nice if we could use mercurial's purge extension to remove untracked files. The problem is that
|
||||
# purging is not supported by the mercurial API.
|
||||
commands.update( get_configured_ui(), repo, rev=ctx_rev )
|
||||
commands.update( hg_util.get_configured_ui(), repo, rev=ctx_rev )
|
||||
|
||||
def update_tool_shed_repository_status( app, tool_shed_repository, status, error_message=None ):
|
||||
"""Update the status of a tool shed repository in the process of being installed into Galaxy."""
|
||||
|
||||
@@ -15,6 +15,7 @@ from galaxy.util.expressions import ExpressionContext
|
||||
from galaxy.web.form_builder import SelectField
|
||||
from galaxy.tools.actions.upload import UploadToolAction
|
||||
from tool_shed.util import common_util
|
||||
from tool_shed.util import hg_util
|
||||
from tool_shed.util import xml_util
|
||||
import tool_shed.util.shed_util_common as suc
|
||||
from xml.etree import ElementTree as XmlET
|
||||
@@ -538,7 +539,7 @@ def get_version_lineage_for_tool( trans, repository_id, repository_metadata, gui
|
||||
"""
|
||||
repository = suc.get_repository_by_id( trans, repository_id )
|
||||
repo_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_dir )
|
||||
# Initialize the tool lineage
|
||||
version_lineage = [ guid ]
|
||||
# Get all ancestor guids of the received guid.
|
||||
@@ -637,7 +638,7 @@ def handle_sample_files_and_load_tool_from_disk( trans, repo_files_dir, reposito
|
||||
def handle_sample_files_and_load_tool_from_tmp_config( trans, repo, repository_id, changeset_revision, tool_config_filename, work_dir ):
|
||||
tool = None
|
||||
message = ''
|
||||
ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
|
||||
ctx = hg_util.get_changectx_for_changeset( repo, changeset_revision )
|
||||
# We're not currently doing anything with the returned list of deleted_sample_files here. It is intended to help handle sample files that are in
|
||||
# the manifest, but have been deleted from disk.
|
||||
sample_files, deleted_sample_files = get_list_of_copied_sample_files( repo, ctx, dir=work_dir )
|
||||
@@ -866,7 +867,7 @@ def load_tool_from_changeset_revision( trans, repository_id, changeset_revision,
|
||||
original_tool_data_path = trans.app.config.tool_data_path
|
||||
repository = suc.get_repository_in_tool_shed( trans, repository_id )
|
||||
repo_files_dir = repository.repo_path( trans.app )
|
||||
repo = hg.repository( suc.get_configured_ui(), repo_files_dir )
|
||||
repo = hg.repository( hg_util.get_configured_ui(), repo_files_dir )
|
||||
message = ''
|
||||
tool = None
|
||||
can_use_disk_file = False
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
<repository owner="devteam" name="analyze_covariates" changeset_revision="738bc749f9a3" description="Analyze Covariates">
|
||||
<tool id="gatk_analyze_covariates" version="0.0.5" file="gatk/analyze_covariates.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="basecoverage" changeset_revision="1e6a9e97fa41" description="Base Coverage of all intervals">
|
||||
<tool id="gops_basecoverage_1" version="0.0.1" file="new_operations/basecoverage.xml" />
|
||||
<repository owner="devteam" name="basecoverage" changeset_revision="642849141ae9" description="Base Coverage of all intervals">
|
||||
<tool id="gops_basecoverage_1" version="1.0.0" file="new_operations/basecoverage.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="best_regression_subsets" changeset_revision="e769cde223a5" description="Perform Best-subsets Regression">
|
||||
<tool id="BestSubsetsRegression1" version="0.0.1" file="regVariation/best_regression_subsets.xml" />
|
||||
<repository owner="devteam" name="best_regression_subsets" changeset_revision="4f33ec73e445" description="Perform Best-subsets Regression">
|
||||
<tool id="BestSubsetsRegression1" version="1.0.0" file="regVariation/best_regression_subsets.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="cluster" changeset_revision="d5677eecbad4" description="Cluster">
|
||||
<tool id="gops_cluster_1" version="0.0.1" file="new_operations/cluster.xml" />
|
||||
<repository owner="devteam" name="cluster" changeset_revision="9fcc3a1c3d26" description="Cluster">
|
||||
<tool id="gops_cluster_1" version="1.0.0" file="new_operations/cluster.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="complement" changeset_revision="d958d5a0d1e8" description="Complement intervals of a dataset">
|
||||
<tool id="gops_complement_1" version="0.0.1" file="new_operations/complement.xml" />
|
||||
<repository owner="devteam" name="complement" changeset_revision="67c4ed724bfd" description="Complement intervals of a dataset">
|
||||
<tool id="gops_complement_1" version="1.0.0" file="new_operations/complement.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="compute_q_values" changeset_revision="63abfc350814" description="Compute q-values based on multiple simultaneous tests p-values">
|
||||
<tool id="compute_q_values" version="1.0.1" file="regVariation/compute_q_values.xml" />
|
||||
@@ -24,8 +24,8 @@
|
||||
<repository owner="devteam" name="count_covariates" changeset_revision="14e304b70425" description="Count Covariates on BAM files">
|
||||
<tool id="gatk_count_covariates" version="0.0.5" file="gatk/count_covariates.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="coverage" changeset_revision="1e864693a1c0" description="Coverage of a set of intervals on second set of intervals">
|
||||
<tool id="gops_coverage_1" version="0.0.1" file="new_operations/coverage.xml" />
|
||||
<repository owner="devteam" name="coverage" changeset_revision="16b62a897aac" description="Coverage of a set of intervals on second set of intervals">
|
||||
<tool id="gops_coverage_1" version="1.0.0" file="new_operations/coverage.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="depth_of_coverage" changeset_revision="c3f08370fc82" description="Depth of Coverage on BAM files">
|
||||
<tool id="gatk_depth_of_coverage" version="0.0.2" file="gatk/depth_of_coverage.xml" />
|
||||
@@ -36,23 +36,23 @@
|
||||
<repository owner="devteam" name="flanking_features" changeset_revision="90100b587723" description="Fetch closest non-overlapping feature for every interval">
|
||||
<tool id="flanking_features_1" version="4.0.1" file="new_operations/flanking_features.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="get_flanks" changeset_revision="a72f0decd7b3" description="Get flanks - returns flanking region/s for every gene">
|
||||
<tool id="get_flanks1" version="0.0.1" file="new_operations/get_flanks.xml" />
|
||||
<repository owner="devteam" name="get_flanks" changeset_revision="c3b1781c6fd1" description="Get flanks - returns flanking region/s for every gene">
|
||||
<tool id="get_flanks1" version="1.0.0" file="new_operations/get_flanks.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="getindelrates_3way" changeset_revision="d427e5acb9ee" description="Estimate Indel Rates for 3-way alignments">
|
||||
<tool id="indelRates_3way" version="1.0.0" file="regVariation/getIndelRates_3way.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="getindels_2way" changeset_revision="91655316fcf0" description="Fetch Indels from pairwise alignments">
|
||||
<tool id="getIndels_2way" version="0.0.1" file="regVariation/getIndels_2way.xml" />
|
||||
<repository owner="devteam" name="getindels_2way" changeset_revision="f1dc6f5fce6e" description="Fetch Indels from pairwise alignments">
|
||||
<tool id="getIndels_2way" version="1.0.0" file="regVariation/getIndels_2way.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="indel_realigner" changeset_revision="bb0beda6cf83" description="Indel Realigner - perform local realignment">
|
||||
<tool id="gatk_indel_realigner" version="0.0.6" file="gatk/indel_realigner.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="intersect" changeset_revision="5b3c6135a982" description="Intersect the intervals of two datasets">
|
||||
<tool id="gops_intersect_1" version="0.0.1" file="new_operations/intersect.xml" />
|
||||
<repository owner="devteam" name="intersect" changeset_revision="81ad85f731b9" description="Intersect the intervals of two datasets">
|
||||
<tool id="gops_intersect_1" version="1.0.0" file="new_operations/intersect.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="join" changeset_revision="e56b47dce68a" description="Join the intervals of two datasets side-by-side">
|
||||
<tool id="gops_join_1" version="0.0.1" file="new_operations/join.xml" />
|
||||
<repository owner="devteam" name="join" changeset_revision="11a49f94d086" description="Join the intervals of two datasets side-by-side">
|
||||
<tool id="gops_join_1" version="1.0.0" file="new_operations/join.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="linear_regression" changeset_revision="cf431604ec3e" description="Perform Linear Regression">
|
||||
<tool id="LinearRegression1" version="1.0.1" file="regVariation/linear_regression.xml" />
|
||||
@@ -63,11 +63,11 @@
|
||||
<repository owner="devteam" name="maf_cpg_filter" changeset_revision="7f2a12cb047d" description="Mask CpG/non-CpG sites from MAF file">
|
||||
<tool id="cpgFilter" version="1.0.0" file="regVariation/maf_cpg_filter.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="merge" changeset_revision="b488a1fa07f6" description="Merge the overlapping intervals of a dataset">
|
||||
<tool id="gops_merge_1" version="0.0.1" file="new_operations/merge.xml" />
|
||||
<repository owner="devteam" name="merge" changeset_revision="55e88307811d" description="Merge the overlapping intervals of a dataset">
|
||||
<tool id="gops_merge_1" version="1.0.0" file="new_operations/merge.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="microsats_alignment_level" changeset_revision="d4368a5a3fc7" description="Extract Orthologous Microsatellites from pair-wise alignments">
|
||||
<tool id="microsats_align1" version="0.0.1" file="regVariation/microsats_alignment_level.xml" />
|
||||
<repository owner="devteam" name="microsats_alignment_level" changeset_revision="7852385470f3" description="Extract Orthologous Microsatellites from pair-wise alignments">
|
||||
<tool id="microsats_align1" version="1.0.0" file="regVariation/microsats_alignment_level.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="microsats_mutability" changeset_revision="4aa1ee5d8510" description="Estimate microsatellite mutability by specified attributes">
|
||||
<tool id="microsats_mutability1" version="1.1.0" file="regVariation/microsats_mutability.xml" />
|
||||
@@ -93,8 +93,8 @@
|
||||
<repository owner="devteam" name="substitutions" changeset_revision="c54f5d0bbb58" description="Fetch substitutions from pairwise alignments">
|
||||
<tool id="substitutions1" version="1.0.0" file="regVariation/substitutions.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="subtract" changeset_revision="5bc2dacbe729" description="Subtract the intervals of two datasets">
|
||||
<tool id="gops_subtract_1" version="0.0.1" file="new_operations/subtract.xml" />
|
||||
<repository owner="devteam" name="subtract" changeset_revision="7bf44b9d7a8b" description="Subtract the intervals of two datasets">
|
||||
<tool id="gops_subtract_1" version="1.0.0" file="new_operations/subtract.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="subtract_query" changeset_revision="5f6ebef89722" description="Subtract Whole Dataset from another dataset">
|
||||
<tool id="subtract_query1" version="0.1" file="new_operations/subtract_query.xml" />
|
||||
@@ -135,7 +135,7 @@
|
||||
<repository owner="devteam" name="weightedaverage" changeset_revision="90611e86a998" description="Assign weighted-average of the values of features overlapping an interval">
|
||||
<tool id="wtavg" version="1.0.0" file="regVariation/WeightedAverage.xml" />
|
||||
</repository>
|
||||
<repository owner="devteam" name="windowsplitter" changeset_revision="e5490ea33640" description="Make windows">
|
||||
<tool id="winSplitter" version="0.0.1" file="regVariation/windowSplitter.xml" />
|
||||
<repository owner="devteam" name="windowsplitter" changeset_revision="75abda2290cc" description="Make windows">
|
||||
<tool id="winSplitter" version="1.0.0" file="regVariation/windowSplitter.xml" />
|
||||
</repository>
|
||||
</toolshed>
|
||||
@@ -2,28 +2,30 @@
|
||||
// === MAIN GALAXY LIBRARY MODULE ====
|
||||
// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
|
||||
// global variables
|
||||
var library_router = null;
|
||||
|
||||
// dependencies
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"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"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
"mvc/library/library-librarytoolbar-view",
|
||||
"mvc/library/library-foldertoolbar-view"
|
||||
],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_baseMVC,
|
||||
mod_library_model,
|
||||
mod_folderlist_view,
|
||||
mod_librarylist_view,
|
||||
mod_librarytoolbar_view) {
|
||||
mod_librarytoolbar_view,
|
||||
mod_foldertoolbar_view
|
||||
) {
|
||||
|
||||
// ============================================================================
|
||||
//ROUTER
|
||||
var LibraryRouter = Backbone.Router.extend({
|
||||
routes: {
|
||||
@@ -44,12 +46,14 @@ var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({
|
||||
}
|
||||
});
|
||||
|
||||
// galaxy library wrapper View
|
||||
// ============================================================================
|
||||
// Main controller of Galaxy Library
|
||||
var GalaxyLibrary = Backbone.View.extend({
|
||||
toolbarView: null,
|
||||
libraryToolbarView: null,
|
||||
libraryListView: null,
|
||||
library_router: null,
|
||||
folderContentView: null,
|
||||
folderToolbarView: null,
|
||||
folderListView: null,
|
||||
initialize : function(){
|
||||
Galaxy.libraries = this;
|
||||
|
||||
@@ -59,25 +63,26 @@ var GalaxyLibrary = Backbone.View.extend({
|
||||
|
||||
this.library_router.on('route:libraries', function() {
|
||||
// initialize and render the toolbar first
|
||||
Galaxy.libraries.toolbarView = new mod_librarytoolbar_view.ToolbarView();
|
||||
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) {
|
||||
// render folder contents
|
||||
if (!Galaxy.libraries.folderContentView) {Galaxy.libraries.folderContentView = new mod_folderlist_view.FolderContentView();}
|
||||
Galaxy.libraries.folderContentView.render({id: id});
|
||||
// TODO place caching here, sessionstorage/localstorage?
|
||||
Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id});
|
||||
Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id});
|
||||
});
|
||||
|
||||
this.library_router.on('route:download', function(folder_id, format) {
|
||||
if ($('#center').find(':checked').length === 0) {
|
||||
if ($('#center').find(':checked').length === 0) {
|
||||
mod_toastr.info('You have to select some datasets to download')
|
||||
// this happens rarely when there is a server/data error and client gets an actual response instead of an attachment
|
||||
// we don't know what was selected so we can't download again, we redirect to the folder provided
|
||||
Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true});
|
||||
} else {
|
||||
// send download stream
|
||||
Galaxy.libraries.folderContentView.download(folder_id, format);
|
||||
Galaxy.libraries.folderToolbarView.download(folder_id, format);
|
||||
Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: false, replace: true});
|
||||
}
|
||||
});
|
||||
@@ -86,7 +91,6 @@ var GalaxyLibrary = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
|
||||
// return
|
||||
return {
|
||||
GalaxyApp: GalaxyLibrary
|
||||
};
|
||||
|
||||
@@ -172,101 +172,98 @@ function Node( element ) {
|
||||
}
|
||||
$.extend( Node.prototype, {
|
||||
new_input_terminal : function( input ) {
|
||||
var t = $("<div class='terminal input-terminal'></div>");
|
||||
var t = $("<div class='terminal input-terminal'></div>")[ 0 ];
|
||||
this.enable_input_terminal( t, input.name, input.extensions, input.multiple );
|
||||
return t;
|
||||
},
|
||||
enable_input_terminal : function( elements, name, types, multiple ) {
|
||||
enable_input_terminal : function( element, name, types, multiple ) {
|
||||
var node = this;
|
||||
$(elements).each( function() {
|
||||
var terminal = this.terminal = new InputTerminal( this, types, multiple );
|
||||
terminal.node = node;
|
||||
terminal.name = name;
|
||||
$(this).bind( "dropinit", function( e, d ) {
|
||||
// Accept a dragable if it is an output terminal and has a
|
||||
// compatible type
|
||||
return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
|
||||
}).bind( "dropstart", function( e, d ) {
|
||||
if (d.proxy.terminal) {
|
||||
d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
|
||||
}
|
||||
}).bind( "dropend", function ( e, d ) {
|
||||
if (d.proxy.terminal) {
|
||||
d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
|
||||
}
|
||||
}).bind( "drop", function( e, d ) {
|
||||
( new Connector( d.drag.terminal, terminal ) ).redraw();
|
||||
}).bind( "hover", function() {
|
||||
// If connected, create a popup to allow disconnection
|
||||
if ( terminal.connectors.length > 0 ) {
|
||||
// Create callout
|
||||
var t = $("<div class='callout'></div>")
|
||||
.css( { display: 'none' } )
|
||||
.appendTo( "body" )
|
||||
.append(
|
||||
$("<div class='button'></div>").append(
|
||||
$("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
|
||||
$.each( terminal.connectors, function( _, x ) {
|
||||
if (x) {
|
||||
x.destroy();
|
||||
}
|
||||
});
|
||||
t.remove();
|
||||
})))
|
||||
.bind( "mouseleave", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
// Position it and show
|
||||
t.css({
|
||||
top: $(this).offset().top - 2,
|
||||
left: $(this).offset().left - t.width(),
|
||||
'padding-right': $(this).width()
|
||||
}).show();
|
||||
}
|
||||
});
|
||||
node.input_terminals[name] = terminal;
|
||||
|
||||
var terminal = element.terminal = new InputTerminal( element, types, multiple );
|
||||
terminal.node = node;
|
||||
terminal.name = name;
|
||||
$(element).bind( "dropinit", function( e, d ) {
|
||||
// Accept a dragable if it is an output terminal and has a
|
||||
// compatible type
|
||||
return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
|
||||
}).bind( "dropstart", function( e, d ) {
|
||||
if (d.proxy.terminal) {
|
||||
d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
|
||||
}
|
||||
}).bind( "dropend", function ( e, d ) {
|
||||
if (d.proxy.terminal) {
|
||||
d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
|
||||
}
|
||||
}).bind( "drop", function( e, d ) {
|
||||
( new Connector( d.drag.terminal, terminal ) ).redraw();
|
||||
}).bind( "hover", function() {
|
||||
// If connected, create a popup to allow disconnection
|
||||
if ( terminal.connectors.length > 0 ) {
|
||||
// Create callout
|
||||
var t = $("<div class='callout'></div>")
|
||||
.css( { display: 'none' } )
|
||||
.appendTo( "body" )
|
||||
.append(
|
||||
$("<div class='button'></div>").append(
|
||||
$("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
|
||||
$.each( terminal.connectors, function( _, x ) {
|
||||
if (x) {
|
||||
x.destroy();
|
||||
}
|
||||
});
|
||||
t.remove();
|
||||
})))
|
||||
.bind( "mouseleave", function() {
|
||||
$(this).remove();
|
||||
});
|
||||
// Position it and show
|
||||
t.css({
|
||||
top: $(element).offset().top - 2,
|
||||
left: $(element).offset().left - t.width(),
|
||||
'padding-right': $(element).width()
|
||||
}).show();
|
||||
}
|
||||
});
|
||||
node.input_terminals[name] = terminal;
|
||||
},
|
||||
enable_output_terminal : function( elements, name, type ) {
|
||||
enable_output_terminal : function( element, name, type ) {
|
||||
var node = this;
|
||||
$(elements).each( function() {
|
||||
var terminal_element = this;
|
||||
var terminal = this.terminal = new OutputTerminal( this, type );
|
||||
terminal.node = node;
|
||||
terminal.name = name;
|
||||
$(this).bind( "dragstart", function( e, d ) {
|
||||
$( d.available ).addClass( "input-terminal-active" );
|
||||
// Save PJAs in the case of change datatype actions.
|
||||
workflow.check_changes_in_active_form();
|
||||
// Drag proxy div
|
||||
var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
|
||||
.appendTo( "#canvas-container" ).get(0);
|
||||
// Terminal and connection to display noodle while dragging
|
||||
h.terminal = new OutputTerminal( h );
|
||||
var c = new Connector();
|
||||
c.dragging = true;
|
||||
c.connect( this.terminal, h.terminal );
|
||||
return h;
|
||||
}).bind( "drag", function ( e, d ) {
|
||||
var onmove = function() {
|
||||
var po = $(d.proxy).offsetParent().offset(),
|
||||
x = d.offsetX - po.left,
|
||||
y = d.offsetY - po.top;
|
||||
$(d.proxy).css( { left: x, top: y } );
|
||||
d.proxy.terminal.redraw();
|
||||
// FIXME: global
|
||||
canvas_manager.update_viewport_overlay();
|
||||
};
|
||||
onmove();
|
||||
$("#canvas-container").get(0).scroll_panel.test( e, onmove );
|
||||
}).bind( "dragend", function ( e, d ) {
|
||||
d.proxy.terminal.connectors[0].destroy();
|
||||
$(d.proxy).remove();
|
||||
$( d.available ).removeClass( "input-terminal-active" );
|
||||
$("#canvas-container").get(0).scroll_panel.stop();
|
||||
});
|
||||
node.output_terminals[name] = terminal;
|
||||
var terminal_element = element;
|
||||
var terminal = element.terminal = new OutputTerminal( element, type );
|
||||
terminal.node = node;
|
||||
terminal.name = name;
|
||||
$(element).bind( "dragstart", function( e, d ) {
|
||||
$( d.available ).addClass( "input-terminal-active" );
|
||||
// Save PJAs in the case of change datatype actions.
|
||||
workflow.check_changes_in_active_form();
|
||||
// Drag proxy div
|
||||
var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
|
||||
.appendTo( "#canvas-container" ).get(0);
|
||||
// Terminal and connection to display noodle while dragging
|
||||
h.terminal = new OutputTerminal( h );
|
||||
var c = new Connector();
|
||||
c.dragging = true;
|
||||
c.connect( element.terminal, h.terminal );
|
||||
return h;
|
||||
}).bind( "drag", function ( e, d ) {
|
||||
var onmove = function() {
|
||||
var po = $(d.proxy).offsetParent().offset(),
|
||||
x = d.offsetX - po.left,
|
||||
y = d.offsetY - po.top;
|
||||
$(d.proxy).css( { left: x, top: y } );
|
||||
d.proxy.terminal.redraw();
|
||||
// FIXME: global
|
||||
canvas_manager.update_viewport_overlay();
|
||||
};
|
||||
onmove();
|
||||
$("#canvas-container").get(0).scroll_panel.test( e, onmove );
|
||||
}).bind( "dragend", function ( e, d ) {
|
||||
d.proxy.terminal.connectors[0].destroy();
|
||||
$(d.proxy).remove();
|
||||
$( d.available ).removeClass( "input-terminal-active" );
|
||||
$("#canvas-container").get(0).scroll_panel.stop();
|
||||
});
|
||||
node.output_terminals[name] = terminal;
|
||||
},
|
||||
redraw : function () {
|
||||
$.each( this.input_terminals, function( _, t ) {
|
||||
@@ -342,7 +339,7 @@ $.extend( Node.prototype, {
|
||||
}
|
||||
$.each( data.data_outputs, function( i, output ) {
|
||||
var t = $( "<div class='terminal output-terminal'></div>" );
|
||||
node.enable_output_terminal( t, output.name, output.extensions );
|
||||
node.enable_output_terminal( t[ 0 ], output.name, output.extensions );
|
||||
var label = output.name;
|
||||
if ( output.extensions.indexOf( 'input' ) < 0 ) {
|
||||
label = label + " (" + output.extensions.join(", ") + ")";
|
||||
@@ -422,7 +419,6 @@ $.extend( Node.prototype, {
|
||||
// Update input rows
|
||||
var old_body = el.find( "div.inputs" );
|
||||
var new_body = $("<div class='inputs'></div>");
|
||||
var old = old_body.find( "div.input-data-row");
|
||||
$.each( data.data_inputs, function( i, input ) {
|
||||
var t = node.new_input_terminal( input );
|
||||
// If already connected save old connection
|
||||
@@ -430,8 +426,8 @@ $.extend( Node.prototype, {
|
||||
$(this).find( ".input-terminal" ).each( function() {
|
||||
var c = this.terminal.connectors[0];
|
||||
if ( c ) {
|
||||
t[0].terminal.connectors[0] = c;
|
||||
c.handle2 = t[0].terminal;
|
||||
t.terminal.connectors[0] = c;
|
||||
c.handle2 = t.terminal;
|
||||
}
|
||||
});
|
||||
$(this).remove();
|
||||
@@ -893,6 +889,18 @@ function prebuild_node( type, title_text, tool_id ) {
|
||||
return node;
|
||||
}
|
||||
|
||||
function add_node( type, title_text, tool_id ) {
|
||||
// Abstraction for use by galaxy.workflow.js to hide
|
||||
// some editor details from workflow code and reduce duplication
|
||||
// between add_node_for_tool and add_node_for_module.
|
||||
var node = prebuild_node( type, title_text, tool_id );
|
||||
workflow.add_node( node );
|
||||
workflow.fit_canvas_to_nodes();
|
||||
canvas_manager.draw_overview();
|
||||
workflow.activate_node( node );
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
var ext_to_type = null;
|
||||
var type_to_type = null;
|
||||
|
||||
@@ -320,11 +320,7 @@ function scroll_to_nodes() {
|
||||
|
||||
// Add a new step to the workflow by tool id
|
||||
function add_node_for_tool( id, title ) {
|
||||
var node = prebuild_node( 'tool', title, id );
|
||||
workflow.add_node( node );
|
||||
workflow.fit_canvas_to_nodes();
|
||||
canvas_manager.draw_overview();
|
||||
workflow.activate_node( node );
|
||||
node = add_node( 'tool', title, id );
|
||||
$.ajax( {
|
||||
url: get_new_module_info_url,
|
||||
data: { type: "tool", tool_id: id, "_": "true" },
|
||||
@@ -344,11 +340,7 @@ function add_node_for_tool( id, title ) {
|
||||
}
|
||||
|
||||
function add_node_for_module( type, title ) {
|
||||
node = prebuild_node( type, title );
|
||||
workflow.add_node( node );
|
||||
workflow.fit_canvas_to_nodes();
|
||||
canvas_manager.draw_overview();
|
||||
workflow.activate_node( node );
|
||||
node = add_node( type, title );
|
||||
$.ajax( {
|
||||
url: get_new_module_info_url,
|
||||
data: { type: type, "_": "true" },
|
||||
|
||||
@@ -1,458 +1,126 @@
|
||||
// dependencies
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"galaxy.masthead",
|
||||
"utils/utils",
|
||||
"libs/toastr",
|
||||
"mvc/library/library-model"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
"mvc/library/library-model",
|
||||
"mvc/library/library-folderrow-view"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_library_model) {
|
||||
mod_library_model,
|
||||
mod_library_folderrow_view) {
|
||||
|
||||
//main view for folder browsing
|
||||
var FolderContentView = Backbone.View.extend({
|
||||
// main element definition
|
||||
el : '#center',
|
||||
// progress percentage
|
||||
progress: 0,
|
||||
// progress rate per one item
|
||||
progressStep: 1,
|
||||
// last selected history in modal for UX
|
||||
lastSelectedHistory: '',
|
||||
// self modal
|
||||
modal : null,
|
||||
// loaded folders
|
||||
folders : null,
|
||||
var FolderListView = Backbone.View.extend({
|
||||
// main element definition
|
||||
el : '#folder_items_element',
|
||||
// progress percentage
|
||||
progress: 0,
|
||||
// progress rate per one item
|
||||
progressStep: 1,
|
||||
// self modal
|
||||
modal : null,
|
||||
|
||||
folderContainer: null,
|
||||
|
||||
// event binding
|
||||
events: {
|
||||
'click #select-all-checkboxes' : 'selectAll',
|
||||
'click .dataset_row' : 'selectClickedRow'
|
||||
},
|
||||
// initialize
|
||||
initialize : function(){
|
||||
this.folders = [];
|
||||
initialize : function(options){
|
||||
var that = this;
|
||||
this.options = _.defaults(this.options || {}, options);
|
||||
this.queue = jQuery.Deferred();
|
||||
this.queue.resolve();
|
||||
},
|
||||
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
// === TEMPLATES ====
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
|
||||
// main template for folder browsing
|
||||
templateFolder : function (){
|
||||
var tmpl_array = [];
|
||||
|
||||
// CONTAINER
|
||||
tmpl_array.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; ">');
|
||||
tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-folders" target="_blank">Trello</a>.</h3>');
|
||||
|
||||
// TOOLBAR
|
||||
tmpl_array.push('<div id="library_folder_toolbar" >');
|
||||
tmpl_array.push(' <button title="Create New Folder" id="toolbtn_create_folder" class="primary-button" type="button"><span class="fa fa-plus"></span> <span class="fa fa-folder-close"></span> folder</button>');
|
||||
tmpl_array.push(' <button title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button" style="display: none; margin-left: 0.5em;" type="button"><span class="fa fa-book"></span> to history</button>');
|
||||
tmpl_array.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display: none; ">');
|
||||
tmpl_array.push(' <button title="Download selected datasets" 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><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');
|
||||
tmpl_array.push(' <li><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');
|
||||
tmpl_array.push(' <li><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');
|
||||
tmpl_array.push(' </ul>');
|
||||
tmpl_array.push(' </div>');
|
||||
|
||||
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(path, function(path_item) { %>');
|
||||
tmpl_array.push(' <% if (path_item[0] != 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 in this folder"><%- path_item[1] %></span></li>');
|
||||
tmpl_array.push(' <% } %>');
|
||||
tmpl_array.push(' <% }); %>');
|
||||
tmpl_array.push('</ol>');
|
||||
|
||||
|
||||
// FOLDER CONTENT
|
||||
tmpl_array.push('<table id="folder_table" class="grid table table-condensed">');
|
||||
tmpl_array.push(' <thead>');
|
||||
tmpl_array.push(' <th class="button_heading"></th>');
|
||||
tmpl_array.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');
|
||||
tmpl_array.push(' <th>name</th>');
|
||||
tmpl_array.push(' <th>data type</th>');
|
||||
tmpl_array.push(' <th>size</th>');
|
||||
tmpl_array.push(' <th>date (UTC)</th>');
|
||||
tmpl_array.push(' </thead>');
|
||||
tmpl_array.push(' <tbody>');
|
||||
tmpl_array.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>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' </tr>');
|
||||
tmpl_array.push(' <% _.each(items, function(content_item) { %>');
|
||||
tmpl_array.push(' <% if (content_item.get("type") === "folder") { %>'); // folder
|
||||
tmpl_array.push(' <tr class="folder_row light" id="<%- content_item.id %>">');
|
||||
tmpl_array.push(' <td>');
|
||||
tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');
|
||||
tmpl_array.push(' </td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td>');
|
||||
tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');
|
||||
tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>'); // empty folder
|
||||
tmpl_array.push(' <span class="muted">(empty folder)</span>');
|
||||
tmpl_array.push(' <% } %>');
|
||||
tmpl_array.push(' </td>');
|
||||
tmpl_array.push(' <td>folder</td>');
|
||||
tmpl_array.push(' <td><%= _.escape(content_item.get("item_count")) %> item(s)</td>'); // size
|
||||
tmpl_array.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>'); // time updated
|
||||
tmpl_array.push(' </tr>');
|
||||
tmpl_array.push(' <% } else { %>');
|
||||
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="#" 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("time_updated")) %></td>'); // time updated
|
||||
tmpl_array.push(' </tr>');
|
||||
tmpl_array.push(' <% } %> ');
|
||||
tmpl_array.push(' <% }); %>');
|
||||
tmpl_array.push(' ');
|
||||
tmpl_array.push(' </tbody>');
|
||||
tmpl_array.push('</table>');
|
||||
|
||||
tmpl_array.push('</div>');
|
||||
return 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('');
|
||||
},
|
||||
|
||||
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_bulk" name="dataset_import_bulk" 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 tmpl_array.join('');
|
||||
},
|
||||
|
||||
templateProgressBar : function (){
|
||||
var tmpl_array = [];
|
||||
|
||||
tmpl_array.push('<div class="import_text">');
|
||||
tmpl_array.push('Importing selected datasets to history <b><%= _.escape(history_name) %></b>');
|
||||
tmpl_array.push('</div>');
|
||||
tmpl_array.push('<div class="progress">');
|
||||
tmpl_array.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');
|
||||
tmpl_array.push(' <span class="completion_span">0% Complete</span>');
|
||||
tmpl_array.push(' </div>');
|
||||
tmpl_array.push('</div>');
|
||||
tmpl_array.push('');
|
||||
|
||||
return 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 tmpl_array.join('');
|
||||
},
|
||||
|
||||
// MMMMMMMMMMMMMMM
|
||||
// === EVENTS ====
|
||||
// MMMMMMMMMMMMMMM
|
||||
|
||||
// event binding
|
||||
events: {
|
||||
'click #select-all-checkboxes' : 'selectAll',
|
||||
'click #toolbtn_bulk_import' : 'modalBulkImport',
|
||||
'click #toolbtn_dl' : 'bulkDownload',
|
||||
'click #toolbtn_create_folder' : 'createFolderFromModal',
|
||||
'click .library-dataset' : 'showDatasetDetails',
|
||||
'click .dataset_row' : 'selectClickedRow'
|
||||
},
|
||||
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
// === FUNCTIONS ====
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
|
||||
//render the folder view
|
||||
render: function (options) {
|
||||
//hack to show scrollbars
|
||||
$("#center").css('overflow','auto');
|
||||
|
||||
view = this;
|
||||
var that = this;
|
||||
|
||||
var folderContainer = new mod_library_model.FolderContainer({id: options.id});
|
||||
folderContainer.url = folderContainer.attributes.urlRoot + options.id + '/contents';
|
||||
|
||||
folderContainer.fetch({
|
||||
success: function (container) {
|
||||
|
||||
// prepare nice size strings
|
||||
for (var i = 0; i < folderContainer.attributes.folder.models.length; i++) {
|
||||
var model = folderContainer.attributes.folder.models[i]
|
||||
if (model.get('type') === 'file'){
|
||||
model.set('readable_size', that.size_to_string(model.get('file_size')))
|
||||
}
|
||||
};
|
||||
|
||||
// find the upper id
|
||||
var path = folderContainer.full_path;
|
||||
var upper_folder_id;
|
||||
if (path.length === 1){ // library is above us
|
||||
upper_folder_id = 0;
|
||||
} else {
|
||||
upper_folder_id = path[path.length-2][0];
|
||||
}
|
||||
|
||||
var template = _.template(that.templateFolder(), { path: folderContainer.full_path, items: folderContainer.attributes.folder.models, id: options.id, upper_folder_id: upper_folder_id });
|
||||
// var template = _.template(that.templateFolder(), { path: folderContainer.full_path, items: folderContainer.attributes.folder.models, id: options.id });
|
||||
that.$el.html(template);
|
||||
|
||||
this.folderContainer = new mod_library_model.FolderContainer({id: this.options.id});
|
||||
this.folderContainer.url = this.folderContainer.attributes.urlRoot + this.options.id + '/contents';
|
||||
this.folderContainer.fetch({
|
||||
success: function (folderContainer) {
|
||||
that.render();
|
||||
},
|
||||
error: function(){
|
||||
mod_toastr.error('An error occured :(');
|
||||
}
|
||||
})
|
||||
},
|
||||
error: function(){
|
||||
mod_toastr.error('An error occured :(');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function (options) {
|
||||
this.options = _.defaults(this.options || {}, options);
|
||||
var template = this.templateFolder();
|
||||
var contains_file = false;
|
||||
|
||||
// TODO move to server
|
||||
// prepare nice size strings
|
||||
for (var i = 0; i < this.folderContainer.attributes.folder.models.length; i++) {
|
||||
var model = this.folderContainer.attributes.folder.models[i];
|
||||
if (model.get('type') === 'file'){
|
||||
contains_file = true;
|
||||
model.set('readable_size', this.size_to_string(model.get('file_size')));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO move to server
|
||||
// find the upper id in the full path
|
||||
var path = this.folderContainer.attributes.metadata.full_path;
|
||||
var upper_folder_id;
|
||||
if (path.length === 1){ // the library is above us
|
||||
upper_folder_id = 0;
|
||||
} else {
|
||||
upper_folder_id = path[path.length-2][0];
|
||||
}
|
||||
|
||||
this.$el.html(template({ path: this.folderContainer.attributes.metadata.full_path, items: this.folderContainer.attributes.folder.models, id: this.options.id, upper_folder_id: upper_folder_id }));
|
||||
|
||||
if (this.folderContainer.attributes.folder.models.length > 0){
|
||||
this.renderRows();
|
||||
}
|
||||
if (this.folderContainer.attributes.metadata.can_add_library_item === true){
|
||||
Galaxy.libraries.folderToolbarView.configureElements({ can_add_library_item: this.folderContainer.attributes.metadata.can_add_library_item, contains_file: contains_file });
|
||||
}
|
||||
|
||||
// initialize the library tooltips
|
||||
$("#center [data-toggle]").tooltip();
|
||||
//hack to show scrollbars
|
||||
$("#center").css('overflow','auto');
|
||||
},
|
||||
|
||||
renderRows: function(){
|
||||
for (var i = 0; i < this.folderContainer.attributes.folder.models.length; i++) {
|
||||
var folder_item = this.folderContainer.attributes.folder.models[i];
|
||||
var rowView = new mod_library_folderrow_view.FolderRowView(folder_item);
|
||||
this.$el.find('#folder_list_body').append(rowView.el);
|
||||
}
|
||||
},
|
||||
|
||||
// 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;
|
||||
},
|
||||
|
||||
//show modal with current dataset info
|
||||
showDatasetDetails : function(event){
|
||||
// prevent default
|
||||
event.preventDefault();
|
||||
|
||||
//TODO check whether we already have the data
|
||||
|
||||
//load the ID of the row
|
||||
var id = $(event.target).parent().parent().parent().attr('id');
|
||||
if (typeof id === 'undefined'){
|
||||
id = $(event.target).parent().attr('id');
|
||||
}
|
||||
if (typeof id === 'undefined'){
|
||||
id = $(event.target).parent().parent().attr('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 render here already
|
||||
//fetch user histories for import purposes
|
||||
histories.fetch({
|
||||
success: function (histories){
|
||||
self.renderModalAfterFetch(item, histories)
|
||||
},
|
||||
error: function(){
|
||||
mod_toastr.error('An error occured during fetching histories:(');
|
||||
self.renderModalAfterFetch(item)
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(){
|
||||
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 : 'Dataset Details',
|
||||
body : template,
|
||||
buttons : {
|
||||
'Import' : function() { self.importCurrentIntoHistory() },
|
||||
'Download' : function() { self.downloadCurrent() },
|
||||
'Close' : function() { self.modal.hide() }
|
||||
}
|
||||
});
|
||||
|
||||
$(".peek").html('Peek:' + 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);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 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};
|
||||
|
||||
// we assume the view is existent
|
||||
folderContentView.processDownload(url, data);
|
||||
this.modal.enableButton('Import');
|
||||
this.modal.enableButton('Download');
|
||||
},
|
||||
|
||||
// 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';
|
||||
|
||||
// save the dataset into selected history
|
||||
historyItem.save({ content : library_dataset_id, source : 'library' }, { success : function(){
|
||||
mod_toastr.success('Dataset imported');
|
||||
//enable the buttons
|
||||
self.modal.enableButton('Import');
|
||||
self.modal.enableButton('Download');
|
||||
}, error : function(){
|
||||
mod_toastr.error('An error occured! Dataset not imported. Please try again.')
|
||||
//enable the buttons
|
||||
self.modal.enableButton('Import');
|
||||
self.modal.enableButton('Download');
|
||||
}
|
||||
});
|
||||
},
|
||||
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;
|
||||
},
|
||||
|
||||
// select all datasets
|
||||
selectAll : function (event) {
|
||||
var selected = event.target.checked;
|
||||
that = this;
|
||||
// Iterate each checkbox
|
||||
$(':checkbox').each(function () {
|
||||
this.checked = selected;
|
||||
$(':checkbox').each(function() {
|
||||
this.checked = selected;
|
||||
$row = $(this.parentElement.parentElement);
|
||||
// Change color of selected/unselected
|
||||
(selected) ? that.makeDarkRow($row) : that.makeWhiteRow($row);
|
||||
});
|
||||
// Show the tools in menu
|
||||
this.checkTools();
|
||||
// this.checkTools();
|
||||
},
|
||||
|
||||
// Check checkbox on row itself or row checkbox click
|
||||
@@ -485,7 +153,7 @@ var FolderContentView = Backbone.View.extend({
|
||||
this.makeWhiteRow($row);
|
||||
}
|
||||
}
|
||||
this.checkTools();
|
||||
// this.checkTools();
|
||||
},
|
||||
|
||||
makeDarkRow: function($row){
|
||||
@@ -507,207 +175,56 @@ var FolderContentView = Backbone.View.extend({
|
||||
$row.find('span').removeClass('fa-file');
|
||||
},
|
||||
|
||||
// show toolbar in case something is selected
|
||||
checkTools : function(){
|
||||
var checkedValues = $('#folder_table').find(':checked');
|
||||
if(checkedValues.length > 0){
|
||||
$('#toolbtn_bulk_import').show();
|
||||
$('#toolbtn_dl').show();
|
||||
} else {
|
||||
$('#toolbtn_bulk_import').hide();
|
||||
$('#toolbtn_dl').hide();
|
||||
}
|
||||
},
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
// === TEMPLATES ====
|
||||
// MMMMMMMMMMMMMMMMMM
|
||||
|
||||
// show bulk import modal
|
||||
modalBulkImport : function(){
|
||||
var self = this;
|
||||
// fetch histories
|
||||
var histories = new mod_library_model.GalaxyHistories();
|
||||
histories.fetch({
|
||||
success: function (histories){
|
||||
// make modal
|
||||
var history_modal_tmpl = _.template(self.templateBulkImportInModal(), {histories : histories.models});
|
||||
self.modal = Galaxy.modal;
|
||||
self.modal.show({
|
||||
closing_events : true,
|
||||
title : 'Import into History',
|
||||
body : history_modal_tmpl,
|
||||
buttons : {
|
||||
'Import' : function() {self.importAllIntoHistory()},
|
||||
'Close' : function() {self.modal.hide();}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(){
|
||||
mod_toastr.error('An error occured :(');
|
||||
}
|
||||
});
|
||||
},
|
||||
// main template for folder browsing
|
||||
templateFolder : function (){
|
||||
var tmpl_array = [];
|
||||
|
||||
// import all selected datasets into history
|
||||
importAllIntoHistory : function (){
|
||||
//disable the button to prevent multiple submission
|
||||
this.modal.disableButton('Import');
|
||||
// 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(path, function(path_item) { %>');
|
||||
tmpl_array.push(' <% if (path_item[0] != 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 in this folder"><%- path_item[1] %></span></li>');
|
||||
tmpl_array.push(' <% } %>');
|
||||
tmpl_array.push(' <% }); %>');
|
||||
tmpl_array.push('</ol>');
|
||||
|
||||
var history_id = $("select[name=dataset_import_bulk] option:selected").val();
|
||||
var history_name = $("select[name=dataset_import_bulk] option:selected").text();
|
||||
// FOLDER CONTENT
|
||||
tmpl_array.push('<table id="folder_table" class="grid table table-condensed">');
|
||||
tmpl_array.push(' <thead>');
|
||||
tmpl_array.push(' <th class="button_heading"></th>');
|
||||
tmpl_array.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');
|
||||
tmpl_array.push(' <th>name</th>');
|
||||
tmpl_array.push(' <th>data type</th>');
|
||||
tmpl_array.push(' <th>size</th>');
|
||||
tmpl_array.push(' <th>date (UTC)</th>');
|
||||
tmpl_array.push(' </thead>');
|
||||
tmpl_array.push(' <tbody id="folder_list_body">');
|
||||
tmpl_array.push(' <tr>');
|
||||
tmpl_array.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>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' </tr>');
|
||||
|
||||
var dataset_ids = [];
|
||||
$('#folder_table').find(':checked').each(function(){
|
||||
if (this.parentElement.parentElement.id != '') {
|
||||
dataset_ids.push(this.parentElement.parentElement.id);
|
||||
}
|
||||
});
|
||||
var progress_bar_tmpl = _.template(this.templateProgressBar(), { history_name : history_name });
|
||||
$(this.modal.elMain).find('.modal-body').html(progress_bar_tmpl);
|
||||
tmpl_array.push(' </tbody>');
|
||||
tmpl_array.push('</table>');
|
||||
|
||||
// init the progress bar
|
||||
var progressStep = 100 / dataset_ids.length;
|
||||
this.initProgress(progressStep);
|
||||
|
||||
// prepare the dataset objects to be imported
|
||||
var datasets_to_import = [];
|
||||
for (var i = dataset_ids.length - 1; i >= 0; i--) {
|
||||
library_dataset_id = dataset_ids[i];
|
||||
var historyItem = new mod_library_model.HistoryItem();
|
||||
var self = this;
|
||||
historyItem.url = historyItem.urlRoot + history_id + '/contents';
|
||||
historyItem.content = library_dataset_id;
|
||||
historyItem.source = 'library';
|
||||
datasets_to_import.push(historyItem);
|
||||
};
|
||||
|
||||
// call the recursive function to call ajax one after each other (request FIFO queue)
|
||||
this.chainCall(datasets_to_import);
|
||||
},
|
||||
|
||||
chainCall: function(history_item_set){
|
||||
var self = this;
|
||||
var popped_item = history_item_set.pop();
|
||||
if (typeof popped_item === "undefined") {
|
||||
mod_toastr.success('All datasets imported');
|
||||
this.modal.hide();
|
||||
return
|
||||
}
|
||||
var promise = $.when(popped_item.save({content: popped_item.content, source: popped_item.source})).done(function(a1){
|
||||
self.updateProgress();
|
||||
// responses.push(a1);
|
||||
self.chainCall(history_item_set);
|
||||
});
|
||||
},
|
||||
|
||||
initProgress: function(progressStep){
|
||||
this.progress = 0;
|
||||
this.progressStep = progressStep;
|
||||
},
|
||||
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 selected datasets
|
||||
download : function(folder_id, format){
|
||||
var dataset_ids = [];
|
||||
$('#folder_table').find(':checked').each(function(){
|
||||
if (this.parentElement.parentElement.id != '') {
|
||||
dataset_ids.push(this.parentElement.parentElement.id);
|
||||
}
|
||||
});
|
||||
|
||||
var url = '/api/libraries/datasets/download/' + format;
|
||||
var data = {'ldda_ids' : dataset_ids};
|
||||
this.processDownload(url, data, 'get');
|
||||
},
|
||||
|
||||
// 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');
|
||||
};
|
||||
},
|
||||
|
||||
// shows modal for creating folder
|
||||
createFolderFromModal: function(){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// create modal
|
||||
var self = this;
|
||||
this.modal = Galaxy.modal;
|
||||
this.modal.show({
|
||||
closing_events : true,
|
||||
title : 'Create New Folder',
|
||||
body : this.templateNewFolderInModal(),
|
||||
buttons : {
|
||||
'Create' : function() {self.create_new_folder_event()},
|
||||
'Close' : function() {self.modal.hide(); self.modal = null;}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// create the new folder from modal
|
||||
create_new_folder_event: function(){
|
||||
var folderDetails = this.serialize_new_folder();
|
||||
if (this.validate_new_folder(folderDetails)){
|
||||
var folder = new mod_library_model.FolderAsModel();
|
||||
|
||||
url_items = Backbone.history.fragment.split('/');
|
||||
current_folder_id = url_items[url_items.length-1];
|
||||
folder.url = folder.urlRoot + '/' + current_folder_id ;
|
||||
|
||||
var self = this;
|
||||
folder.save(folderDetails, {
|
||||
success: function (folder) {
|
||||
self.modal.hide();
|
||||
mod_toastr.success('Folder created');
|
||||
self.render({id: current_folder_id});
|
||||
},
|
||||
error: function(){
|
||||
mod_toastr.error('An error occured :(');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mod_toastr.error('Folder\'s name is missing');
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// serialize data from the form
|
||||
serialize_new_folder : function(){
|
||||
return {
|
||||
name: $("input[name='Name']").val(),
|
||||
description: $("input[name='Description']").val()
|
||||
};
|
||||
},
|
||||
|
||||
// validate new library info
|
||||
validate_new_folder: function(folderDetails){
|
||||
return folderDetails.name !== '';
|
||||
return _.template(tmpl_array.join(''));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// return
|
||||
return {
|
||||
FolderContentView: FolderContentView
|
||||
FolderListView: FolderListView
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
// dependencies
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"utils/utils",
|
||||
"libs/toastr",
|
||||
"mvc/library/library-model"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_library_model) {
|
||||
|
||||
// galaxy library row view
|
||||
var FolderRowView = Backbone.View.extend({
|
||||
// last selected history in modal for UX
|
||||
lastSelectedHistory: '',
|
||||
|
||||
events: {
|
||||
'click .library-dataset' : 'showDatasetDetails'
|
||||
},
|
||||
|
||||
options: {
|
||||
type: null
|
||||
},
|
||||
|
||||
initialize : function(folder_item){
|
||||
this.render(folder_item);
|
||||
},
|
||||
|
||||
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';
|
||||
template = this.templateRowFolder();
|
||||
} else {
|
||||
this.options.type = 'file';
|
||||
template = this.templateRowFile();
|
||||
}
|
||||
this.setElement(template({content_item:folder_item}));
|
||||
this.$el.show();
|
||||
return this;
|
||||
},
|
||||
|
||||
//show modal with current dataset info
|
||||
showDatasetDetails : function(event){
|
||||
// prevent default
|
||||
event.preventDefault();
|
||||
|
||||
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(){
|
||||
mod_toastr.error('An error occured during fetching histories:(');
|
||||
self.renderModalAfterFetch(item);
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(){
|
||||
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 : 'Dataset Details',
|
||||
body : template,
|
||||
buttons : {
|
||||
'Import' : function() { self.importCurrentIntoHistory(); },
|
||||
'Download' : function() { self.downloadCurrent(); },
|
||||
'Close' : function() { self.modal.hide(); }
|
||||
}
|
||||
});
|
||||
|
||||
$(".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';
|
||||
|
||||
// save the dataset into selected history
|
||||
historyItem.save({ content : library_dataset_id, source : 'library' }, { success : function(){
|
||||
mod_toastr.success('Dataset imported');
|
||||
//enable the buttons
|
||||
self.modal.enableButton('Import');
|
||||
self.modal.enableButton('Download');
|
||||
}, error : function(){
|
||||
mod_toastr.error('An error occured! Dataset not imported. Please try again.');
|
||||
//enable the buttons
|
||||
self.modal.enableButton('Import');
|
||||
self.modal.enableButton('Download');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
templateRowFolder: function() {
|
||||
tmpl_array = [];
|
||||
|
||||
tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');
|
||||
tmpl_array.push(' <td>');
|
||||
tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');
|
||||
tmpl_array.push(' </td>');
|
||||
tmpl_array.push(' <td></td>');
|
||||
tmpl_array.push(' <td>');
|
||||
tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');
|
||||
tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>'); // 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><%= _.escape(content_item.get("item_count")) %> item(s)</td>'); // size
|
||||
tmpl_array.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>'); // time updated
|
||||
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="#" 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("time_updated")) %></td>'); // time updated
|
||||
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('');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return {
|
||||
FolderRowView: FolderRowView
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,320 @@
|
||||
// dependencies
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"utils/utils",
|
||||
"libs/toastr",
|
||||
"mvc/library/library-model"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_library_model) {
|
||||
|
||||
var FolderToolbarView = Backbone.View.extend({
|
||||
el: '#center',
|
||||
|
||||
events: {
|
||||
'click #toolbtn_create_folder' : 'createFolderFromModal',
|
||||
'click #toolbtn_bulk_import' : 'modalBulkImport'
|
||||
},
|
||||
|
||||
defaults: {
|
||||
'can_add_library_item' : false,
|
||||
'contains_file' : false
|
||||
},
|
||||
|
||||
modal : null,
|
||||
|
||||
initialize: function(options){
|
||||
this.options = _.defaults(options || {}, this.defaults);
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function(options){
|
||||
this.options = _.extend(this.options, options);
|
||||
var toolbar_template = this.templateToolBar();
|
||||
var is_admin = Galaxy.currUser.isAdmin();
|
||||
this.$el.html(toolbar_template({id: this.options.id, admin_user: is_admin}));
|
||||
},
|
||||
|
||||
configureElements: function(options){
|
||||
this.options = _.extend(this.options, options);
|
||||
if (this.options.can_add_library_item === true){
|
||||
$('#toolbtn_create_folder').show();
|
||||
$('#toolbtn_upload_files').show();
|
||||
}
|
||||
if (this.options.contains_file === true){
|
||||
$('#toolbtn_bulk_import').show();
|
||||
$('#toolbtn_dl').show();
|
||||
}
|
||||
this.$el.find('[data-toggle]').tooltip();
|
||||
},
|
||||
|
||||
// shows modal for creating folder
|
||||
createFolderFromModal: function(){
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// create modal
|
||||
var self = this;
|
||||
var template = this.templateNewFolderInModal();
|
||||
this.modal = Galaxy.modal;
|
||||
this.modal.show({
|
||||
closing_events : true,
|
||||
title : 'Create New Folder',
|
||||
body : template(),
|
||||
buttons : {
|
||||
'Create' : function() {self.create_new_folder_event();},
|
||||
'Close' : function() {self.modal.hide(); self.modal = null;}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// create the new folder from modal
|
||||
create_new_folder_event: function(){
|
||||
var folderDetails = this.serialize_new_folder();
|
||||
if (this.validate_new_folder(folderDetails)){
|
||||
var folder = new mod_library_model.FolderAsModel();
|
||||
url_items = Backbone.history.fragment.split('/');
|
||||
current_folder_id = url_items[url_items.length-1];
|
||||
folder.url = folder.urlRoot + '/' + current_folder_id ;
|
||||
|
||||
var self = this;
|
||||
folder.save(folderDetails, {
|
||||
success: function (folder) {
|
||||
self.modal.hide();
|
||||
mod_toastr.success('Folder created');
|
||||
Galaxy.libraries.folderListView.render({id: current_folder_id});
|
||||
},
|
||||
error: function(){
|
||||
mod_toastr.error('An error occured :(');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mod_toastr.error('Folder\'s name is missing');
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// serialize data from the modal
|
||||
serialize_new_folder : function(){
|
||||
return {
|
||||
name: $("input[name='Name']").val(),
|
||||
description: $("input[name='Description']").val()
|
||||
};
|
||||
},
|
||||
|
||||
// validate new folder info
|
||||
validate_new_folder: function(folderDetails){
|
||||
return folderDetails.name !== '';
|
||||
},
|
||||
|
||||
|
||||
// show bulk import modal
|
||||
modalBulkImport : function(){
|
||||
var checkedValues = $('#folder_table').find(':checked');
|
||||
if(checkedValues.length === 0){
|
||||
mod_toastr.info('You have to select some datasets first');
|
||||
} else {
|
||||
var self = this;
|
||||
// fetch histories
|
||||
var template = this.templateBulkImportInModal();
|
||||
var histories = new mod_library_model.GalaxyHistories();
|
||||
histories.fetch({
|
||||
success: function (histories){
|
||||
// make modal
|
||||
// var history_modal_tmpl = template({histories : histories.models});
|
||||
self.modal = Galaxy.modal;
|
||||
self.modal.show({
|
||||
closing_events : true,
|
||||
title : 'Import into History',
|
||||
body : template({histories : histories.models}),
|
||||
buttons : {
|
||||
'Import' : function() {self.importAllIntoHistory();},
|
||||
'Close' : function() {self.modal.hide();}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(){
|
||||
mod_toastr.error('An error occured :(');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// import all selected datasets into history
|
||||
importAllIntoHistory : function (){
|
||||
//disable the button to prevent multiple submission
|
||||
this.modal.disableButton('Import');
|
||||
|
||||
var history_id = $("select[name=dataset_import_bulk] option:selected").val();
|
||||
var history_name = $("select[name=dataset_import_bulk] option:selected").text();
|
||||
|
||||
var dataset_ids = [];
|
||||
$('#folder_table').find(':checked').each(function(){
|
||||
if (this.parentElement.parentElement.id !== '') {
|
||||
dataset_ids.push(this.parentElement.parentElement.id);
|
||||
}
|
||||
});
|
||||
var progress_bar_tmpl = this.templateProgressBar();
|
||||
$(this.modal.elMain).find('.modal-body').html(progress_bar_tmpl({ history_name : history_name }));
|
||||
|
||||
// init the progress bar
|
||||
var progressStep = 100 / dataset_ids.length;
|
||||
this.initProgress(progressStep);
|
||||
|
||||
// prepare the dataset objects to be imported
|
||||
var datasets_to_import = [];
|
||||
for (var i = dataset_ids.length - 1; i >= 0; i--) {
|
||||
library_dataset_id = dataset_ids[i];
|
||||
var historyItem = new mod_library_model.HistoryItem();
|
||||
var self = this;
|
||||
historyItem.url = historyItem.urlRoot + history_id + '/contents';
|
||||
historyItem.content = library_dataset_id;
|
||||
historyItem.source = 'library';
|
||||
datasets_to_import.push(historyItem);
|
||||
}
|
||||
// call the recursive function to call ajax one after each other (request FIFO queue)
|
||||
this.chainCall(datasets_to_import);
|
||||
},
|
||||
|
||||
chainCall: function(history_item_set){
|
||||
var self = this;
|
||||
var popped_item = history_item_set.pop();
|
||||
if (typeof popped_item === "undefined") {
|
||||
mod_toastr.success('All datasets imported');
|
||||
this.modal.hide();
|
||||
return;
|
||||
}
|
||||
var promise = $.when(popped_item.save({content: popped_item.content, source: popped_item.source})).done(function(a1){
|
||||
self.updateProgress();
|
||||
self.chainCall(history_item_set);
|
||||
});
|
||||
},
|
||||
|
||||
initProgress: function(progressStep){
|
||||
this.progress = 0;
|
||||
this.progressStep = progressStep;
|
||||
},
|
||||
|
||||
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 selected datasets
|
||||
download : function(folder_id, format){
|
||||
var dataset_ids = [];
|
||||
$('#folder_table').find(':checked').each(function(){
|
||||
if (this.parentElement.parentElement.id !== '') {
|
||||
dataset_ids.push(this.parentElement.parentElement.id);
|
||||
}
|
||||
});
|
||||
|
||||
var url = '/api/libraries/datasets/download/' + format;
|
||||
var data = {'ldda_ids' : dataset_ids};
|
||||
this.processDownload(url, data, 'get');
|
||||
},
|
||||
|
||||
// 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');
|
||||
}
|
||||
},
|
||||
|
||||
templateToolBar: function(){
|
||||
tmpl_array = [];
|
||||
|
||||
// CONTAINER
|
||||
tmpl_array.push('<div class="library_style_container">');
|
||||
tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-folders" target="_blank">Trello</a>.</h3>');
|
||||
// TOOLBAR
|
||||
tmpl_array.push('<div id="library_folder_toolbar" >');
|
||||
tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span> <span class="fa fa-folder-close"></span> folder</button>');
|
||||
tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Upload Files to Current Folder" id="toolbtn_upload_files" class="primary-button" type="button" style="display:none;"><span class="fa fa-upload"></span> upload</button>');
|
||||
tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button" 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" style="margin-left: 0.5em; display:none; ">');
|
||||
tmpl_array.push(' <button title="Download selected datasets" 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(' </div>');
|
||||
tmpl_array.push(' <div id="folder_items_element">');
|
||||
// library items will append here
|
||||
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 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_bulk" name="dataset_import_bulk" 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(''));
|
||||
},
|
||||
|
||||
templateProgressBar : function (){
|
||||
var tmpl_array = [];
|
||||
|
||||
tmpl_array.push('<div class="import_text">');
|
||||
tmpl_array.push('Importing selected datasets to history <b><%= _.escape(history_name) %></b>');
|
||||
tmpl_array.push('</div>');
|
||||
tmpl_array.push('<div class="progress">');
|
||||
tmpl_array.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');
|
||||
tmpl_array.push(' <span class="completion_span">0% Complete</span>');
|
||||
tmpl_array.push(' </div>');
|
||||
tmpl_array.push('</div>');
|
||||
tmpl_array.push('');
|
||||
|
||||
return _.template(tmpl_array.join(''));
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
FolderToolbarView: FolderToolbarView
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,14 +1,14 @@
|
||||
// dependencies
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"mvc/base-mvc",
|
||||
"mvc/base-mvc",
|
||||
"utils/utils",
|
||||
"libs/toastr",
|
||||
"mvc/library/library-model",
|
||||
"mvc/library/library-libraryrow-view"],
|
||||
"mvc/library/library-libraryrow-view"],
|
||||
function(mod_masthead,
|
||||
mod_baseMVC,
|
||||
mod_utils,
|
||||
mod_baseMVC,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_library_model,
|
||||
mod_library_libraryrow_view) {
|
||||
@@ -29,7 +29,8 @@ var LibraryListView = Backbone.View.extend({
|
||||
rowViews: {},
|
||||
|
||||
// initialize
|
||||
initialize : function(){
|
||||
initialize : function(options){
|
||||
this.options = _.defaults(this.options || {}, options);
|
||||
var viewContext = this;
|
||||
|
||||
this.rowViews = {};
|
||||
@@ -43,7 +44,7 @@ var LibraryListView = Backbone.View.extend({
|
||||
error: function(model, response){
|
||||
mod_toastr.error('An error occured. Please try again.');
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
/** Renders the libraries table either from the object's own collection,
|
||||
@@ -52,9 +53,8 @@ var LibraryListView = Backbone.View.extend({
|
||||
render: function (options) {
|
||||
var template = this.templateLibraryList();
|
||||
var libraries_to_render = null;
|
||||
var include_deleted = true;
|
||||
var include_deleted = Galaxy.libraries.preferences.get('with_deleted');
|
||||
var models = null
|
||||
var models = null;
|
||||
if (typeof options !== 'undefined'){
|
||||
include_deleted = typeof options.with_deleted !== 'undefined' ? options.with_deleted : false;
|
||||
models = typeof options.models !== 'undefined' ? options.models : null;
|
||||
@@ -64,7 +64,7 @@ var LibraryListView = Backbone.View.extend({
|
||||
if (include_deleted){ // show all the libraries
|
||||
libraries_to_render = this.collection.models;
|
||||
} else{ // show only undeleted libraries
|
||||
libraries_to_render = this.collection.where({deleted: false});;
|
||||
libraries_to_render = this.collection.where({deleted: false});
|
||||
}
|
||||
} else if (models !== null){
|
||||
libraries_to_render = models;
|
||||
@@ -74,7 +74,9 @@ var LibraryListView = Backbone.View.extend({
|
||||
|
||||
this.$el.html(template({length: libraries_to_render.length, order: Galaxy.libraries.preferences.get('sort_order') }));
|
||||
|
||||
this.renderRows(libraries_to_render);
|
||||
if (libraries_to_render.length > 0){
|
||||
this.renderRows(libraries_to_render);
|
||||
}
|
||||
// initialize the library tooltips
|
||||
$("#center [data-toggle]").tooltip();
|
||||
// modification of upper DOM element to show scrollbars due to the #center element inheritance
|
||||
@@ -92,9 +94,9 @@ var LibraryListView = Backbone.View.extend({
|
||||
var rowView = new mod_library_libraryrow_view.LibraryRowView(library);
|
||||
this.$el.find('#library_list_body').append(rowView.el);
|
||||
// save new rowView to cache
|
||||
this.rowViews[library.get('id')] = rowView;
|
||||
this.rowViews[library.get('id')] = rowView;
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
sort_clicked : function(){
|
||||
@@ -115,17 +117,17 @@ var LibraryListView = Backbone.View.extend({
|
||||
if (order === 'asc'){
|
||||
// this.collection.sort_order = 'asc';
|
||||
this.collection.comparator = function(libraryA, libraryB){
|
||||
if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) return 1; // after
|
||||
if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) return -1; // before
|
||||
if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) {return 1;} // after
|
||||
if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) {return -1;} // before
|
||||
return 0; // equal
|
||||
}
|
||||
};
|
||||
} else if (order === 'desc'){
|
||||
// this.collection.sort_order = 'desc';
|
||||
this.collection.comparator = function(libraryA, libraryB){
|
||||
if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) return -1; // before
|
||||
if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) return 1; // after
|
||||
if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) {return -1;} // before
|
||||
if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) {return 1;} // after
|
||||
return 0; // equal
|
||||
}
|
||||
};
|
||||
}
|
||||
this.collection.sort();
|
||||
}
|
||||
@@ -140,7 +142,7 @@ var LibraryListView = Backbone.View.extend({
|
||||
|
||||
tmpl_array.push('<div class="library_container table-responsive">');
|
||||
tmpl_array.push('<% if(length === 0) { %>');
|
||||
tmpl_array.push("<div>I see no libraries. Why don't you create one?</div>");
|
||||
tmpl_array.push('<div>There are no libraries visible to you. If you expected some to show up please consult the <a href="https://wiki.galaxyproject.org/Admin/DataLibraries/LibrarySecurity">library security wikipage</a>.</div>');
|
||||
tmpl_array.push('<% } else{ %>');
|
||||
tmpl_array.push('<table class="grid table table-condensed">');
|
||||
tmpl_array.push(' <thead>');
|
||||
@@ -175,7 +177,7 @@ var LibraryListView = Backbone.View.extend({
|
||||
|
||||
redirectToHome: function(){
|
||||
window.location = '../';
|
||||
},
|
||||
},
|
||||
redirectToLogin: function(){
|
||||
window.location = '/user/login';
|
||||
},
|
||||
@@ -193,7 +195,7 @@ var LibraryListView = Backbone.View.extend({
|
||||
title : 'Create New Library',
|
||||
body : this.templateNewLibraryInModal(),
|
||||
buttons : {
|
||||
'Create' : function() {self.create_new_library_event()},
|
||||
'Create' : function() {self.create_new_library_event();},
|
||||
'Close' : function() {self.modal.hide();}
|
||||
}
|
||||
});
|
||||
@@ -245,7 +247,6 @@ var LibraryListView = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
|
||||
// return
|
||||
return {
|
||||
LibraryListView: LibraryListView
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// dependencies
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"galaxy.masthead",
|
||||
"utils/utils",
|
||||
"libs/toastr",
|
||||
"mvc/library/library-model"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
"mvc/library/library-model"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_library_model) {
|
||||
|
||||
@@ -39,7 +39,7 @@ var LibraryRowView = Backbone.View.extend({
|
||||
|
||||
render: function(library){
|
||||
if (typeof library === 'undefined'){
|
||||
var library = Galaxy.libraries.libraryListView.collection.get(this.$el.data('id'));
|
||||
library = Galaxy.libraries.libraryListView.collection.get(this.$el.data('id'));
|
||||
}
|
||||
this.prepareButtons(library);
|
||||
var tmpl = this.templateRow();
|
||||
@@ -51,7 +51,7 @@ var LibraryRowView = Backbone.View.extend({
|
||||
repaint: function(library){
|
||||
/* need to hide manually because of the element removal in setElement
|
||||
invoked in render() */
|
||||
$(".tooltip").hide();
|
||||
$(".tooltip").hide();
|
||||
/* we need to store the old element to be able to replace it with
|
||||
new one */
|
||||
var old_element = this.$el;
|
||||
@@ -83,13 +83,13 @@ var LibraryRowView = Backbone.View.extend({
|
||||
vis_config.undelete_library_btn = false;
|
||||
if (library.get('can_user_add') === true){
|
||||
vis_config.upload_library_btn = true;
|
||||
}
|
||||
}
|
||||
if (library.get('can_user_modify') === true){
|
||||
vis_config.edit_library_btn = true;
|
||||
}
|
||||
}
|
||||
if (library.get('can_user_manage') === true){
|
||||
vis_config.permission_library_btn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this.edit_mode === true){
|
||||
vis_config.upload_library_btn = false;
|
||||
@@ -136,7 +136,7 @@ var LibraryRowView = Backbone.View.extend({
|
||||
is_changed = true;
|
||||
} else{
|
||||
mod_toastr.warning('Library name has to be at least 3 characters long');
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ var LibraryRowView = Backbone.View.extend({
|
||||
Galaxy.libraries.libraryListView.collection.add(library);
|
||||
row_view.edit_mode = false;
|
||||
if (Galaxy.libraries.preferences.get('with_deleted') === false){
|
||||
$(".tooltip").hide();
|
||||
$('.tooltip').hide();
|
||||
row_view.$el.remove();
|
||||
} else if (Galaxy.libraries.preferences.get('with_deleted') === true){
|
||||
row_view.repaint(library);
|
||||
@@ -247,12 +247,11 @@ var LibraryRowView = Backbone.View.extend({
|
||||
tmpl_array.push(' </td>');
|
||||
tmpl_array.push(' </tr>');
|
||||
|
||||
return _.template(tmpl_array.join(''));
|
||||
return _.template(tmpl_array.join(''));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// return
|
||||
return {
|
||||
LibraryRowView: LibraryRowView
|
||||
};
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// dependencies
|
||||
define([
|
||||
"galaxy.masthead",
|
||||
"galaxy.masthead",
|
||||
"utils/utils",
|
||||
"libs/toastr",
|
||||
"mvc/library/library-model"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
"mvc/library/library-model"],
|
||||
function(mod_masthead,
|
||||
mod_utils,
|
||||
mod_toastr,
|
||||
mod_library_model) {
|
||||
|
||||
var ToolbarView = Backbone.View.extend({
|
||||
var LibraryToolbarView = Backbone.View.extend({
|
||||
el: '#center',
|
||||
|
||||
events: {
|
||||
events: {
|
||||
'click #create_new_library_btn' : 'delegate_modal',
|
||||
'click #include_deleted_chk' : 'check_include_deleted'
|
||||
},
|
||||
@@ -23,14 +23,16 @@ var ToolbarView = Backbone.View.extend({
|
||||
|
||||
render: function(){
|
||||
var toolbar_template = this.templateToolBar();
|
||||
this.$el.html(toolbar_template({admin_user: Galaxy.currUser.isAdmin(), anon_user: Galaxy.currUser.isAnonymous()}))
|
||||
var is_admin = Galaxy.currUser.isAdmin();
|
||||
var is_anonym = Galaxy.currUser.isAnonymous();
|
||||
this.$el.html(toolbar_template({admin_user: is_admin, anon_user: is_anonym}));
|
||||
if (Galaxy.currUser.isAdmin() === true){
|
||||
this.$el.find('#include_deleted_chk')[0].checked = Galaxy.libraries.preferences.get('with_deleted');
|
||||
}
|
||||
},
|
||||
|
||||
delegate_modal: function(event){
|
||||
// probably should refactor to have this functionality in this view, not in the library view
|
||||
// probably should refactor to have this functionality in this view, not in the library list view
|
||||
Galaxy.libraries.libraryListView.show_library_modal(event);
|
||||
},
|
||||
|
||||
@@ -48,7 +50,7 @@ var ToolbarView = Backbone.View.extend({
|
||||
templateToolBar: function(){
|
||||
tmpl_array = [];
|
||||
|
||||
tmpl_array.push('<div id="libraries_container" style="width: 90%; margin: auto; margin-top:2em; overflow: auto !important; ">');
|
||||
tmpl_array.push('<div class="library_style_container">');
|
||||
// TOOLBAR
|
||||
tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');
|
||||
tmpl_array.push(' <h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-folders" target="_blank">Trello</a>.</h3>');
|
||||
@@ -60,16 +62,16 @@ var ToolbarView = Backbone.View.extend({
|
||||
tmpl_array.push(' <% } %>');
|
||||
tmpl_array.push(' </div>');
|
||||
tmpl_array.push(' <div id="libraries_element">');
|
||||
// table with libraries will append here
|
||||
tmpl_array.push(' </div>');
|
||||
tmpl_array.push('</div>');
|
||||
|
||||
return _.template(tmpl_array.join(''));
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// return
|
||||
return {
|
||||
ToolbarView: ToolbarView
|
||||
LibraryToolbarView: LibraryToolbarView
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -66,16 +66,14 @@ define([], function() {
|
||||
var FolderContainer = Backbone.Model.extend({
|
||||
defaults : {
|
||||
folder : new Folder(),
|
||||
full_path : "unknown",
|
||||
urlRoot : "/api/folders/",
|
||||
id : "unknown"
|
||||
},
|
||||
parse : function(obj) {
|
||||
this.full_path = obj[0].full_path;
|
||||
// response is not a simple array, it contains metadata
|
||||
// this will update the inner collection
|
||||
this.get("folder").reset(obj[1].folder_contents);
|
||||
return obj;
|
||||
// response is not a simple array, it contains metadata
|
||||
// this will update the inner collection
|
||||
this.get("folder").reset(obj.folder_contents);
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ var ToolParameter = Backbone.Model.extend({
|
||||
num_samples: 5
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
initialize: function(options) {
|
||||
this.attributes.html = unescape(this.attributes.html);
|
||||
},
|
||||
|
||||
@@ -124,6 +124,8 @@ var Tool = Backbone.Model.extend({
|
||||
outputs: []
|
||||
},
|
||||
|
||||
urlRoot: galaxy_config.root + 'api/tools',
|
||||
|
||||
initialize: function(options) {
|
||||
|
||||
// Set parameters.
|
||||
@@ -133,7 +135,16 @@ var Tool = Backbone.Model.extend({
|
||||
})));
|
||||
},
|
||||
|
||||
urlRoot: galaxy_config.root + 'api/tools',
|
||||
/**
|
||||
*
|
||||
*/
|
||||
toJSON: function() {
|
||||
var rval = Backbone.Model.prototype.toJSON.call(this);
|
||||
|
||||
// Convert inputs to JSON manually.
|
||||
rval.inputs = this.get('inputs').map(function(i) { return i.toJSON(); });
|
||||
return rval;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes inputs of a particular type; this is useful because not all inputs can be handled by
|
||||
|
||||
@@ -1 +1 @@
|
||||
var library_router=null;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"],function(e,c,g,j,h,a,f,d){var k=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var i=j.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({toolbarView:null,libraryListView:null,library_router:null,folderContentView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new i({id:"global-lib-prefs"});this.library_router=new k();this.library_router.on("route:libraries",function(){Galaxy.libraries.toolbarView=new d.ToolbarView();Galaxy.libraries.libraryListView=new f.LibraryListView()});this.library_router.on("route:folder_content",function(l){if(!Galaxy.libraries.folderContentView){Galaxy.libraries.folderContentView=new a.FolderContentView()}Galaxy.libraries.folderContentView.render({id:l})});this.library_router.on("route:download",function(l,m){if($("#center").find(":checked").length===0){Galaxy.libraries.library_router.navigate("folders/"+l,{trigger:true,replace:true})}else{Galaxy.libraries.folderContentView.download(l,m);Galaxy.libraries.library_router.navigate("folders/"+l,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
|
||||
define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view"],function(e,c,g,k,h,a,f,d,i){var l=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var j=k.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,folderToolbarView:null,folderListView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new j({id:"global-lib-prefs"});this.library_router=new l();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new d.LibraryToolbarView();Galaxy.libraries.libraryListView=new f.LibraryListView()});this.library_router.on("route:folder_content",function(m){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($("#center").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})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(a,d,e,c){var b=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"delegate_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},render:function(){var f=this.templateToolBar();this.$el.html(f({admin_user:Galaxy.currUser.isAdmin(),anon_user:Galaxy.currUser.isAnonymous()}));if(Galaxy.currUser.isAdmin()===true){this.$el.find("#include_deleted_chk")[0].checked=Galaxy.libraries.preferences.get("with_deleted")}},delegate_modal:function(f){Galaxy.libraries.libraryListView.show_library_modal(f)},check_include_deleted:function(f){if(f.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 id="libraries_container" style="width: 90%; margin: auto; margin-top:2em; overflow: auto !important; ">');tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');tmpl_array.push(' <h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-folders" target="_blank">Trello</a>.</h3>');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(""))}});return{ToolbarView:b}});
|
||||
define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(a,c,d,b){var e=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"delegate_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},render:function(){var h=this.templateToolBar();var g=Galaxy.currUser.isAdmin();var f=Galaxy.currUser.isAnonymous();this.$el.html(h({admin_user:g,anon_user:f}));if(Galaxy.currUser.isAdmin()===true){this.$el.find("#include_deleted_chk")[0].checked=Galaxy.libraries.preferences.get("with_deleted")}},delegate_modal:function(f){Galaxy.libraries.libraryListView.show_library_modal(f)},check_include_deleted:function(f){if(f.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(' <h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-folders" target="_blank">Trello</a>.</h3>');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(""))}});return{LibraryToolbarView:e}});
|
||||
@@ -1 +1 @@
|
||||
define([],function(){var e=Backbone.Model.extend({urlRoot:"/api/libraries/",isVisible:function(k){var j=true;if((!show_delete)&&(this.get("deleted"))){j=false}return j}});var a=Backbone.Model.extend({urlRoot:"/api/folders"});var h=Backbone.Collection.extend({url:"/api/libraries",model:e,sort_key:"name",sort_order:null,initialize:function(j){j=j||{}},getVisible:function(k,l){l=l||[];var j=new h(this.filter(function(m){return m.isVisible(k)}));return j}});var f=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var c=Backbone.Collection.extend({model:f});var d=Backbone.Model.extend({defaults:{folder:new c(),full_path:"unknown",urlRoot:"/api/folders/",id:"unknown"},parse:function(j){this.full_path=j[0].full_path;this.get("folder").reset(j[1].folder_contents);return j}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var g=Backbone.Model.extend({url:"/api/histories/"});var i=Backbone.Collection.extend({url:"/api/histories",model:g});return{Library:e,FolderAsModel:a,Libraries:h,Item:f,Folder:c,FolderContainer:d,HistoryItem:b,GalaxyHistory:g,GalaxyHistories:i}});
|
||||
define([],function(){var e=Backbone.Model.extend({urlRoot:"/api/libraries/",isVisible:function(k){var j=true;if((!show_delete)&&(this.get("deleted"))){j=false}return j}});var a=Backbone.Model.extend({urlRoot:"/api/folders"});var h=Backbone.Collection.extend({url:"/api/libraries",model:e,sort_key:"name",sort_order:null,initialize:function(j){j=j||{}},getVisible:function(k,l){l=l||[];var j=new h(this.filter(function(m){return m.isVisible(k)}));return j}});var f=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var c=Backbone.Collection.extend({model:f});var d=Backbone.Model.extend({defaults:{folder:new c(),urlRoot:"/api/folders/",id:"unknown"},parse:function(j){this.get("folder").reset(j.folder_contents);return j}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var g=Backbone.Model.extend({url:"/api/histories/"});var i=Backbone.Collection.extend({url:"/api/histories",model:g});return{Library:e,FolderAsModel:a,Libraries:h,Item:f,Folder:c,FolderContainer:d,HistoryItem:b,GalaxyHistory:g,GalaxyHistories:i}});
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -304,6 +304,7 @@ var ConfigSettingCollectionView = Backbone.View.extend({
|
||||
});
|
||||
|
||||
return {
|
||||
ConfigSetting: ConfigSetting,
|
||||
ConfigSettingCollection: ConfigSettingCollection,
|
||||
ConfigSettingCollectionView: ConfigSettingCollectionView
|
||||
};
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
define([
|
||||
], function(){
|
||||
/*global window, jQuery, console */
|
||||
/*=============================================================================
|
||||
TODO:
|
||||
broken pipe due to onunload post in webkit, safari
|
||||
need to use persistence
|
||||
|
||||
=============================================================================*/
|
||||
/** @class MetricsLogger
|
||||
*
|
||||
* Object to cache, output, and post log/metric messages to the server.
|
||||
* Meant to be attached to the Galaxy object.
|
||||
*
|
||||
* Log from objects by either attaching logger directly:
|
||||
* panel.logger.metric( 'user dataset deletion', panel.user.id, hda.toJSON() )
|
||||
* or using the LoggableMixin or addLogging function:
|
||||
* MyBackboneModel.extend( LoggableMixin ).extend({ ... })
|
||||
* addLogging( MyBackboneModel, 'my-backbone-model' )
|
||||
*
|
||||
* Log from templates by calling directly from Galaxy object:
|
||||
* Galaxy.logger.metric( 'template loaded', { ownedByUser : true });
|
||||
*
|
||||
* If you attempt to log an un-serializable object (circular reference, window, etc.),
|
||||
* that entry will not be cached (or sent). If you set consoleLevel and consoleLogger
|
||||
* appropriately, a warning will be shown when this happens:
|
||||
* > panel.metric( 'something weird with window', { window : window })
|
||||
* !'Metrics logger could not stringify logArguments: ...'
|
||||
*/
|
||||
function MetricsLogger( options ){
|
||||
options = options || {};
|
||||
var self = this;
|
||||
|
||||
//TODO: this might be used if we store the logs in browser storage
|
||||
///** */
|
||||
//self.userId = options.userId || null;
|
||||
|
||||
/** the (optional) console to emit logs to */
|
||||
self.consoleLogger = options.consoleLogger || null;
|
||||
|
||||
self._init( options );
|
||||
return self;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------- defaults and constants
|
||||
// see: python std lib, logging
|
||||
MetricsLogger.ALL = 0;
|
||||
MetricsLogger.DEBUG = 10;
|
||||
MetricsLogger.INFO = 20;
|
||||
MetricsLogger.WARN = 30;
|
||||
MetricsLogger.ERROR = 40;
|
||||
// metrics levels here?
|
||||
//MetricsLogger.MinorEvent = 45;
|
||||
//MetricsLogger.MajorEvent = 50;
|
||||
MetricsLogger.METRIC = 50;
|
||||
MetricsLogger.NONE = 100;
|
||||
|
||||
/** default options - override these through the constructor */
|
||||
MetricsLogger.defaultOptions = {
|
||||
/** if an incoming message has a level >= this, it will be cached - can also be a string (e.g. 'debug') */
|
||||
logLevel : MetricsLogger.INFO,
|
||||
/** if an incoming message has a level >= this, it will be output to the console */
|
||||
consoleLevel : MetricsLogger.NONE,
|
||||
/** the default 'namespace' or label associated with an incoming message (if none is passed) */
|
||||
defaultNamespace : 'Galaxy',
|
||||
/** the prefix attached to client-side logs to distinguish them in the metrics db */
|
||||
clientPrefix : 'client.',
|
||||
|
||||
/** the maximum number of messages the cache should hold; if exceeded older messages are removed first */
|
||||
maxCacheSize : 3000,
|
||||
/** the number of messages accumulate before posting to the server; should be <= maxCacheSize */
|
||||
postSize : 1000,
|
||||
/** T/F whether to add a timestamp to incoming cached messages */
|
||||
addTime : true,
|
||||
|
||||
/** the relative url to post messages to */
|
||||
postUrl : '/api/metrics',
|
||||
|
||||
/** post when the page is unloaded? */// needs to be true if using the LoggingCache (for now)
|
||||
postOnUnload : true,
|
||||
|
||||
/** an (optional) function that should return an object; used to send additional data with the metrics */
|
||||
getPingData : undefined,
|
||||
/** an (optional) function that will handle the servers response after successfully posting messages */
|
||||
onServerResponse : undefined
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------- set up
|
||||
/** initialize the logger with options, set up instance vars and cache, and add onpageunload to window */
|
||||
MetricsLogger.prototype._init = function _init( options ){
|
||||
var self = this;
|
||||
self.options = {};
|
||||
for( var k in MetricsLogger.defaultOptions ){
|
||||
if( MetricsLogger.defaultOptions.hasOwnProperty( k ) ){
|
||||
self.options[ k ] = ( options.hasOwnProperty( k ) )?( options[ k ] ):( MetricsLogger.defaultOptions[ k ] );
|
||||
}
|
||||
}
|
||||
self.options.logLevel = self._parseLevel( self.options.logLevel );
|
||||
self.options.consoleLevel = self._parseLevel( self.options.consoleLevel );
|
||||
//self._emitToConsole( 'debug', 'MetricsLogger', 'MetricsLogger.options:', self.options );
|
||||
|
||||
self._sending = false;
|
||||
self._postSize = self.options.postSize;
|
||||
self._initCache();
|
||||
|
||||
// post the entire cache on unload (since LoggingCache isn't persistent ATM)
|
||||
if( self.options.postOnUnload ){
|
||||
self.onpageunload = function onpageunload( ev ){
|
||||
ev.preventDefault();
|
||||
self._postCache({ count: self.cache.length() });
|
||||
};
|
||||
window.addEventListener( 'unload', self.onpageunload );
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
/** initialize the cache */
|
||||
MetricsLogger.prototype._initCache = function _initCache(){
|
||||
this.cache = new LoggingCache({ maxSize : this.options.maxCacheSize });
|
||||
|
||||
};
|
||||
|
||||
/** return the numeric log level if level in 'none, debug, log, info, warn, error' */
|
||||
MetricsLogger.prototype._parseLevel = function _parseLevel( level ){
|
||||
var type = typeof level;
|
||||
if( type === 'number' ){ return level; }
|
||||
var upper = level.toUpperCase();
|
||||
if( type === 'string' && MetricsLogger.hasOwnProperty( upper ) ){
|
||||
return MetricsLogger[ upper ];
|
||||
}
|
||||
throw new Error( 'Unknown log level: ' + level );
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------- main entry point
|
||||
/** record a log/message's arguments to the cache and/or the console based on level and namespace */
|
||||
MetricsLogger.prototype.emit = function emit( level, namespace, logArguments ){
|
||||
//this._emitToConsole( 'debug', 'MetricsLogger', [ 'emit:', level, namespace, logArguments ]);
|
||||
var self = this;
|
||||
namespace = namespace || self.options.defaultNamespace;
|
||||
if( !level || !logArguments ){
|
||||
return self;
|
||||
}
|
||||
// add to cache if proper level
|
||||
//TODO: respect do not track?
|
||||
//if( !navigator.doNotTrack && level >= self.options.logLevel ){
|
||||
level = self._parseLevel( level );
|
||||
if( level >= self.options.logLevel ){
|
||||
self._addToCache( level, namespace, logArguments );
|
||||
}
|
||||
// also emit to consoleLogger if proper level for that
|
||||
if( self.consoleLogger && level >= self.options.consoleLevel ){
|
||||
self._emitToConsole( level, namespace, logArguments );
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------- cache
|
||||
/** add a message to the cache and if messages.length is high enough post them to the server */
|
||||
MetricsLogger.prototype._addToCache = function _addToCache( level, namespace, logArguments ){
|
||||
this._emitToConsole( 'debug', 'MetricsLogger',
|
||||
[ '_addToCache:', arguments, this.options.addTime, this.cache.length() ]);
|
||||
//this._emitToConsole( 'debug', 'MetricsLogger', [ '\t logArguments:', logArguments ]);
|
||||
var self = this;
|
||||
// try add to the cache and if we've got _postSize number of entries, attempt to post them to the server
|
||||
try {
|
||||
var newLength = self.cache.add( self._buildEntry( level, namespace, logArguments ) );
|
||||
if( newLength >= self._postSize ){
|
||||
self._postCache();
|
||||
}
|
||||
// discard entry if an error occurs, but warn if level set to do so
|
||||
} catch( err ){
|
||||
if( self.options.consoleLevel <= MetricsLogger.WARN ){
|
||||
console.warn( 'Metrics logger could not stringify logArguments:', namespace, logArguments );
|
||||
console.error( err );
|
||||
}
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
/** build a log cache entry object from the given level, namespace, and arguments (optionally adding timestamp */
|
||||
MetricsLogger.prototype._buildEntry = function _buildEntry( level, namespace, logArguments ){
|
||||
this._emitToConsole( 'debug', 'MetricsLogger', [ '_buildEntry:', arguments ]);
|
||||
var entry = {
|
||||
level : level,
|
||||
namespace : this.options.clientPrefix + namespace,
|
||||
args : logArguments
|
||||
};
|
||||
if( this.options.addTime ){
|
||||
entry.time = new Date().toISOString();
|
||||
}
|
||||
return entry;
|
||||
};
|
||||
|
||||
/** post _postSize messages from the cache to the server, removing them if successful
|
||||
* if the post fails, wait until maxCacheSize is accumulated instead and try again then
|
||||
* in addition to the messages from the cache ('metrics'), any info from getPingData (if set) will be sent
|
||||
* onServerResponse will be called (if set) with any response from the server
|
||||
*/
|
||||
MetricsLogger.prototype._postCache = function _postCache( options ){
|
||||
options = options || {};
|
||||
this._emitToConsole( 'info', 'MetricsLogger', [ '_postCache', options, this._postSize ]);
|
||||
//TODO: remove jq dependence
|
||||
|
||||
// short circuit if we're already sending
|
||||
if( !this.options.postUrl || this._sending ){
|
||||
return jQuery.when({});
|
||||
}
|
||||
|
||||
var self = this,
|
||||
postSize = options.count || self._postSize,
|
||||
// do not splice - remove after *successful* post
|
||||
entries = self.cache.get( postSize ),
|
||||
entriesLength = entries.length,
|
||||
// use the optional getPingData to add any extra info we may want to send
|
||||
postData = ( typeof self.options.getPingData === 'function' )?( self.options.getPingData() ):( {} );
|
||||
//console.debug( postSize, entriesLength );
|
||||
|
||||
// add the metrics and send
|
||||
postData.metrics = self._preprocessCache( entries );
|
||||
self._sending = true;
|
||||
return jQuery.post( self.options.postUrl, postData )
|
||||
.always( function(){
|
||||
self._sending = false;
|
||||
})
|
||||
.fail( function(){
|
||||
// if we failed the previous time, set the next post target to the max num of entries
|
||||
self._postSize = self.options.maxCacheSize;
|
||||
})
|
||||
.done( function( response ){
|
||||
if( typeof self.options.onServerResponse === 'function' ){
|
||||
self.options.onServerResponse( response );
|
||||
}
|
||||
// only remove if post successful
|
||||
self.cache.remove( entriesLength );
|
||||
console.debug( 'removed entries:', entriesLength, 'size now:', self.cache.length() );
|
||||
// if we succeeded, reset the post target to the normal num of entries
|
||||
self._postSize = self.options.postSize;
|
||||
});
|
||||
// return the xhr promise
|
||||
};
|
||||
|
||||
/** Preprocess a number of cache entries for sending to the server (stringification) */
|
||||
MetricsLogger.prototype._preprocessCache = function _preprocessCache( entries ){
|
||||
return [ '[', ( entries.join( ',\n' ) ), ']' ].join( '\n' );
|
||||
//return [ '[', ( entries.join( ',' ) ), ']' ].join( '' );
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------- console
|
||||
/** output message to console based on level and consoleLogger type */
|
||||
MetricsLogger.prototype._emitToConsole = function _emitToConsole( level, namespace, logArguments ){
|
||||
//console.debug( '_emitToConsole:', level, namespace, logArguments );
|
||||
var self = this;
|
||||
if( !self.consoleLogger ){ return self; }
|
||||
|
||||
var args = Array.prototype.slice.call( logArguments, 0 );
|
||||
args.unshift( namespace );
|
||||
//TODO: script location and/or source maps?
|
||||
//TODO: branch on navigator.userAgent == AIIEEE - it only has log
|
||||
if( level >= MetricsLogger.METRIC && typeof( self.consoleLogger.info ) === 'function' ){
|
||||
return self.consoleLogger.info.apply( self.consoleLogger, args );
|
||||
|
||||
} else if( level >= MetricsLogger.ERROR && typeof( self.consoleLogger.error ) === 'function' ){
|
||||
return self.consoleLogger.error.apply( self.consoleLogger, args );
|
||||
} else if( level >= MetricsLogger.WARN && typeof( self.consoleLogger.warn ) === 'function' ){
|
||||
self.consoleLogger.warn.apply( self.consoleLogger, args );
|
||||
} else if( level >= MetricsLogger.INFO && typeof( self.consoleLogger.info ) === 'function' ){
|
||||
self.consoleLogger.info.apply( self.consoleLogger, args );
|
||||
} else if( level >= MetricsLogger.DEBUG && typeof( self.consoleLogger.debug ) === 'function' ){
|
||||
self.consoleLogger.debug.apply( self.consoleLogger, args );
|
||||
} else if( typeof( self.consoleLogger.log ) === 'function' ){
|
||||
self.consoleLogger.log.apply( self.consoleLogger, args );
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------- shortcuts
|
||||
// generic functions when logging from non-namespaced object (e.g. templates)
|
||||
/** debug to default namespace */
|
||||
MetricsLogger.prototype.debug = function debug(){
|
||||
this.emit( MetricsLogger.DEBUG, this.options.defaultNamespace, arguments );
|
||||
};
|
||||
|
||||
/** log to default namespace */
|
||||
MetricsLogger.prototype.log = function log(){
|
||||
this.emit( 1, this.options.defaultNamespace, arguments );
|
||||
};
|
||||
|
||||
/** info to default namespace */
|
||||
MetricsLogger.prototype.info = function info(){
|
||||
this.emit( MetricsLogger.INFO, this.options.defaultNamespace, arguments );
|
||||
};
|
||||
|
||||
/** warn to default namespace */
|
||||
MetricsLogger.prototype.warn = function warn(){
|
||||
this.emit( MetricsLogger.WARN, this.options.defaultNamespace, arguments );
|
||||
};
|
||||
|
||||
/** error to default namespace */
|
||||
MetricsLogger.prototype.error = function error(){
|
||||
this.emit( MetricsLogger.ERROR, this.options.defaultNamespace, arguments );
|
||||
};
|
||||
|
||||
/** metric to default namespace */
|
||||
MetricsLogger.prototype.metric = function metric(){
|
||||
this.emit( MetricsLogger.METRIC, this.options.defaultNamespace, arguments );
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
/** @class LoggingCache
|
||||
* Simple implementation of cache wrapping an array.
|
||||
*
|
||||
* Formats an entry before it's cached and only keeps options.maxSize number
|
||||
* of entries. Older entries are deleted first.
|
||||
*/
|
||||
function LoggingCache( options ){
|
||||
var self = this;
|
||||
self._cache = [];
|
||||
return self._init( options || {} );
|
||||
}
|
||||
|
||||
/** default options */
|
||||
LoggingCache.defaultOptions = {
|
||||
/** maximum number of entries to keep before discarding oldest */
|
||||
maxSize : 5000
|
||||
};
|
||||
|
||||
/** initialize with options */
|
||||
LoggingCache.prototype._init = function _init( options ){
|
||||
this.maxSize = options.maxSize || LoggingCache.defaultOptions.maxSize;
|
||||
return this;
|
||||
};
|
||||
|
||||
/** add an entry to the cache, removing the oldest beforehand if size >= maxSize */
|
||||
LoggingCache.prototype.add = function add( entry ){
|
||||
var self = this,
|
||||
overage = ( self.length() + 1 ) - self.maxSize;
|
||||
if( overage > 0 ){
|
||||
self.remove( overage );
|
||||
}
|
||||
self._cache.push( self._preprocessEntry( entry ) );
|
||||
return self.length();
|
||||
};
|
||||
|
||||
/** process the entry before caching */
|
||||
LoggingCache.prototype._preprocessEntry = function _preprocessEntry( entry ){
|
||||
return JSON.stringify( entry );
|
||||
};
|
||||
|
||||
/** return the length --- oh, getters where are you? */
|
||||
LoggingCache.prototype.length = function length(){
|
||||
return this._cache.length;
|
||||
};
|
||||
|
||||
/** get count number of entries starting with the oldest */
|
||||
LoggingCache.prototype.get = function get( count ){
|
||||
return this._cache.slice( 0, count );
|
||||
};
|
||||
|
||||
/** remove count number of entries starting with the oldest */
|
||||
LoggingCache.prototype.remove = function remove( count ){
|
||||
return this._cache.splice( 0, count );
|
||||
};
|
||||
|
||||
/** stringify count number of entries (but do not remove) */
|
||||
LoggingCache.prototype.stringify = function stringify( count ){
|
||||
return [ '[', ( this.get( count ).join( ',\n' ) ), ']' ].join( '\n' );
|
||||
};
|
||||
|
||||
/** outputs entire cache to console */
|
||||
LoggingCache.prototype.print = function print(){
|
||||
// popup? (really, carl? a popup?) - easier to copy/paste
|
||||
this._cache.forEach( function( entry ){
|
||||
console.log( entry );
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
return {
|
||||
MetricsLogger : MetricsLogger
|
||||
};
|
||||
});
|
||||
@@ -3,8 +3,8 @@
|
||||
* genomic visualization.
|
||||
*/
|
||||
|
||||
define(["libs/underscore", "libs/d3", "viz/trackster/util", "viz/visualization", "viz/trackster/tracks", "mvc/tools", "mvc/data"],
|
||||
function(_, d3, util, visualization, tracks, tools, data) {
|
||||
define(["libs/underscore", "libs/d3", "viz/trackster/util", "viz/visualization", "viz/trackster/tracks", "mvc/tools", "mvc/data", "utils/config"],
|
||||
function(_, d3, util, visualization, tracks, tools, data, config) {
|
||||
|
||||
/**
|
||||
* A collection of tool input settings. Object is useful for keeping a list of settings
|
||||
@@ -257,7 +257,7 @@ var SweepsterTrack = Backbone.Model.extend({
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
this.set('regions', new visualization.GenomeRegionCollection(options.regions));
|
||||
this.set('regions', options.regions);
|
||||
if (options.track) {
|
||||
// FIXME: find a better way to deal with needed URLs:
|
||||
var track_config = _.extend({
|
||||
@@ -310,12 +310,12 @@ var SweepsterVisualization = visualization.Visualization.extend({
|
||||
this.set('dataset', new data.Dataset(options.dataset));
|
||||
this.set('tool', new tools.Tool(options.tool));
|
||||
this.set('regions', new visualization.GenomeRegionCollection(options.regions));
|
||||
this.set('tracks', new SweepsterTrackCollection(options.tracks));
|
||||
this.set('tracks', new TrackCollection(options.tracks));
|
||||
|
||||
var tool_with_samplable_inputs = this.get('tool');
|
||||
this.set('tool_with_samplable_inputs', tool_with_samplable_inputs);
|
||||
// Remove complex parameters for now.
|
||||
tool_with_samplable_inputs.remove_inputs( [ 'data', 'hidden_data', 'conditional' ] );
|
||||
tool_with_samplable_inputs.remove_inputs( [ 'data', 'hidden_data', 'conditional', 'text' ] );
|
||||
|
||||
this.set('parameter_tree', new ToolParameterTree({
|
||||
tool: tool_with_samplable_inputs,
|
||||
@@ -430,7 +430,7 @@ var SweepsterTrackView = Backbone.View.extend({
|
||||
var canvas = self.canvas_manager.new_canvas();
|
||||
canvas.width = self.TILE_LEN;
|
||||
canvas.height = track.get_canvas_height(tile_data, mode, w_scale, canvas.width);
|
||||
track.draw_tile(tile_data, canvas.getContext('2d'), mode, resolution, region, w_scale);
|
||||
track.draw_tile(tile_data, canvas.getContext('2d'), mode, region, w_scale);
|
||||
$(tile_containers[index]).empty().append(canvas);
|
||||
});
|
||||
});
|
||||
@@ -680,8 +680,18 @@ var SweepsterVisualizationView = Backbone.View.extend({
|
||||
});
|
||||
|
||||
// Set block, reverse strand block colors; these colors will be used for all tracks.
|
||||
this.block_color = util.get_random_color();
|
||||
this.reverse_strand_color = util.get_random_color( [ this.block_color, "#ffffff" ] );
|
||||
this.config = config.ConfigSettingCollection.from_models_and_saved_values(
|
||||
[
|
||||
{ key: 'name', label: 'Name', type: 'text', default_value: '' },
|
||||
{ key: 'a_color', label: 'A Color', type: 'color', default_value: "#FF0000" },
|
||||
{ key: 'c_color', label: 'C Color', type: 'color', default_value: "#00FF00" },
|
||||
{ key: 'g_color', label: 'G Color', type: 'color', default_value: "#0000FF" },
|
||||
{ key: 't_color', label: 'T Color', type: 'color', default_value: "#FF00FF" },
|
||||
{ key: 'n_color', label: 'N Color', type: 'color', default_value: "#AAAAAA" },
|
||||
{ key: 'block_color', label: 'Block color', type: 'color' },
|
||||
{ key: 'reverse_strand_color', label: 'Antisense strand color', type: 'color' },
|
||||
], {}
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@@ -792,6 +802,11 @@ var SweepsterVisualizationView = Backbone.View.extend({
|
||||
$("#right .unified-panel-header-inner").append(menu.$el);
|
||||
},
|
||||
|
||||
get_base_color: function(base) {
|
||||
return this.config.get_value(base.toLowerCase() + '_color') ||
|
||||
this.config.get_value('n_color');
|
||||
},
|
||||
|
||||
run_tool_on_dataset: function(settings) {
|
||||
var tool = this.model.get('tool'),
|
||||
tool_name = tool.get('name'),
|
||||
@@ -904,14 +919,12 @@ var SweepsterVisualizationView = Backbone.View.extend({
|
||||
// the tool parameters and parameter tree.
|
||||
track_config.tool = null;
|
||||
|
||||
track_config.prefs = self.config.to_key_value_dict();
|
||||
|
||||
// Create and add track for output dataset.
|
||||
var track_obj = tracks.object_from_template(track_config, self, null);
|
||||
track_obj.init_for_tool_data();
|
||||
|
||||
// Set track block colors.
|
||||
track_obj.prefs.block_color = self.block_color;
|
||||
track_obj.prefs.reverse_strand_color = self.reverse_strand_color;
|
||||
|
||||
pm_track.set('track', track_obj);
|
||||
});
|
||||
}, index * 10000);
|
||||
|
||||
@@ -2243,7 +2243,7 @@ extend(Track.prototype, Drawable.prototype, {
|
||||
on_click_fn: function(track) {
|
||||
var template =
|
||||
'<strong>Tool</strong>: <%= track.tool.get("name") %><br/>' +
|
||||
'<strong>Dataset</strong>: <%= track.config.get("name") %><br/>' +
|
||||
'<strong>Dataset</strong>: <%= track.config.get_value("name") %><br/>' +
|
||||
'<strong>Region(s)</strong>: <select name="regions">' +
|
||||
'<option value="cur">current viewing area</option>' +
|
||||
'<option value="bookmarks">bookmarks</option>' +
|
||||
|
||||
@@ -1299,6 +1299,7 @@ td.right-center{vertical-align:middle !important;text-align:right}
|
||||
.library_table td{border-top:1px solid #5f6990 !important}
|
||||
.library_table th{border-bottom:2px solid #5f6990 !important}
|
||||
.library_table a{color:#0A143D}.library_table a:hover{color:maroon}
|
||||
.library_style_container{width:95%;margin:auto;margin-top:2em;overflow:auto !important}
|
||||
tr.light td{background-color:white;color:black}
|
||||
tr.light:hover td{background-color:#f5e8cc}
|
||||
tr.dark td{background-color:#d6b161;color:white}
|
||||
|
||||
@@ -10,6 +10,7 @@ td.right-center{vertical-align:middle !important;text-align:right}
|
||||
.library_table td{border-top:1px solid #5f6990 !important}
|
||||
.library_table th{border-bottom:2px solid #5f6990 !important}
|
||||
.library_table a{color:#0A143D}.library_table a:hover{color:maroon}
|
||||
.library_style_container{width:95%;margin:auto;margin-top:2em;overflow:auto !important}
|
||||
tr.light td{background-color:white;color:black}
|
||||
tr.light:hover td{background-color:#f5e8cc}
|
||||
tr.dark td{background-color:#d6b161;color:white}
|
||||
|
||||
@@ -49,6 +49,12 @@ td.right-center{
|
||||
}
|
||||
}
|
||||
}
|
||||
.library_style_container{
|
||||
width: 95%;
|
||||
margin: auto;
|
||||
margin-top:2em;
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
tr.light td
|
||||
{
|
||||
|
||||
@@ -378,3 +378,10 @@
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
%if tool.tool_shed_repository:
|
||||
<% tool_url = tool.tool_shed_repository.get_sharable_url( tool.app ) %>
|
||||
%if tool_url:
|
||||
<br/>
|
||||
${ render_msg( 'This tool was installed from a ToolShed, you may be able to find additional information by following this link: <a href="%s" target="_blank">%s</a>' % ( tool_url, tool_url ), 'info' ) }
|
||||
%endif
|
||||
%endif
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<%def name="render_multiple_heads_message( heads )">
|
||||
<div class="warningmessage">
|
||||
<%
|
||||
from tool_shed.util.shed_util_common import get_revision_label_from_ctx
|
||||
from tool_shed.util.hg_util import get_revision_label_from_ctx
|
||||
heads_str = ''
|
||||
for ctx in heads:
|
||||
heads_str += '%s<br/>' % get_revision_label_from_ctx( ctx, include_date=True )
|
||||
|
||||
@@ -49,7 +49,7 @@ ${render_tool_shed_repository_actions( repository=repository )}
|
||||
%endif
|
||||
<div class="toolForm">
|
||||
<%
|
||||
from tool_shed.util.shed_util_common import get_readable_ctx_date
|
||||
from tool_shed.util.hg_util import get_readable_ctx_date
|
||||
changeset_revision_date = get_readable_ctx_date( ctx )
|
||||
if can_download:
|
||||
title_str = 'Changeset <b>%s:%s</b> <i>(%s)</i>' % ( ctx.rev(), ctx, changeset_revision_date )
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<!-- Minimal outline test page for a requirejs+qunit testing setup,
|
||||
test environment is bootstrapped in test-common.js -->
|
||||
<html>
|
||||
<head>
|
||||
<script data-main="../test-common" src="../scripts/libs/require.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,379 @@
|
||||
/* global define, QUnit, module, test, ok, equal, deepEqual, notEqual */
|
||||
/* global Workflow, CanvasManager, InputTerminal, Connector, add_node */
|
||||
define([
|
||||
"galaxy.workflow_editor.canvas",
|
||||
"jquery",
|
||||
"sinon-qunit"
|
||||
], function(
|
||||
workflowEditor,
|
||||
$,
|
||||
sinon
|
||||
){
|
||||
"use strict";
|
||||
|
||||
// globals cosumed by workflow editor
|
||||
window.show_form_for_tool = sinon.spy();
|
||||
window.workflow = null;
|
||||
window.canvas_manager = null;
|
||||
|
||||
// Stub used over stubbing issubtype for unit testing datatype comparisons.
|
||||
var issubtypeStub = null;
|
||||
|
||||
QUnit.moduleStart(function() {
|
||||
if( issubtypeStub === null) {
|
||||
issubtypeStub = sinon.stub( window, "issubtype" );
|
||||
}
|
||||
});
|
||||
QUnit.moduleDone(function() {
|
||||
if( issubtypeStub !== null) {
|
||||
issubtypeStub.restore();
|
||||
issubtypeStub = null;
|
||||
}
|
||||
});
|
||||
|
||||
var with_canvas_container = function( f ) {
|
||||
var canvas_container = $("<div id='canvas-container'>");
|
||||
$("body").append( canvas_container );
|
||||
f( canvas_container );
|
||||
canvas_container.remove();
|
||||
};
|
||||
|
||||
var with_workflow_global = function( f ) {
|
||||
var overview = $( "<div id='overview'><canvas id='overview-canvas'></canvas><div id='overview-viewport'></div></div>" );
|
||||
var canvas_viewport = $( "<div id='canvas-viewport'><div id='canvas-container'></div></div>" );
|
||||
|
||||
$("body").append( overview, canvas_viewport );
|
||||
window.canvas_manager = new CanvasManager( canvas_viewport, overview );
|
||||
with_canvas_container( function( canvas_container ) {
|
||||
window.workflow = new Workflow( canvas_container );
|
||||
f( window.workflow );
|
||||
window.workflow = null;
|
||||
} );
|
||||
window.canvas_manager = null;
|
||||
overview.remove();
|
||||
canvas_viewport.remove();
|
||||
};
|
||||
|
||||
module( "Input terminal model test", {
|
||||
setup: function() {
|
||||
this.node = { };
|
||||
this.element = $( "<div>" );
|
||||
this.input_terminal = new InputTerminal( this.element, [ "txt" ] );
|
||||
this.input_terminal.node = this.node;
|
||||
},
|
||||
test_connector: function( attr ) {
|
||||
var connector = attr || {};
|
||||
this.input_terminal.connectors.push( connector );
|
||||
return connector;
|
||||
},
|
||||
with_test_connector: function( attr, f ) {
|
||||
this.test_connector( attr );
|
||||
f();
|
||||
this.reset_connectors();
|
||||
},
|
||||
reset_connectors: function( ) {
|
||||
this.input_terminal.connectors = [];
|
||||
},
|
||||
test_accept: function( other ) {
|
||||
other = other || { node: {}, datatypes: [ "txt" ] };
|
||||
return this.input_terminal.can_accept( other );
|
||||
}
|
||||
} );
|
||||
|
||||
test( "test connect", function() {
|
||||
this.node.changed = sinon.spy();
|
||||
|
||||
var connector = {};
|
||||
this.input_terminal.connect( connector );
|
||||
|
||||
// Assert node changed called
|
||||
ok( this.node.changed.called );
|
||||
// Assert connectors updated
|
||||
ok( this.input_terminal.connectors[ 0 ] === connector );
|
||||
} );
|
||||
|
||||
test( "test disconnect", function() {
|
||||
this.node.changed = sinon.spy();
|
||||
|
||||
var connector = this.test_connector( {} );
|
||||
this.input_terminal.disconnect( connector );
|
||||
|
||||
// Assert node changed called
|
||||
ok( this.node.changed.called );
|
||||
// Assert connectors updated
|
||||
equal( this.input_terminal.connectors.length, 0 );
|
||||
} );
|
||||
|
||||
test( "test redraw", function() {
|
||||
var connector = this.test_connector( { redraw: sinon.spy() } );
|
||||
this.input_terminal.redraw();
|
||||
// Assert connectors were redrawn
|
||||
ok( connector.redraw.called );
|
||||
} );
|
||||
|
||||
test( "test destroy", function() {
|
||||
var connector = this.test_connector( { destroy: sinon.spy() } );
|
||||
|
||||
this.input_terminal.destroy();
|
||||
// Assert connectors were redrawn
|
||||
ok( connector.destroy.called );
|
||||
} );
|
||||
|
||||
test( "can accept correct datatype", function() {
|
||||
issubtypeStub.returns(true);
|
||||
ok( this.test_accept() ) ;
|
||||
} );
|
||||
|
||||
test( "cannot accept incorrect datatypes", function() {
|
||||
issubtypeStub.returns(false);
|
||||
ok( ! this.test_accept() );
|
||||
} );
|
||||
|
||||
test( "can accept inputs", function() {
|
||||
issubtypeStub.returns(false);
|
||||
// Other is data input module - always accept (currently - could be
|
||||
// more intelligent by looking at what else input is connected to.
|
||||
var other = { node: {}, datatypes: [ "input" ] };
|
||||
ok( this.test_accept( other ) );
|
||||
} );
|
||||
|
||||
test( "cannot accept when already connected", function() {
|
||||
issubtypeStub.returns(true);
|
||||
var self = this;
|
||||
// If other is subtype but already connected, cannot accept
|
||||
this.with_test_connector( {}, function() {
|
||||
ok( ! self.test_accept() );
|
||||
} );
|
||||
} );
|
||||
|
||||
module( "Connector test", {
|
||||
|
||||
} );
|
||||
|
||||
test( "connects only if both valid handles", function() {
|
||||
var input = { connect: sinon.spy() };
|
||||
var output = { connect: sinon.spy() };
|
||||
new Connector( input, null );
|
||||
new Connector( null, output );
|
||||
// Not attempts to connect...
|
||||
ok( ! input.connect.called );
|
||||
ok( ! output.connect.called );
|
||||
|
||||
new Connector( input, output );
|
||||
ok( input.connect.called );
|
||||
ok( output.connect.called );
|
||||
});
|
||||
|
||||
test( "default attributes", function() {
|
||||
var input = { connect: sinon.spy() };
|
||||
var output = { connect: sinon.spy() };
|
||||
var connector = new Connector( input, output );
|
||||
|
||||
equal( connector.dragging, false );
|
||||
equal( connector.canvas, null );
|
||||
equal( connector.inner_color, "#FFFFFF" );
|
||||
equal( connector.outer_color, "#D8B365" );
|
||||
} );
|
||||
|
||||
test( "destroy", function() {
|
||||
var input = { connect: sinon.spy(), disconnect: sinon.spy() };
|
||||
var output = { connect: sinon.spy(), disconnect: sinon.spy() };
|
||||
var connector = new Connector( input, output );
|
||||
|
||||
connector.destroy();
|
||||
ok( input.disconnect.called );
|
||||
ok( output.disconnect.called );
|
||||
} );
|
||||
|
||||
test( "initial redraw", function() {
|
||||
with_canvas_container( function( canvas_container ) {
|
||||
var input = { connect: sinon.spy(), element: $("<div>") };
|
||||
var output = { connect: sinon.spy(), element: $("<div>") };
|
||||
var connector = new Connector( input, output );
|
||||
|
||||
connector.redraw();
|
||||
// Ensure canvas gets set
|
||||
ok( connector.canvas );
|
||||
// Ensure it gest added to canvas container
|
||||
equal( canvas_container.children()[ 0 ], connector.canvas );
|
||||
} );
|
||||
} );
|
||||
|
||||
module( "Node unit test", {
|
||||
setup: function() {
|
||||
this.input_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
|
||||
this.output_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
|
||||
this.element = $("<div><div class='toolFormBody'></div></div>");
|
||||
this.node = new Node( this.element );
|
||||
this.node.input_terminals.i1 = this.input_terminal;
|
||||
this.node.output_terminals.o1 = this.output_terminal;
|
||||
},
|
||||
$: function( selector ) {
|
||||
return $( this.node.element.find( selector ) );
|
||||
},
|
||||
expect_workflow_node_changed: function( f ) {
|
||||
var node = this.node;
|
||||
with_workflow_global( function( workflow ) {
|
||||
var node_changed_spy = sinon.spy( workflow, "node_changed" );
|
||||
f();
|
||||
ok( node_changed_spy.calledWith( node ) );
|
||||
} );
|
||||
},
|
||||
init_field_data_simple: function() {
|
||||
var data = {
|
||||
data_inputs: [ {name: "input1", extensions: [ "data" ] } ],
|
||||
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
|
||||
};
|
||||
this.node.init_field_data( data );
|
||||
},
|
||||
update_field_data_with_new_input: function() {
|
||||
var new_data = {
|
||||
data_inputs: [
|
||||
{ name: "input1", extensions: [ "data" ] },
|
||||
{ name: "extra_0|input1", extensions: [ "data" ] },
|
||||
],
|
||||
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
|
||||
post_job_actions: "{}"
|
||||
};
|
||||
this.node.update_field_data( new_data );
|
||||
}
|
||||
} );
|
||||
|
||||
test( "make active", function() {
|
||||
ok( ! this.element.hasClass( "toolForm-active" ) );
|
||||
this.node.make_active();
|
||||
ok( this.element.hasClass( "toolForm-active" ) );
|
||||
} );
|
||||
|
||||
test( "destroy", function() {
|
||||
var test = this;
|
||||
with_workflow_global( function( workflow ) {
|
||||
var remove_node_spy = sinon.spy( workflow, "remove_node" );
|
||||
test.node.destroy();
|
||||
ok( test.input_terminal.destroy.called );
|
||||
ok( test.output_terminal.destroy.called );
|
||||
ok( remove_node_spy.calledWith( test.node ) );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( "error", function() {
|
||||
// Test body of toolFormBody div updated and workflow notified of change.
|
||||
var test = this;
|
||||
this.expect_workflow_node_changed( function() {
|
||||
test.node.error( "TOOL ERROR" );
|
||||
equal( $( test.$(".toolFormBody").children()[ 0 ] ).html(), "TOOL ERROR" );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( "init_field_data properties", function() {
|
||||
var node = this.node;
|
||||
this.expect_workflow_node_changed( function( ) {
|
||||
var data = {
|
||||
data_inputs: [],
|
||||
data_outputs: [],
|
||||
type: "tool",
|
||||
name: "cat1",
|
||||
form_html: "<form>",
|
||||
tool_state: "ok",
|
||||
tool_errors: false,
|
||||
tooltip: "tool tooltip",
|
||||
annotation: "tool annotation",
|
||||
workflow_outputs: [ "out1" ],
|
||||
};
|
||||
node.init_field_data( data );
|
||||
equal( node.type, "tool" );
|
||||
equal( node.name, "cat1" );
|
||||
equal( node.form_html, "<form>" );
|
||||
equal( node.tool_state, "ok" );
|
||||
equal( node.tooltip, "tool tooltip" );
|
||||
equal( node.annotation, "tool annotation" );
|
||||
deepEqual( node.post_job_actions, {} );
|
||||
deepEqual( node.workflow_outputs, [ "out1" ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( "init_field_data data", function() {
|
||||
var test = this;
|
||||
this.expect_workflow_node_changed( function( ) {
|
||||
// pre-init not tool form body...
|
||||
equal( test.$( ".output-terminal" ).length, 0 );
|
||||
equal( test.$( ".input-terminal" ).length, 0 );
|
||||
equal( test.$( ".rule" ).length, 0 );
|
||||
|
||||
test.init_field_data_simple();
|
||||
|
||||
// After init tool form should have three "rows"/divs - , inputs div, one output, and rule...
|
||||
equal( test.$( ".output-terminal" ).length, 1 );
|
||||
equal( test.$( ".input-terminal" ).length, 1 );
|
||||
equal( test.$( ".rule" ).length, 1 );
|
||||
|
||||
equal( test.$( ".toolFormBody" ).children().length, 3 );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( "update_field_data updated data inputs and outputs", function() {
|
||||
var test = this;
|
||||
this.expect_workflow_node_changed( function( ) {
|
||||
// Call init with one input and output.
|
||||
test.init_field_data_simple();
|
||||
|
||||
test.update_field_data_with_new_input();
|
||||
|
||||
// Now there are 2 inputs...
|
||||
equal( test.$( ".input-terminal" ).length, 2 );
|
||||
equal( test.$( ".output-terminal" ).length, 1 );
|
||||
equal( test.$( ".rule" ).length, 1 );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( "update_field_data preserves connectors", function() {
|
||||
var test = this;
|
||||
var node = this.node;
|
||||
this.expect_workflow_node_changed( function( ) {
|
||||
// Call init with one input and output.
|
||||
test.init_field_data_simple();
|
||||
|
||||
var connector = new Connector();
|
||||
var old_input_terminal = node.input_terminals.input1;
|
||||
old_input_terminal.connectors.push( connector );
|
||||
|
||||
test.update_field_data_with_new_input();
|
||||
|
||||
var new_input_terminal = node.input_terminals.input1;
|
||||
equal( old_input_terminal, old_input_terminal );
|
||||
notEqual( old_input_terminal, new_input_terminal );
|
||||
equal( connector, new_input_terminal.connectors[ 0 ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
test( "update_field_data destroys old terminals", function() {
|
||||
var test = this;
|
||||
var node = this.node;
|
||||
this.expect_workflow_node_changed( function( ) {
|
||||
var data = {
|
||||
data_inputs: [ { name: "input1", extensions: [ "data" ] },
|
||||
{ name: "willDisappear", extensions: [ "data" ] } ],
|
||||
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
|
||||
};
|
||||
node.init_field_data( data );
|
||||
|
||||
var old_input_terminal = node.input_terminals.willDisappear;
|
||||
var destroy_spy = sinon.spy( old_input_terminal, "destroy" );
|
||||
// Update
|
||||
test.update_field_data_with_new_input();
|
||||
|
||||
ok( destroy_spy.called );
|
||||
} );
|
||||
} );
|
||||
|
||||
module( "add_node" );
|
||||
|
||||
test( "node added to workflow", function() {
|
||||
with_workflow_global( function( workflow ) {
|
||||
var add_node_spy = sinon.spy( workflow, "add_node" );
|
||||
var node = add_node( "tool", "Cat Files", "cat1" );
|
||||
ok( add_node_spy.calledWith( node ) );
|
||||
} );
|
||||
} );
|
||||
|
||||
});
|
||||
@@ -1418,10 +1418,10 @@ class ShedTwillTestCase( TwillTestCase ):
|
||||
def verify_repository_reviews( self, repository, reviewer=None, strings_displayed=[], strings_not_displayed=[] ):
|
||||
changeset_revision = self.get_repository_tip( repository )
|
||||
# Verify that the currently logged in user has a repository review for the specified repository, reviewer, and changeset revision.
|
||||
strings_displayed=[ repository.name, reviewer.username, changeset_revision ]
|
||||
strings_displayed=[ repository.name, reviewer.username ]
|
||||
self.display_reviewed_repositories_owned_by_user( strings_displayed=strings_displayed )
|
||||
# Verify that the reviewer has reviewed the specified repository's changeset revision.
|
||||
strings_displayed=[ repository.name, repository.description, changeset_revision ]
|
||||
strings_displayed=[ repository.name, repository.description ]
|
||||
self.display_repository_reviews_by_user( reviewer, strings_displayed=strings_displayed )
|
||||
# Load the review and check for the components passed in strings_displayed.
|
||||
review = test_db_util.get_repository_review_by_user_id_changeset_revision( reviewer.id, repository.id, changeset_revision )
|
||||
|
||||
@@ -104,7 +104,6 @@ class TestRepositoryCitableURLs( ShedTwillTestCase ):
|
||||
strings_displayed = [ '/repository/browse_repositories', encoded_user_id, 'operation=repositories_by_user' ]
|
||||
strings_displayed.append( encoded_user_id )
|
||||
strings_displayed_in_iframe = [ 'user1', 'filtering_0420', 'Galaxy filtering tool for test 0420' ]
|
||||
strings_displayed_in_iframe.append( self.get_repository_tip( repository ) )
|
||||
self.load_citable_url( username='user1',
|
||||
repository_name=None,
|
||||
changeset_revision=None,
|
||||
@@ -208,7 +207,6 @@ class TestRepositoryCitableURLs( ShedTwillTestCase ):
|
||||
strings_displayed.extend( [ 'list+of+repositories+owned', 'does+not+include+one+named', '%21%21invalid%21%21', 'status=error' ] )
|
||||
strings_displayed_in_iframe = [ 'user1', 'filtering_0420' ]
|
||||
strings_displayed_in_iframe.append( 'Repositories Owned by user1' )
|
||||
strings_displayed_in_iframe.append( tip_revision )
|
||||
self.load_citable_url( username='user1',
|
||||
repository_name='!!invalid!!',
|
||||
changeset_revision=None,
|
||||
|
||||
Reference in New Issue
Block a user