1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/a70f236803f7/ Changeset: a70f236803f7 User: martenson Date: 2014-04-10 21:05:33 Summary: data libraries: API refactoring and improvements; backbone decoupling; role UI first implementation Affected #: 19 files diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f lib/galaxy/webapps/galaxy/api/folder_contents.py --- a/lib/galaxy/webapps/galaxy/api/folder_contents.py +++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py @@ -1,13 +1,16 @@ """ -API operations on the contents of a folder. +API operations on the contents of a library folder. """ -import logging, os, string, shutil, urllib, re, socket -from cgi import escape, FieldStorage -from galaxy import util, datatypes, jobs, web, util -from galaxy.web.base.controller import * -from galaxy.util.sanitize_html import sanitize_html -from galaxy.model.orm import * +from galaxy import util +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 ): @@ -15,65 +18,60 @@ Class controls retrieval, creation and updating of 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. - """ - current_user_roles = trans.get_current_user_roles() - is_admin = trans.user_is_admin() - content_items = [] - for subfolder in folder.active_folders: - if not is_admin: - can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, subfolder ) - if (is_admin or can_access) and not subfolder.deleted: - subfolder.api_type = 'folder' - content_items.append( subfolder ) - for dataset in folder.datasets: - if not is_admin: - can_access = trans.app.security_agent.can_access_dataset( current_user_roles, dataset.library_dataset_dataset_association.dataset ) - if (is_admin or can_access) and not dataset.deleted: - dataset.api_type = 'file' - content_items.append( dataset ) - return content_items - - @web.expose_api + @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 as a separate object in response providing data for breadcrumb path building. + Full path is provided in response as a separate object providing data for breadcrumb path building. """ - folder_container = [] - current_user_roles = trans.get_current_user_roles() - if ( folder_id.startswith( 'F' ) ): + if ( len( folder_id ) == 17 and folder_id.startswith( 'F' ) ): try: - decoded_folder_id = trans.security.decode_id( folder_id[1:] ) + 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 ) + 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 ).get( decoded_folder_id ) - except: - folder = None - log.error( "FolderContentsController.index: Unable to retrieve folder with ID: %s" % folder_id ) + 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.' ) - # 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 ) - + 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 ) ): - 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 ) + 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 ) ) path_to_root = [] def build_path ( folder ): """ - Search the path upwards recursively and load the whole route of names and ids for breadcrumb purposes. + 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 @@ -88,13 +86,13 @@ # 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 ): + 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" ) @@ -122,16 +120,36 @@ 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 + + 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. + """ + current_user_roles = trans.get_current_user_roles() + is_admin = trans.user_is_admin() + content_items = [] + for subfolder in folder.active_folders: + if not is_admin: + can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, subfolder ) + if (is_admin or can_access) and not subfolder.deleted: + subfolder.api_type = 'folder' + content_items.append( subfolder ) + for dataset in folder.datasets: + if not is_admin: + can_access = trans.app.security_agent.can_access_dataset( current_user_roles, dataset.library_dataset_dataset_association.dataset ) + if (is_admin or can_access) and not dataset.deleted: + dataset.api_type = 'file' + content_items.append( dataset ) + return content_items @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 ): @@ -140,20 +158,21 @@ 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.' ) # TODO: Move to library_common. - def __decode_library_content_id( self, trans, content_id ): - if ( len( content_id ) % 16 == 0 ): - return 'LibraryDataset', content_id - elif ( content_id.startswith( 'F' ) ): - return 'LibraryFolder', content_id[1:] - else: - raise HTTPBadRequest( 'Malformed library content id ( %s ) specified, unable to decode.' % str( content_id ) ) + # def __decode_library_content_id( self, trans, content_id ): + # if ( len( content_id ) % 16 == 0 ): + # return 'LibraryDataset', content_id + # elif ( content_id.startswith( 'F' ) ): + # return 'LibraryFolder', content_id[1:] + # else: + # raise HTTPBadRequest( 'Malformed library content id ( %s ) specified, unable to decode.' % str( content_id ) ) + diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f lib/galaxy/webapps/galaxy/api/folders.py --- a/lib/galaxy/webapps/galaxy/api/folders.py +++ b/lib/galaxy/webapps/galaxy/api/folders.py @@ -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 @@ """ 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 ): diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f lib/galaxy/webapps/galaxy/api/libraries.py --- a/lib/galaxy/webapps/galaxy/api/libraries.py +++ b/lib/galaxy/webapps/galaxy/api/libraries.py @@ -7,7 +7,7 @@ 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 @@ 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 @@ 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 @@ 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 ): diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f lib/galaxy/webapps/galaxy/api/library_contents.py --- a/lib/galaxy/webapps/galaxy/api/library_contents.py +++ b/lib/galaxy/webapps/galaxy/api/library_contents.py @@ -17,8 +17,7 @@ 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 ): diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/galaxy.library.js --- a/static/scripts/galaxy.library.js +++ b/static/scripts/galaxy.library.js @@ -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 @@ } }); -// 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 @@ 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 @@ } }); -// return return { GalaxyApp: GalaxyLibrary }; diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/mvc/library/library-folderlist-view.js --- a/static/scripts/mvc/library/library-folderlist-view.js +++ b/static/scripts/mvc/library/library-folderlist-view.js @@ -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-fold..." 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 :('); - } - }) - }, - - // 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 :('); - } + error: function(){ + mod_toastr.error('An error occured :('); + } }); }, - // 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")); + render: function (options) { + this.options = _.defaults(this.options || {}, options); + var template = this.templateFolder(); + var contains_file = false; - // 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 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'))); + } + } - // download dataset shown currently in modal - downloadCurrent : function(){ - //disable the buttons - this.modal.disableButton('Import'); - this.modal.disableButton('Download'); + // 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]; + } - 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.$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 })); - // we assume the view is existent - folderContentView.processDownload(url, data); - this.modal.enableButton('Import'); - this.modal.enableButton('Download'); - }, + 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 }); + } - // import dataset shown currently in modal into selected history - importCurrentIntoHistory : function(){ - //disable the buttons - this.modal.disableButton('Import'); - this.modal.disableButton('Download'); + // initialize the library tooltips + $("#center [data-toggle]").tooltip(); + //hack to show scrollbars + $("#center").css('overflow','auto'); + }, - 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 + 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); + } + }, - 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'); - } - }); - }, + // 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; + }, // 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 @@ this.makeWhiteRow($row); } } - this.checkTools(); + // this.checkTools(); }, makeDarkRow: function($row){ @@ -507,207 +175,56 @@ $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 }; }); diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/mvc/library/library-librarylist-view.js --- a/static/scripts/mvc/library/library-librarylist-view.js +++ b/static/scripts/mvc/library/library-librarylist-view.js @@ -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 @@ rowViews: {}, // initialize - initialize : function(){ + initialize : function(options){ + this.options = _.defaults(this.options || {}, options); var viewContext = this; this.rowViews = {}; @@ -43,7 +44,7 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ redirectToHome: function(){ window.location = '../'; - }, + }, redirectToLogin: function(){ window.location = '/user/login'; }, @@ -193,7 +195,7 @@ 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 @@ } }); -// return return { LibraryListView: LibraryListView }; diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/mvc/library/library-libraryrow-view.js --- a/static/scripts/mvc/library/library-libraryrow-view.js +++ b/static/scripts/mvc/library/library-libraryrow-view.js @@ -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 @@ 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 @@ 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 @@ 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 @@ is_changed = true; } else{ mod_toastr.warning('Library name has to be at least 3 characters long'); - return + return; } } @@ -183,7 +183,7 @@ 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 @@ tmpl_array.push(' </td>'); tmpl_array.push(' </tr>'); - return _.template(tmpl_array.join('')); + return _.template(tmpl_array.join('')); } }); - // return return { LibraryRowView: LibraryRowView }; diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/mvc/library/library-librarytoolbar-view.js --- a/static/scripts/mvc/library/library-librarytoolbar-view.js +++ b/static/scripts/mvc/library/library-librarytoolbar-view.js @@ -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 @@ 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 @@ 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-fold..." target="_blank">Trello</a>.</h3>'); @@ -60,16 +62,16 @@ 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 }; }); diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/mvc/library/library-model.js --- a/static/scripts/mvc/library/library-model.js +++ b/static/scripts/mvc/library/library-model.js @@ -66,16 +66,14 @@ 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; } }); diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/packed/galaxy.library.js --- a/static/scripts/packed/galaxy.library.js +++ b/static/scripts/packed/galaxy.library.js @@ -1,1 +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}}); \ No newline at end of file +define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view"],function(e,c,g,k,h,a,f,d,i){var l=Backbone.Router.extend({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}}); \ No newline at end of file diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/packed/mvc/library/library-folderlist-view.js --- a/static/scripts/packed/mvc/library/library-folderlist-view.js +++ b/static/scripts/packed/mvc/library/library-folderlist-view.js @@ -1,1 +1,1 @@ -define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(a,c,d,b){var e=Backbone.View.extend({el:"#center",progress:0,progressStep:1,lastSelectedHistory:"",modal:null,folders:null,initialize:function(){this.folders=[];this.queue=jQuery.Deferred();this.queue.resolve()},templateFolder:function(){var f=[];f.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; ">');f.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-fold..." target="_blank">Trello</a>.</h3>');f.push('<div id="library_folder_toolbar" >');f.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>');f.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>');f.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display: none; ">');f.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');f.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');f.push(" </button>");f.push(' <ul class="dropdown-menu" role="menu">');f.push(' <li><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');f.push(' <li><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');f.push(' <li><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');f.push(" </ul>");f.push(" </div>");f.push("</div>");f.push('<ol class="breadcrumb">');f.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');f.push(" <% _.each(path, function(path_item) { %>");f.push(" <% if (path_item[0] != id) { %>");f.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');f.push("<% } else { %>");f.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');f.push(" <% } %>");f.push(" <% }); %>");f.push("</ol>");f.push('<table id="folder_table" class="grid table table-condensed">');f.push(" <thead>");f.push(' <th class="button_heading"></th>');f.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');f.push(" <th>name</th>");f.push(" <th>data type</th>");f.push(" <th>size</th>");f.push(" <th>date (UTC)</th>");f.push(" </thead>");f.push(" <tbody>");f.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>');f.push(" <td></td>");f.push(" <td></td>");f.push(" <td></td>");f.push(" <td></td>");f.push(" <td></td>");f.push(" </tr>");f.push(" <% _.each(items, function(content_item) { %>");f.push(' <% if (content_item.get("type") === "folder") { %>');f.push(' <tr class="folder_row light" id="<%- content_item.id %>">');f.push(" <td>");f.push(' <span title="Folder" class="fa fa-folder-o"></span>');f.push(" </td>");f.push(" <td></td>");f.push(" <td>");f.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');f.push(' <% if (content_item.get("item_count") === 0) { %>');f.push(' <span class="muted">(empty folder)</span>');f.push(" <% } %>");f.push(" </td>");f.push(" <td>folder</td>");f.push(' <td><%= _.escape(content_item.get("item_count")) %> item(s)</td>');f.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');f.push(" </tr>");f.push(" <% } else { %>");f.push(' <tr class="dataset_row light" id="<%- content_item.id %>">');f.push(" <td>");f.push(' <span title="Dataset" class="fa fa-file-o"></span>');f.push(" </td>");f.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');f.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>');f.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');f.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');f.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');f.push(" </tr>");f.push(" <% } %> ");f.push(" <% }); %>");f.push(" ");f.push(" </tbody>");f.push("</table>");f.push("</div>");return f.join("")},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")},templateBulkImportInModal:function(){var f=[];f.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")},templateProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return f.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("")},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"},render:function(f){$("#center").css("overflow","auto");view=this;var h=this;var g=new b.FolderContainer({id:f.id});g.url=g.attributes.urlRoot+f.id+"/contents";g.fetch({success:function(j){for(var l=0;l<g.attributes.folder.models.length;l++){var k=g.attributes.folder.models[l];if(k.get("type")==="file"){k.set("readable_size",h.size_to_string(k.get("file_size")))}}var n=g.full_path;var o;if(n.length===1){o=0}else{o=n[n.length-2][0]}var m=_.template(h.templateFolder(),{path:g.full_path,items:g.attributes.folder.models,id:f.id,upper_folder_id:o});h.$el.html(m)},error:function(){d.error("An error occured :(")}})},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},showDatasetDetails:function(i){i.preventDefault();var j=$(i.target).parent().parent().parent().attr("id");if(typeof j==="undefined"){j=$(i.target).parent().attr("id")}if(typeof j==="undefined"){j=$(i.target).parent().parent().attr("id")}var h=new b.Item();var g=new b.GalaxyHistories();h.id=j;var f=this;h.fetch({success:function(k){g.fetch({success:function(l){f.renderModalAfterFetch(k,l)},error:function(){d.error("An error occured during fetching histories:(");f.renderModalAfterFetch(k)}})},error:function(){d.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html("Peek:"+k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};folderContentView.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var h=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=h;var f=$("#id_row").attr("data-id");var i=new b.HistoryItem();var g=this;i.url=i.urlRoot+h+"/contents";i.save({content:f,source:"library"},{success:function(){d.success("Dataset imported");g.modal.enableButton("Import");g.modal.enableButton("Download")},error:function(){d.error("An error occured! Dataset not imported. Please try again.");g.modal.enableButton("Import");g.modal.enableButton("Download")}})},selectAll:function(g){var f=g.target.checked;that=this;$(":checkbox").each(function(){this.checked=f;$row=$(this.parentElement.parentElement);(f)?that.makeDarkRow($row):that.makeWhiteRow($row)});this.checkTools()},selectClickedRow:function(g){var i="";var f;var h;if(g.target.localName==="input"){i=g.target;f=$(g.target.parentElement.parentElement);h="input"}else{if(g.target.localName==="td"){i=$("#"+g.target.parentElement.id).find(":checkbox")[0];f=$(g.target.parentElement);h="td"}}if(i.checked){if(h==="td"){i.checked="";this.makeWhiteRow(f)}else{if(h==="input"){this.makeDarkRow(f)}}}else{if(h==="td"){i.checked="selected";this.makeDarkRow(f)}else{if(h==="input"){this.makeWhiteRow(f)}}}this.checkTools()},makeDarkRow:function(f){f.removeClass("light");f.find("a").removeClass("light");f.addClass("dark");f.find("a").addClass("dark");f.find("span").removeClass("fa-file-o");f.find("span").addClass("fa-file")},makeWhiteRow:function(f){f.removeClass("dark");f.find("a").removeClass("dark");f.addClass("light");f.find("a").addClass("light");f.find("span").addClass("fa-file-o");f.find("span").removeClass("fa-file")},checkTools:function(){var f=$("#folder_table").find(":checked");if(f.length>0){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}else{$("#toolbtn_bulk_import").hide();$("#toolbtn_dl").hide()}},modalBulkImport:function(){var g=this;var f=new b.GalaxyHistories();f.fetch({success:function(h){var i=_.template(g.templateBulkImportInModal(),{histories:h.models});g.modal=Galaxy.modal;g.modal.show({closing_events:true,title:"Import into History",body:i,buttons:{Import:function(){g.importAllIntoHistory()},Close:function(){g.modal.hide()}}})},error:function(){d.error("An error occured :(")}})},importAllIntoHistory:function(){this.modal.disableButton("Import");var h=$("select[name=dataset_import_bulk] option:selected").val();var m=$("select[name=dataset_import_bulk] option:selected").text();var o=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){o.push(this.parentElement.parentElement.id)}});var n=_.template(this.templateProgressBar(),{history_name:m});$(this.modal.elMain).find(".modal-body").html(n);var j=100/o.length;this.initProgress(j);var f=[];for(var g=o.length-1;g>=0;g--){library_dataset_id=o[g];var k=new b.HistoryItem();var l=this;k.url=k.urlRoot+h+"/contents";k.content=library_dataset_id;k.source="library";f.push(k)}this.chainCall(f)},chainCall:function(g){var f=this;var h=g.pop();if(typeof h==="undefined"){d.success("All datasets imported");this.modal.hide();return}var i=$.when(h.save({content:h.content,source:h.source})).done(function(j){f.updateProgress();f.chainCall(g)})},initProgress:function(f){this.progress=0;this.progressStep=f},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(f,j){var h=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){h.push(this.parentElement.parentElement.id)}});var g="/api/libraries/datasets/download/"+j;var i={ldda_ids:h};this.processDownload(g,i,"get")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();d.info("Your download will begin soon")}},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:this.templateNewFolderInModal(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){f.modal.hide();f.modal=null}}})},create_new_folder_event:function(){var f=this.serialize_new_folder();if(this.validate_new_folder(f)){var h=new b.FolderAsModel();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];h.url=h.urlRoot+"/"+current_folder_id;var g=this;h.save(f,{success:function(i){g.modal.hide();d.success("Folder created");g.render({id:current_folder_id})},error:function(){d.error("An error occured :(")}})}else{d.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""}});return{FolderContentView:e}}); \ No newline at end of file +define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderrow-view"],function(c,e,f,d,a){var b=Backbone.View.extend({el:"#folder_items_element",progress:0,progressStep:1,modal:null,folderContainer:null,events:{"click #select-all-checkboxes":"selectAll","click .dataset_row":"selectClickedRow"},initialize:function(g){var h=this;this.options=_.defaults(this.options||{},g);this.queue=jQuery.Deferred();this.queue.resolve();this.folderContainer=new d.FolderContainer({id:this.options.id});this.folderContainer.url=this.folderContainer.attributes.urlRoot+this.options.id+"/contents";this.folderContainer.fetch({success:function(i){h.render()},error:function(){f.error("An error occured :(")}})},render:function(h){this.options=_.defaults(this.options||{},h);var k=this.templateFolder();var l=false;for(var j=0;j<this.folderContainer.attributes.folder.models.length;j++){var g=this.folderContainer.attributes.folder.models[j];if(g.get("type")==="file"){l=true;g.set("readable_size",this.size_to_string(g.get("file_size")))}}var m=this.folderContainer.attributes.metadata.full_path;var n;if(m.length===1){n=0}else{n=m[m.length-2][0]}this.$el.html(k({path:this.folderContainer.attributes.metadata.full_path,items:this.folderContainer.attributes.folder.models,id:this.options.id,upper_folder_id:n}));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:l})}$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(){for(var j=0;j<this.folderContainer.attributes.folder.models.length;j++){var h=this.folderContainer.attributes.folder.models[j];var g=new a.FolderRowView(h);this.$el.find("#folder_list_body").append(g.el)}},size_to_string:function(g){var h="";if(g>=100000000000){g=g/100000000000;h="TB"}else{if(g>=100000000){g=g/100000000;h="GB"}else{if(g>=100000){g=g/100000;h="MB"}else{if(g>=100){g=g/100;h="KB"}else{g=g*10;h="b"}}}}return(Math.round(g)/10)+h},selectAll:function(h){var g=h.target.checked;that=this;$(":checkbox").each(function(){this.checked=g;$row=$(this.parentElement.parentElement);(g)?that.makeDarkRow($row):that.makeWhiteRow($row)})},selectClickedRow:function(h){var j="";var g;var i;if(h.target.localName==="input"){j=h.target;g=$(h.target.parentElement.parentElement);i="input"}else{if(h.target.localName==="td"){j=$("#"+h.target.parentElement.id).find(":checkbox")[0];g=$(h.target.parentElement);i="td"}}if(j.checked){if(i==="td"){j.checked="";this.makeWhiteRow(g)}else{if(i==="input"){this.makeDarkRow(g)}}}else{if(i==="td"){j.checked="selected";this.makeDarkRow(g)}else{if(i==="input"){this.makeWhiteRow(g)}}}},makeDarkRow:function(g){g.removeClass("light");g.find("a").removeClass("light");g.addClass("dark");g.find("a").addClass("dark");g.find("span").removeClass("fa-file-o");g.find("span").addClass("fa-file")},makeWhiteRow:function(g){g.removeClass("dark");g.find("a").removeClass("dark");g.addClass("light");g.find("a").addClass("light");g.find("span").addClass("fa-file-o");g.find("span").removeClass("fa-file")},templateFolder:function(){var g=[];g.push('<ol class="breadcrumb">');g.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');g.push(" <% _.each(path, function(path_item) { %>");g.push(" <% if (path_item[0] != id) { %>");g.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');g.push("<% } else { %>");g.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');g.push(" <% } %>");g.push(" <% }); %>");g.push("</ol>");g.push('<table id="folder_table" class="grid table table-condensed">');g.push(" <thead>");g.push(' <th class="button_heading"></th>');g.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');g.push(" <th>name</th>");g.push(" <th>data type</th>");g.push(" <th>size</th>");g.push(" <th>date (UTC)</th>");g.push(" </thead>");g.push(' <tbody id="folder_list_body">');g.push(" <tr>");g.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" </tr>");g.push(" </tbody>");g.push("</table>");return _.template(g.join(""))}});return{FolderListView:b}}); \ No newline at end of file diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/packed/mvc/library/library-librarylist-view.js --- a/static/scripts/packed/mvc/library/library-librarylist-view.js +++ b/static/scripts/packed/mvc/library/library-librarylist-view.js @@ -1,1 +1,1 @@ -define(["galaxy.masthead","mvc/base-mvc","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-libraryrow-view"],function(b,g,d,e,c,a){var f=Backbone.View.extend({el:"#libraries_element",events:{"click .sort-libraries-link":"sort_clicked"},modal:null,collection:null,rowViews:{},initialize:function(){var h=this;this.rowViews={};this.collection=new c.Libraries();this.collection.fetch({success:function(i){h.render()},error:function(j,i){e.error("An error occured. Please try again.")}})},render:function(i){var j=this.templateLibraryList();var k=null;var h=true;var h=Galaxy.libraries.preferences.get("with_deleted");var l=null;if(typeof i!=="undefined"){h=typeof i.with_deleted!=="undefined"?i.with_deleted:false;l=typeof i.models!=="undefined"?i.models:null}if(this.collection!==null&&l===null){if(h){k=this.collection.models}else{k=this.collection.where({deleted:false})}}else{if(l!==null){k=l}else{k=[]}}this.$el.html(j({length:k.length,order:Galaxy.libraries.preferences.get("sort_order")}));this.renderRows(k);$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(m){for(var l=0;l<m.length;l++){var k=m[l];var j=_.findWhere(this.rowViews,{id:k.get("id")});if(j!==undefined&&this instanceof Backbone.View){j.delegateEvents();this.$el.find("#library_list_body").append(j.el)}else{var h=new a.LibraryRowView(k);this.$el.find("#library_list_body").append(h.el);this.rowViews[k.get("id")]=h}}},sort_clicked:function(){if(Galaxy.libraries.preferences.get("sort_order")==="asc"){this.sortLibraries("name","desc");Galaxy.libraries.preferences.set({sort_order:"desc"})}else{this.sortLibraries("name","asc");Galaxy.libraries.preferences.set({sort_order:"asc"})}this.render()},sortLibraries:function(i,h){if(i==="name"){if(h==="asc"){this.collection.comparator=function(k,j){if(k.get("name").toLowerCase()>j.get("name").toLowerCase()){return 1}if(j.get("name").toLowerCase()>k.get("name").toLowerCase()){return -1}return 0}}else{if(h==="desc"){this.collection.comparator=function(k,j){if(k.get("name").toLowerCase()>j.get("name").toLowerCase()){return -1}if(j.get("name").toLowerCase()>k.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];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("<% } else{ %>");tmpl_array.push('<table class="grid table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th style="width:30%;"><a class="sort-libraries-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(' <th style="width:22%;">description</th>');tmpl_array.push(' <th style="width:22%;">synopsis</th> ');tmpl_array.push(' <th style="width:26%;"></th> ');tmpl_array.push(" </thead>");tmpl_array.push(' <tbody id="library_list_body">');tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("<% }%>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(i){i.preventDefault();i.stopPropagation();var h=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){h.create_new_library_event()},Close:function(){h.modal.hide()}}})},create_new_library_event:function(){var j=this.serialize_new_library();if(this.validate_new_library(j)){var i=new c.Library();var h=this;i.save(j,{success:function(k){h.collection.add(k);h.modal.hide();h.clear_library_modal();h.render();e.success("Library created")},error:function(){e.error("An error occured :(")}})}else{e.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(h){return h.name!==""}});return{LibraryListView:f}}); \ No newline at end of file +define(["galaxy.masthead","mvc/base-mvc","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-libraryrow-view"],function(b,g,d,e,c,a){var f=Backbone.View.extend({el:"#libraries_element",events:{"click .sort-libraries-link":"sort_clicked"},modal:null,collection:null,rowViews:{},initialize:function(i){this.options=_.defaults(this.options||{},i);var h=this;this.rowViews={};this.collection=new c.Libraries();this.collection.fetch({success:function(j){h.render()},error:function(k,j){e.error("An error occured. Please try again.")}})},render:function(i){var j=this.templateLibraryList();var k=null;var h=Galaxy.libraries.preferences.get("with_deleted");var l=null;if(typeof i!=="undefined"){h=typeof i.with_deleted!=="undefined"?i.with_deleted:false;l=typeof i.models!=="undefined"?i.models:null}if(this.collection!==null&&l===null){if(h){k=this.collection.models}else{k=this.collection.where({deleted:false})}}else{if(l!==null){k=l}else{k=[]}}this.$el.html(j({length:k.length,order:Galaxy.libraries.preferences.get("sort_order")}));if(k.length>0){this.renderRows(k)}$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(m){for(var l=0;l<m.length;l++){var k=m[l];var j=_.findWhere(this.rowViews,{id:k.get("id")});if(j!==undefined&&this instanceof Backbone.View){j.delegateEvents();this.$el.find("#library_list_body").append(j.el)}else{var h=new a.LibraryRowView(k);this.$el.find("#library_list_body").append(h.el);this.rowViews[k.get("id")]=h}}},sort_clicked:function(){if(Galaxy.libraries.preferences.get("sort_order")==="asc"){this.sortLibraries("name","desc");Galaxy.libraries.preferences.set({sort_order:"desc"})}else{this.sortLibraries("name","asc");Galaxy.libraries.preferences.set({sort_order:"asc"})}this.render()},sortLibraries:function(i,h){if(i==="name"){if(h==="asc"){this.collection.comparator=function(k,j){if(k.get("name").toLowerCase()>j.get("name").toLowerCase()){return 1}if(j.get("name").toLowerCase()>k.get("name").toLowerCase()){return -1}return 0}}else{if(h==="desc"){this.collection.comparator=function(k,j){if(k.get("name").toLowerCase()>j.get("name").toLowerCase()){return -1}if(j.get("name").toLowerCase()>k.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container table-responsive">');tmpl_array.push("<% if(length === 0) { %>");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>");tmpl_array.push(' <th style="width:30%;"><a class="sort-libraries-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(' <th style="width:22%;">description</th>');tmpl_array.push(' <th style="width:22%;">synopsis</th> ');tmpl_array.push(' <th style="width:26%;"></th> ');tmpl_array.push(" </thead>");tmpl_array.push(' <tbody id="library_list_body">');tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("<% }%>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(i){i.preventDefault();i.stopPropagation();var h=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){h.create_new_library_event()},Close:function(){h.modal.hide()}}})},create_new_library_event:function(){var j=this.serialize_new_library();if(this.validate_new_library(j)){var i=new c.Library();var h=this;i.save(j,{success:function(k){h.collection.add(k);h.modal.hide();h.clear_library_modal();h.render();e.success("Library created")},error:function(){e.error("An error occured :(")}})}else{e.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(h){return h.name!==""}});return{LibraryListView:f}}); \ No newline at end of file diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/packed/mvc/library/library-libraryrow-view.js --- a/static/scripts/packed/mvc/library/library-libraryrow-view.js +++ b/static/scripts/packed/mvc/library/library-libraryrow-view.js @@ -1,1 +1,1 @@ -define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({events:{"click .edit_library_btn":"edit_button_clicked","click .cancel_library_btn":"cancel_library_modification","click .save_library_btn":"save_library_modification","click .delete_library_btn":"delete_library","click .undelete_library_btn":"undelete_library","click .upload_library_btn":"upload_to_library","click .permission_library_btn":"permissions_on_library"},edit_mode:false,element_visibility_config:{upload_library_btn:false,edit_library_btn:false,permission_library_btn:false,save_library_btn:false,cancel_library_btn:false,delete_library_btn:false,undelete_library_btn:false},initialize:function(f){this.render(f)},render:function(g){if(typeof g==="undefined"){var g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"))}this.prepareButtons(g);var f=this.templateRow();this.setElement(f({library:g,button_config:this.element_visibility_config,edit_mode:this.edit_mode}));this.$el.show();return this},repaint:function(f){$(".tooltip").hide();var g=this.$el;this.render(f);g.replaceWith(this.$el);this.$el.find("[data-toggle]").tooltip()},prepareButtons:function(f){vis_config=this.element_visibility_config;if(this.edit_mode===false){vis_config.save_library_btn=false;vis_config.cancel_library_btn=false;vis_config.delete_library_btn=false;if(f.get("deleted")===true){vis_config.undelete_library_btn=true;vis_config.upload_library_btn=false;vis_config.edit_library_btn=false;vis_config.permission_library_btn=false}else{if(f.get("deleted")===false){vis_config.save_library_btn=false;vis_config.cancel_library_btn=false;vis_config.undelete_library_btn=false;if(f.get("can_user_add")===true){vis_config.upload_library_btn=true}if(f.get("can_user_modify")===true){vis_config.edit_library_btn=true}if(f.get("can_user_manage")===true){vis_config.permission_library_btn=true}}}}else{if(this.edit_mode===true){vis_config.upload_library_btn=false;vis_config.edit_library_btn=false;vis_config.permission_library_btn=false;vis_config.save_library_btn=true;vis_config.cancel_library_btn=true;vis_config.delete_library_btn=true}}this.element_visibility_config=vis_config},upload_to_library:function(){e.info("Coming soon. Stay tuned.")},permissions_on_library:function(){e.info("Coming soon. Stay tuned.")},edit_button_clicked:function(){this.edit_mode=true;this.repaint()},cancel_library_modification:function(){e.info("Modifications canceled");this.edit_mode=false;this.repaint()},save_library_modification:function(){var g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"));var h=false;var j=this.$el.find(".input_library_name").val();if(typeof j!=="undefined"&&j!==g.get("name")){if(j.length>2){g.set("name",j);h=true}else{e.warning("Library name has to be at least 3 characters long");return}}var i=this.$el.find(".input_library_description").val();if(typeof i!=="undefined"&&i!==g.get("description")){g.set("description",i);h=true}var k=this.$el.find(".input_library_synopsis").val();if(typeof k!=="undefined"&&k!==g.get("synopsis")){g.set("synopsis",k);h=true}if(h){var f=this;g.save(null,{patch:true,success:function(l){f.edit_mode=false;f.repaint(l);e.success("Changes to library saved")},error:function(m,l){e.error("An error occured during updating the library :(")}})}else{this.edit_mode=false;this.repaint(g);e.info("Nothing has changed")}},delete_library:function(){var g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"));var f=this;g.destroy({success:function(h){h.set("deleted",true);Galaxy.libraries.libraryListView.collection.add(h);f.edit_mode=false;if(Galaxy.libraries.preferences.get("with_deleted")===false){$(".tooltip").hide();f.$el.remove()}else{if(Galaxy.libraries.preferences.get("with_deleted")===true){f.repaint(h)}}e.success("Library has been marked deleted")},error:function(){e.error("An error occured during deleting the library :(")}})},undelete_library:function(){var g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"));var f=this;g.url=g.urlRoot+g.id+"?undelete=true";g.destroy({success:function(h){h.set("deleted",false);Galaxy.libraries.libraryListView.collection.add(h);f.edit_mode=false;f.repaint(h);e.success("Library has been undeleted")},error:function(){e.error("An error occured while undeleting the library :(")}})},templateRow:function(){tmpl_array=[];tmpl_array.push(' <tr class="<% if(library.get("deleted") === true) { print("active") } %>" style="display:none;" data-id="<%- library.get("id") %>">');tmpl_array.push(" <% if(!edit_mode) { %>");tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(" <% } else if(edit_mode){ %>");tmpl_array.push(' <td><input type="text" class="form-control input_library_name" placeholder="name" value="<%- library.get("name") %>"></td>');tmpl_array.push(' <td><input type="text" class="form-control input_library_description" placeholder="description" value="<%- library.get("description") %>"></td>');tmpl_array.push(' <td><input type="text" class="form-control input_library_synopsis" placeholder="synopsis" value="<%- library.get("synopsis") %>"></td>');tmpl_array.push(" <% } %>");tmpl_array.push(' <td class="right-center">');tmpl_array.push(' <% if(library.get("deleted") === true) { %>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg deleted_lib_ico"></span>');tmpl_array.push(' <% } else if(library.get("public") === true) { %>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Public" style="color:grey;" class="fa fa-globe fa-lg public_lib_ico"></span>');tmpl_array.push(" <% }%>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Upload to library" class="primary-button btn-xs upload_library_btn" type="button" style="<% if(button_config.upload_library_btn === false) { print("display:none;") } %>"><span class="fa fa-upload"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify library" class="primary-button btn-xs edit_library_btn" type="button" style="<% if(button_config.edit_library_btn === false) { print("display:none;") } %>"><span class="fa fa-pencil"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify permissions" class="primary-button btn-xs permission_library_btn" type="button" style="<% if(button_config.permission_library_btn === false) { print("display:none;") } %>"><span class="fa fa-group"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save changes" class="primary-button btn-xs save_library_btn" type="button" style="<% if(button_config.save_library_btn === false) { print("display:none;") } %>"><span class="fa fa-floppy-o"> Save</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Discard changes" class="primary-button btn-xs cancel_library_btn" type="button" style="<% if(button_config.cancel_library_btn === false) { print("display:none;") } %>"><span class="fa fa-times"> Cancel</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Delete library (can be undeleted later)" class="primary-button btn-xs delete_library_btn" type="button" style="<% if(button_config.delete_library_btn === false) { print("display:none;") } %>"><span class="fa fa-trash-o"> Delete</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Undelete library" class="primary-button btn-xs undelete_library_btn" type="button" style="<% if(button_config.undelete_library_btn === false) { print("display:none;") } %>"><span class="fa fa-unlock"> Undelete</span></button>');tmpl_array.push(" </td>");tmpl_array.push(" </tr>");return _.template(tmpl_array.join(""))}});return{LibraryRowView:a}}); \ No newline at end of file +define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({events:{"click .edit_library_btn":"edit_button_clicked","click .cancel_library_btn":"cancel_library_modification","click .save_library_btn":"save_library_modification","click .delete_library_btn":"delete_library","click .undelete_library_btn":"undelete_library","click .upload_library_btn":"upload_to_library","click .permission_library_btn":"permissions_on_library"},edit_mode:false,element_visibility_config:{upload_library_btn:false,edit_library_btn:false,permission_library_btn:false,save_library_btn:false,cancel_library_btn:false,delete_library_btn:false,undelete_library_btn:false},initialize:function(f){this.render(f)},render:function(g){if(typeof g==="undefined"){g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"))}this.prepareButtons(g);var f=this.templateRow();this.setElement(f({library:g,button_config:this.element_visibility_config,edit_mode:this.edit_mode}));this.$el.show();return this},repaint:function(f){$(".tooltip").hide();var g=this.$el;this.render(f);g.replaceWith(this.$el);this.$el.find("[data-toggle]").tooltip()},prepareButtons:function(f){vis_config=this.element_visibility_config;if(this.edit_mode===false){vis_config.save_library_btn=false;vis_config.cancel_library_btn=false;vis_config.delete_library_btn=false;if(f.get("deleted")===true){vis_config.undelete_library_btn=true;vis_config.upload_library_btn=false;vis_config.edit_library_btn=false;vis_config.permission_library_btn=false}else{if(f.get("deleted")===false){vis_config.save_library_btn=false;vis_config.cancel_library_btn=false;vis_config.undelete_library_btn=false;if(f.get("can_user_add")===true){vis_config.upload_library_btn=true}if(f.get("can_user_modify")===true){vis_config.edit_library_btn=true}if(f.get("can_user_manage")===true){vis_config.permission_library_btn=true}}}}else{if(this.edit_mode===true){vis_config.upload_library_btn=false;vis_config.edit_library_btn=false;vis_config.permission_library_btn=false;vis_config.save_library_btn=true;vis_config.cancel_library_btn=true;vis_config.delete_library_btn=true}}this.element_visibility_config=vis_config},upload_to_library:function(){e.info("Coming soon. Stay tuned.")},permissions_on_library:function(){e.info("Coming soon. Stay tuned.")},edit_button_clicked:function(){this.edit_mode=true;this.repaint()},cancel_library_modification:function(){e.info("Modifications canceled");this.edit_mode=false;this.repaint()},save_library_modification:function(){var g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"));var h=false;var j=this.$el.find(".input_library_name").val();if(typeof j!=="undefined"&&j!==g.get("name")){if(j.length>2){g.set("name",j);h=true}else{e.warning("Library name has to be at least 3 characters long");return}}var i=this.$el.find(".input_library_description").val();if(typeof i!=="undefined"&&i!==g.get("description")){g.set("description",i);h=true}var k=this.$el.find(".input_library_synopsis").val();if(typeof k!=="undefined"&&k!==g.get("synopsis")){g.set("synopsis",k);h=true}if(h){var f=this;g.save(null,{patch:true,success:function(l){f.edit_mode=false;f.repaint(l);e.success("Changes to library saved")},error:function(m,l){e.error("An error occured during updating the library :(")}})}else{this.edit_mode=false;this.repaint(g);e.info("Nothing has changed")}},delete_library:function(){var g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"));var f=this;g.destroy({success:function(h){h.set("deleted",true);Galaxy.libraries.libraryListView.collection.add(h);f.edit_mode=false;if(Galaxy.libraries.preferences.get("with_deleted")===false){$(".tooltip").hide();f.$el.remove()}else{if(Galaxy.libraries.preferences.get("with_deleted")===true){f.repaint(h)}}e.success("Library has been marked deleted")},error:function(){e.error("An error occured during deleting the library :(")}})},undelete_library:function(){var g=Galaxy.libraries.libraryListView.collection.get(this.$el.data("id"));var f=this;g.url=g.urlRoot+g.id+"?undelete=true";g.destroy({success:function(h){h.set("deleted",false);Galaxy.libraries.libraryListView.collection.add(h);f.edit_mode=false;f.repaint(h);e.success("Library has been undeleted")},error:function(){e.error("An error occured while undeleting the library :(")}})},templateRow:function(){tmpl_array=[];tmpl_array.push(' <tr class="<% if(library.get("deleted") === true) { print("active") } %>" style="display:none;" data-id="<%- library.get("id") %>">');tmpl_array.push(" <% if(!edit_mode) { %>");tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(" <% } else if(edit_mode){ %>");tmpl_array.push(' <td><input type="text" class="form-control input_library_name" placeholder="name" value="<%- library.get("name") %>"></td>');tmpl_array.push(' <td><input type="text" class="form-control input_library_description" placeholder="description" value="<%- library.get("description") %>"></td>');tmpl_array.push(' <td><input type="text" class="form-control input_library_synopsis" placeholder="synopsis" value="<%- library.get("synopsis") %>"></td>');tmpl_array.push(" <% } %>");tmpl_array.push(' <td class="right-center">');tmpl_array.push(' <% if(library.get("deleted") === true) { %>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg deleted_lib_ico"></span>');tmpl_array.push(' <% } else if(library.get("public") === true) { %>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Public" style="color:grey;" class="fa fa-globe fa-lg public_lib_ico"></span>');tmpl_array.push(" <% }%>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Upload to library" class="primary-button btn-xs upload_library_btn" type="button" style="<% if(button_config.upload_library_btn === false) { print("display:none;") } %>"><span class="fa fa-upload"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify library" class="primary-button btn-xs edit_library_btn" type="button" style="<% if(button_config.edit_library_btn === false) { print("display:none;") } %>"><span class="fa fa-pencil"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify permissions" class="primary-button btn-xs permission_library_btn" type="button" style="<% if(button_config.permission_library_btn === false) { print("display:none;") } %>"><span class="fa fa-group"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save changes" class="primary-button btn-xs save_library_btn" type="button" style="<% if(button_config.save_library_btn === false) { print("display:none;") } %>"><span class="fa fa-floppy-o"> Save</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Discard changes" class="primary-button btn-xs cancel_library_btn" type="button" style="<% if(button_config.cancel_library_btn === false) { print("display:none;") } %>"><span class="fa fa-times"> Cancel</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Delete library (can be undeleted later)" class="primary-button btn-xs delete_library_btn" type="button" style="<% if(button_config.delete_library_btn === false) { print("display:none;") } %>"><span class="fa fa-trash-o"> Delete</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Undelete library" class="primary-button btn-xs undelete_library_btn" type="button" style="<% if(button_config.undelete_library_btn === false) { print("display:none;") } %>"><span class="fa fa-unlock"> Undelete</span></button>');tmpl_array.push(" </td>");tmpl_array.push(" </tr>");return _.template(tmpl_array.join(""))}});return{LibraryRowView:a}}); \ No newline at end of file diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/packed/mvc/library/library-librarytoolbar-view.js --- a/static/scripts/packed/mvc/library/library-librarytoolbar-view.js +++ b/static/scripts/packed/mvc/library/library-librarytoolbar-view.js @@ -1,1 +1,1 @@ -define(["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-fold..." 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}}); \ No newline at end of file +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-fold..." 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}}); \ No newline at end of file diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/scripts/packed/mvc/library/library-model.js --- a/static/scripts/packed/mvc/library/library-model.js +++ b/static/scripts/packed/mvc/library/library-model.js @@ -1,1 +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}}); \ No newline at end of file +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}}); \ No newline at end of file diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/style/blue/base.css --- a/static/style/blue/base.css +++ b/static/style/blue/base.css @@ -1299,6 +1299,7 @@ .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} diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/style/blue/library.css --- a/static/style/blue/library.css +++ b/static/style/blue/library.css @@ -10,6 +10,7 @@ .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} diff -r bacb1a3c0eaa0fd21ddc9f5099cb65bd2c826a9c -r a70f236803f7d398b4f486342e864add77e9ad3f static/style/src/less/library.less --- a/static/style/src/less/library.less +++ b/static/style/src/less/library.less @@ -49,6 +49,12 @@ } } } +.library_style_container{ + width: 95%; + margin: auto; + margin-top:2em; + overflow: auto !important; +} tr.light td { Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.