1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/68d35caf407f/ Changeset: 68d35caf407f User: martenson Date: 2014-03-24 20:12:48 Summary: libraries: refactor into separate files for model/views/main+router, showing infoicon for public libraries Affected #: 12 files diff -r 33cc6056d83760e5e3b98999b01ecb260423d33c -r 68d35caf407f367c3447a1a6675d6705c8daacf4 lib/galaxy/webapps/galaxy/api/libraries.py --- a/lib/galaxy/webapps/galaxy/api/libraries.py +++ b/lib/galaxy/webapps/galaxy/api/libraries.py @@ -55,10 +55,12 @@ libraries = [] for library in query: item = library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) + if trans.app.security_agent.library_is_public( library, contents=False ): + item[ 'public' ] = True libraries.append( item ) return libraries - @expose_api + @expose_api_anonymous def show( self, trans, id, deleted='False', **kwd ): """ show( self, trans, id, deleted='False', **kwd ) @@ -139,6 +141,9 @@ .. note:: Currently, only admin users can update libraries. Also the library must not be `deleted`. + :param id: the encoded id of the library + :type id: an encoded id string + :param payload: (required) dictionary structure containing:: 'name': new library's name, cannot be empty 'description': new library's description @@ -192,7 +197,7 @@ .. note:: Currently, only admin users can un/delete libraries. :param id: the encoded id of the library to un/delete - :type id: str + :type id: an encoded id string :param undelete: (optional) flag specifying whether the item should be deleted or undeleted, defaults to false: :type undelete: bool diff -r 33cc6056d83760e5e3b98999b01ecb260423d33c -r 68d35caf407f367c3447a1a6675d6705c8daacf4 static/scripts/galaxy.library.js --- a/static/scripts/galaxy.library.js +++ b/static/scripts/galaxy.library.js @@ -1,1192 +1,26 @@ -// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM -// === GALAXY LIBRARY MODULE ==== -// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// === MAIN GALAXY LIBRARY MODULE ==== +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM // global variables -var view = null; var library_router = null; -var responses = []; // dependencies define([ "galaxy.masthead", "utils/utils", - "libs/toastr"], function(mod_masthead, mod_utils, mod_toastr) { - -// MMMMMMMMMMMMMMM -// === Models ==== -// MMMMMMMMMMMMMMM - - // LIBRARY - var Library = Backbone.Model.extend({ - urlRoot: '/api/libraries/' - }); - - // FOLDER AS MODEL - var FolderAsModel = Backbone.Model.extend({ - urlRoot: '/api/folders' - }); - - // LIBRARIES - var Libraries = Backbone.Collection.extend({ - url: '/api/libraries', - - model: Library, - - sort_key: 'name', // default - - sort_order: null, // default - - }); - - // ITEM - var Item = Backbone.Model.extend({ - urlRoot : '/api/libraries/datasets' - }); - - // FOLDER AS COLLECTION - var Folder = Backbone.Collection.extend({ - model: Item - }); - - // CONTAINER for folder contents (folders, items and metadata). - 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; - // update the inner collection - this.get("folder").reset(obj[1].folder_contents); - return obj; - } - }); - - // HISTORY ITEM - var HistoryItem = Backbone.Model.extend({ - urlRoot : '/api/histories/' - }); - - // HISTORY - var GalaxyHistory = Backbone.Model.extend({ - url : '/api/histories/' - }); - - // HISTORIES - var GalaxyHistories = Backbone.Collection.extend({ - url : '/api/histories', - model : GalaxyHistory - }); - -// MMMMMMMMMMMMMM -// === VIEWS ==== -// MMMMMMMMMMMMMM - -//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, - - // initialize - initialize : function(){ - this.folders = []; - 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 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); - - }, - 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 Item(); - var histories = new GalaxyHistories(); - item.id = id; - var self = this; - - //fetch the dataset info - item.fetch({ - success: function (item) { - // TODO can render here already - //fetch user histories for import purposes - histories.fetch({ - success: function (histories){ - self.renderModalAfterFetch(item, histories) - }, - error: function(){ - mod_toastr.error('An error occured during fetching histories:('); - self.renderModalAfterFetch(item) - } - }); - }, - error: function(){ - mod_toastr.error('An error occured during loading dataset details :('); - } - }); - }, - - // show the current dataset in a modal - renderModalAfterFetch : function(item, histories){ - var size = this.size_to_string(item.get('file_size')); - var template = _.template(this.templateDatasetModal(), { item : item, size : size }); - // make modal - var self = this; - this.modal = Galaxy.modal; - this.modal.show({ - closing_events : true, - title : 'Dataset Details', - body : template, - buttons : { - 'Import' : function() { self.importCurrentIntoHistory() }, - 'Download' : function() { self.downloadCurrent() }, - 'Close' : function() { self.modal.hide() } - } - }); - - $(".peek").html('Peek:' + item.get("peek")); - - // show the import-into-history footer only if the request for histories succeeded - if (typeof history.models !== undefined){ - var history_footer_tmpl = _.template(this.templateHistorySelectInModal(), {histories : histories.models}); - $(this.modal.elMain).find('.buttons').prepend(history_footer_tmpl); - // preset last selected history if we know it - if (self.lastSelectedHistory.length > 0) { - $(this.modal.elMain).find('#dataset_import_single').val(self.lastSelectedHistory); - } - } - }, - - // download dataset shown currently in modal - downloadCurrent : function(){ - //disable the buttons - this.modal.disableButton('Import'); - this.modal.disableButton('Download'); - - var library_dataset_id = []; - library_dataset_id.push($('#id_row').attr('data-id')); - var url = '/api/libraries/datasets/download/uncompressed'; - var data = {'ldda_ids' : library_dataset_id}; - - // we assume the view is existent - folderContentView.processDownload(url, data); - this.modal.enableButton('Import'); - this.modal.enableButton('Download'); - }, - - // import dataset shown currently in modal into selected history - importCurrentIntoHistory : function(){ - //disable the buttons - this.modal.disableButton('Import'); - this.modal.disableButton('Download'); - - var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val(); - this.lastSelectedHistory = history_id; //save selected history for further use - - var library_dataset_id = $('#id_row').attr('data-id'); - var historyItem = new 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'); - } - }); - }, - - // select all datasets - selectAll : function (event) { - var selected = event.target.checked; - that = this; - // Iterate each checkbox - $(':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(); - }, - - // Check checkbox on row itself or row checkbox click - selectClickedRow : function (event) { - var checkbox = ''; - var $row; - var source; - if (event.target.localName === 'input'){ - checkbox = event.target; - $row = $(event.target.parentElement.parentElement); - source = 'input'; - } else if (event.target.localName === 'td') { - checkbox = $("#" + event.target.parentElement.id).find(':checkbox')[0]; - $row = $(event.target.parentElement); - source = 'td'; - } - - if (checkbox.checked){ - if (source==='td'){ - checkbox.checked = ''; - this.makeWhiteRow($row); - } else if (source==='input') { - this.makeDarkRow($row); - } - } else { - if (source==='td'){ - checkbox.checked = 'selected'; - this.makeDarkRow($row); - } else if (source==='input') { - this.makeWhiteRow($row); - } - } - this.checkTools(); - }, - - makeDarkRow: function($row){ - $row.removeClass('light'); - $row.find('a').removeClass('light'); - $row.addClass('dark'); - $row.find('a').addClass('dark'); - $row.find('span').removeClass('fa-file-o'); - $row.find('span').addClass('fa-file'); - - }, - - makeWhiteRow: function($row){ - $row.removeClass('dark'); - $row.find('a').removeClass('dark'); - $row.addClass('light'); - $row.find('a').addClass('light'); - $row.find('span').addClass('fa-file-o'); - $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(); - } - }, - - // show bulk import modal - modalBulkImport : function(){ - var self = this; - // fetch histories - var histories = new 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 :('); - } - }); - }, - - // import all selected datasets into history - importAllIntoHistory : function (){ - //disable the button to prevent multiple submission - this.modal.disableButton('Import'); - - var history_id = $("select[name=dataset_import_bulk] option:selected").val(); - var history_name = $("select[name=dataset_import_bulk] option:selected").text(); - - var dataset_ids = []; - $('#folder_table').find(':checked').each(function(){ - if (this.parentElement.parentElement.id != '') { - dataset_ids.push(this.parentElement.parentElement.id); - } - }); - var progress_bar_tmpl = _.template(this.templateProgressBar(), { history_name : history_name }); - $(this.modal.elMain).find('.modal-body').html(progress_bar_tmpl); - - // 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 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 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 !== ''; - } - - }); - -// galaxy library view -var GalaxyLibraryview = Backbone.View.extend({ - el: '#libraries_element', - - events: { - 'click .edit_library_btn' : 'edit_button_event', - 'click .save_library_btn' : 'save_library_modification', - 'click .cancel_library_btn' : 'cancel_library_modification', - 'click .delete_library_btn' : 'delete_library', - 'click .undelete_library_btn' : 'undelete_library' - }, - - modal: null, - - collection: null, - - // initialize - initialize : function(){ - var viewContext = this; - this.collection = new Libraries(); - - this.collection.fetch({ - success: function(libraries){ - viewContext.render(); - // initialize the library tooltips - $("#center [data-toggle]").tooltip(); - // modification of upper DOM element to show scrollbars due to the #center element inheritance - $("#center").css('overflow','auto'); - }, - error: function(model, response){ - mod_toastr.error('An error occured. Please try again.'); - } - }) - }, - - /** Renders the libraries table either from the object's own collection, - or from a given array of library models, - or renders an empty list in case no data is given. */ - render: function (options) { - var template = this.templateLibraryList(); - var libraries_to_render = null; - var include_deleted = false; - 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; - } - - if (this.collection !== null && models === null){ - 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});; - } - } else if (models !== null){ - libraries_to_render = models; - } else { - libraries_to_render = []; - } - - this.$el.html(template({libraries: libraries_to_render, order: this.collection.sort_order})); - }, - - /** Sorts the underlying collection according to the parameters received through URL. - Currently supports only sorting by name. */ - sortLibraries: function(sort_by, order){ - if (sort_by === 'name'){ - 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 - 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 - return 0; // equal - } - } - this.collection.sort(); - } - - }, - -// MMMMMMMMMMMMMMMMMM -// === TEMPLATES ==== -// MMMMMMMMMMMMMMMMMM - - templateLibraryList: function(){ - tmpl_array = []; - - tmpl_array.push('<div class="library_container table-responsive">'); - tmpl_array.push('<% if(libraries.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 title="Click to reverse order" href="#sort/name/<% if(order==="desc"||order===null){print("asc")}else{print("desc")} %>">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>'); - tmpl_array.push(' <% _.each(libraries, function(library) { %>'); - tmpl_array.push(' <tr class="<% if(library.get("deleted") === true){print("active");}%>" data-id="<%- library.get("id") %>">'); - 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(' <td class="right-center">'); - tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify library" class="primary-button btn-xs edit_library_btn" type="button"><span class="fa fa-pencil"></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="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="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="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="display:none;"><span class="fa fa-unlock"> Undelete</span></button>'); - tmpl_array.push(' </td>'); - tmpl_array.push(' </tr>'); - tmpl_array.push(' <% }); %>'); - 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(''); - }, - - save_library_modification: function(event){ - var $library_row = $(event.target).closest('tr'); - var library = this.collection.get($library_row.data('id')); - - var is_changed = false; - - var new_name = $library_row.find('.input_library_name').val(); - if (typeof new_name !== 'undefined' && new_name !== library.get('name') ){ - if (new_name.length > 2){ - library.set("name", new_name); - is_changed = true; - } else{ - mod_toastr.warning('Library name has to be at least 3 characters long'); - return - } - } - - var new_description = $library_row.find('.input_library_description').val(); - if (typeof new_description !== 'undefined' && new_description !== library.get('description') ){ - library.set("description", new_description); - is_changed = true; - } - - var new_synopsis = $library_row.find('.input_library_synopsis').val(); - if (typeof new_synopsis !== 'undefined' && new_synopsis !== library.get('synopsis') ){ - library.set("synopsis", new_synopsis); - is_changed = true; - } - - if (is_changed){ - library.save(null, { - patch: true, - success: function(library) { - mod_toastr.success('Changes to library saved'); - galaxyLibraryview.toggle_library_modification($library_row); - }, - error: function(model, response){ - mod_toastr.error('An error occured during updating the library :('); - } - }); - } - }, - - edit_button_event: function(event){ - this.toggle_library_modification($(event.target).closest('tr')); - }, - - toggle_library_modification: function($library_row){ - var library = this.collection.get($library_row.data('id')); - - $library_row.find('.edit_library_btn').toggle(); - $library_row.find('.save_library_btn').toggle(); - $library_row.find('.cancel_library_btn').toggle(); - if (library.get('deleted')){ - $library_row.find('.undelete_library_btn').toggle(); - } else { - $library_row.find('.delete_library_btn').toggle(); - } - - if ($library_row.find('.edit_library_btn').is(':hidden')){ - // library name - var current_library_name = library.get('name'); - var new_html = '<input type="text" class="form-control input_library_name" placeholder="name">'; - $library_row.children('td').eq(0).html(new_html); - if (typeof current_library_name !== undefined){ - $library_row.find('.input_library_name').val(current_library_name); - } - // library description - var current_library_description = library.get('description'); - var new_html = '<input type="text" class="form-control input_library_description" placeholder="description">'; - $library_row.children('td').eq(1).html(new_html); - if (typeof current_library_description !== undefined){ - $library_row.find('.input_library_description').val(current_library_description); - } - // library synopsis - var current_library_synopsis = library.get('synopsis'); - var new_html = '<input type="text" class="form-control input_library_synopsis" placeholder="synopsis">'; - $library_row.children('td').eq(2).html(new_html); - if (typeof current_library_synopsis !== undefined){ - $library_row.find('.input_library_synopsis').val(current_library_synopsis); - } - } else { - $library_row.children('td').eq(0).html(library.get('name')); - $library_row.children('td').eq(1).html(library.get('description')); - $library_row.children('td').eq(2).html(library.get('synopsis')); - } - - }, - - cancel_library_modification: function(event){ - var $library_row = $(event.target).closest('tr'); - var library = this.collection.get($library_row.data('id')); - this.toggle_library_modification($library_row); - - $library_row.children('td').eq(0).html(library.get('name')); - $library_row.children('td').eq(1).html(library.get('description')); - $library_row.children('td').eq(2).html(library.get('synopsis')); - }, - - undelete_library: function(event){ - var $library_row = $(event.target).closest('tr'); - var library = this.collection.get($library_row.data('id')); - this.toggle_library_modification($library_row); - - // mark the library undeleted - library.url = library.urlRoot + library.id + '?undelete=true'; - library.destroy({ - success: function (library) { - // add the newly undeleted library back to the collection - // backbone does not accept changes through destroy, so update it too - library.set('deleted', false); - galaxyLibraryview.collection.add(library); - $library_row.removeClass('active'); - mod_toastr.success('Library has been undeleted'); - }, - error: function(){ - mod_toastr.error('An error occured while undeleting the library :('); - } - }); - }, - - delete_library: function(event){ - var $library_row = $(event.target).closest('tr'); - var library = this.collection.get($library_row.data('id')); - this.toggle_library_modification($library_row); - - // mark the library deleted - library.destroy({ - success: function (library) { - // add the new deleted library back to the collection - $library_row.remove(); - library.set('deleted', true); - galaxyLibraryview.collection.add(library); - mod_toastr.success('Library has been marked deleted'); - }, - error: function(){ - mod_toastr.error('An error occured during deleting the library :('); - } - }); - - }, - - redirectToHome: function(){ - window.location = '../'; - }, - redirectToLogin: function(){ - window.location = '/user/login'; - }, - - // show/hide create library modal - show_library_modal : function (event){ - event.preventDefault(); - event.stopPropagation(); - - // create modal - var self = this; - this.modal = Galaxy.modal; - this.modal.show({ - closing_events : true, - title : 'Create New Library', - body : this.templateNewLibraryInModal(), - buttons : { - 'Create' : function() {self.create_new_library_event()}, - 'Close' : function() {self.modal.hide();} - } - }); - }, - - // create the new library from modal - create_new_library_event: function(){ - var libraryDetails = this.serialize_new_library(); - if (this.validate_new_library(libraryDetails)){ - var library = new Library(); - var self = this; - library.save(libraryDetails, { - success: function (library) { - self.collection.add(library); - self.modal.hide(); - self.clear_library_modal(); - self.render(); - mod_toastr.success('Library created'); - }, - error: function(){ - mod_toastr.error('An error occured :('); - } - }); - } else { - mod_toastr.error('Library\'s name is missing'); - } - return false; - }, - - // clear the library modal once saved - clear_library_modal : function(){ - $("input[name='Name']").val(''); - $("input[name='Description']").val(''); - $("input[name='Synopsis']").val(''); - }, - - // serialize data from the form - serialize_new_library : function(){ - return { - name: $("input[name='Name']").val(), - description: $("input[name='Description']").val(), - synopsis: $("input[name='Synopsis']").val() - }; - }, - - // validate new library info - validate_new_library: function(libraryDetails){ - return libraryDetails.name !== ''; - } -}); - -var ToolbarView = Backbone.View.extend({ - el: '#center', - - events: { - 'click #create_new_library_btn' : 'delegate_modal', - 'click #include_deleted_chk' : 'check_include_deleted' - }, - - initialize: function(){ - this.render(); - }, - - delegate_modal: function(event){ - // probably should refactor to have this functionality in this view, not in the library view - galaxyLibraryview.show_library_modal(event); - }, - - // include or exclude deleted libraries from the view - check_include_deleted: function(event){ - if (event.target.checked){ - galaxyLibraryview.render( {'with_deleted': true} ); - } else{ - galaxyLibraryview.render({'with_deleted': false}); - } - }, - - render: function(){ - var toolbar_template = this.templateToolBar() - this.$el.html(toolbar_template()) - }, - - templateToolBar: function(){ - tmpl_array = []; - - tmpl_array.push('<div id="libraries_container" style="width: 90%; margin: auto; margin-top:2em; overflow: auto !important; ">'); - // 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>'); - tmpl_array.push(' <div id="library_toolbar">'); - tmpl_array.push(' <input id="include_deleted_chk" style="margin: 0;" type="checkbox">include deleted</input>'); - tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Library" id="create_new_library_btn" class="primary-button" type="button"><span class="fa fa-plus"></span> New Library</button>'); - tmpl_array.push(' </div>'); - tmpl_array.push(' </div>'); - tmpl_array.push(' <div id="libraries_element">'); - tmpl_array.push(' </div>'); - tmpl_array.push('</div>'); - - return _.template(tmpl_array.join('')); - } -}) + "libs/toastr", + "mvc/library/library-model", + "mvc/library/library-folderlist-view", + "mvc/library/library-librarylist-view", + "mvc/library/library-librarytoolbar-view"], +function(mod_masthead, + mod_utils, + mod_toastr, + mod_library_model, + mod_folderlist_view, + mod_librarylist_view, + mod_librarytoolbar_view) { //ROUTER var LibraryRouter = Backbone.Router.extend({ @@ -1202,16 +36,17 @@ var GalaxyLibrary = Backbone.View.extend({ initialize : function(){ - toolbarView = new ToolbarView(); - galaxyLibraryview = new GalaxyLibraryview(); + toolbarView = new mod_librarytoolbar_view.ToolbarView(); + galaxyLibraryview = new mod_librarylist_view.GalaxyLibraryview(); library_router = new LibraryRouter(); - folderContentView = new FolderContentView(); + + folderContentView = null; library_router.on('route:libraries', function() { // initialize and render the toolbar first - toolbarView = new ToolbarView(); + toolbarView = new mod_librarytoolbar_view.ToolbarView(); // initialize and render libraries second - galaxyLibraryview = new GalaxyLibraryview(); + galaxyLibraryview = new mod_librarylist_view.GalaxyLibraryview(); }); library_router.on('route:sort_libraries', function(sort_by, order) { @@ -1222,6 +57,7 @@ library_router.on('route:folder_content', function(id) { // render folder contents + if (!folderContentView) {folderContentView = new mod_folderlist_view.FolderContentView();} folderContentView.render({id: id}); }); diff -r 33cc6056d83760e5e3b98999b01ecb260423d33c -r 68d35caf407f367c3447a1a6675d6705c8daacf4 static/scripts/mvc/library/library-folderlist-view.js --- /dev/null +++ b/static/scripts/mvc/library/library-folderlist-view.js @@ -0,0 +1,713 @@ +// dependencies +define([ + "galaxy.masthead", + "utils/utils", + "libs/toastr", + "mvc/library/library-model"], +function(mod_masthead, + mod_utils, + mod_toastr, + mod_library_model) { + + //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, + + // initialize + initialize : function(){ + this.folders = []; + 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); + + }, + 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 :('); + } + }); + }, + + // show the current dataset in a modal + renderModalAfterFetch : function(item, histories){ + var size = this.size_to_string(item.get('file_size')); + var template = _.template(this.templateDatasetModal(), { item : item, size : size }); + // make modal + var self = this; + this.modal = Galaxy.modal; + this.modal.show({ + closing_events : true, + title : 'Dataset Details', + body : template, + buttons : { + 'Import' : function() { self.importCurrentIntoHistory() }, + 'Download' : function() { self.downloadCurrent() }, + 'Close' : function() { self.modal.hide() } + } + }); + + $(".peek").html('Peek:' + item.get("peek")); + + // show the import-into-history footer only if the request for histories succeeded + if (typeof history.models !== undefined){ + var history_footer_tmpl = _.template(this.templateHistorySelectInModal(), {histories : histories.models}); + $(this.modal.elMain).find('.buttons').prepend(history_footer_tmpl); + // preset last selected history if we know it + if (self.lastSelectedHistory.length > 0) { + $(this.modal.elMain).find('#dataset_import_single').val(self.lastSelectedHistory); + } + } + }, + + // download dataset shown currently in modal + downloadCurrent : function(){ + //disable the buttons + this.modal.disableButton('Import'); + this.modal.disableButton('Download'); + + var library_dataset_id = []; + library_dataset_id.push($('#id_row').attr('data-id')); + var url = '/api/libraries/datasets/download/uncompressed'; + var data = {'ldda_ids' : library_dataset_id}; + + // we assume the view is existent + folderContentView.processDownload(url, data); + this.modal.enableButton('Import'); + this.modal.enableButton('Download'); + }, + + // import dataset shown currently in modal into selected history + importCurrentIntoHistory : function(){ + //disable the buttons + this.modal.disableButton('Import'); + this.modal.disableButton('Download'); + + var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val(); + this.lastSelectedHistory = history_id; //save selected history for further use + + var library_dataset_id = $('#id_row').attr('data-id'); + var historyItem = new mod_library_model.HistoryItem(); + var self = this; + historyItem.url = historyItem.urlRoot + history_id + '/contents'; + + // save the dataset into selected history + historyItem.save({ content : library_dataset_id, source : 'library' }, { success : function(){ + mod_toastr.success('Dataset imported'); + //enable the buttons + self.modal.enableButton('Import'); + self.modal.enableButton('Download'); + }, error : function(){ + mod_toastr.error('An error occured! Dataset not imported. Please try again.') + //enable the buttons + self.modal.enableButton('Import'); + self.modal.enableButton('Download'); + } + }); + }, + + // select all datasets + selectAll : function (event) { + var selected = event.target.checked; + that = this; + // Iterate each checkbox + $(':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(); + }, + + // Check checkbox on row itself or row checkbox click + selectClickedRow : function (event) { + var checkbox = ''; + var $row; + var source; + if (event.target.localName === 'input'){ + checkbox = event.target; + $row = $(event.target.parentElement.parentElement); + source = 'input'; + } else if (event.target.localName === 'td') { + checkbox = $("#" + event.target.parentElement.id).find(':checkbox')[0]; + $row = $(event.target.parentElement); + source = 'td'; + } + + if (checkbox.checked){ + if (source==='td'){ + checkbox.checked = ''; + this.makeWhiteRow($row); + } else if (source==='input') { + this.makeDarkRow($row); + } + } else { + if (source==='td'){ + checkbox.checked = 'selected'; + this.makeDarkRow($row); + } else if (source==='input') { + this.makeWhiteRow($row); + } + } + this.checkTools(); + }, + + makeDarkRow: function($row){ + $row.removeClass('light'); + $row.find('a').removeClass('light'); + $row.addClass('dark'); + $row.find('a').addClass('dark'); + $row.find('span').removeClass('fa-file-o'); + $row.find('span').addClass('fa-file'); + + }, + + makeWhiteRow: function($row){ + $row.removeClass('dark'); + $row.find('a').removeClass('dark'); + $row.addClass('light'); + $row.find('a').addClass('light'); + $row.find('span').addClass('fa-file-o'); + $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(); + } + }, + + // 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 :('); + } + }); + }, + + // import all selected datasets into history + importAllIntoHistory : function (){ + //disable the button to prevent multiple submission + this.modal.disableButton('Import'); + + var history_id = $("select[name=dataset_import_bulk] option:selected").val(); + var history_name = $("select[name=dataset_import_bulk] option:selected").text(); + + var dataset_ids = []; + $('#folder_table').find(':checked').each(function(){ + if (this.parentElement.parentElement.id != '') { + dataset_ids.push(this.parentElement.parentElement.id); + } + }); + var progress_bar_tmpl = _.template(this.templateProgressBar(), { history_name : history_name }); + $(this.modal.elMain).find('.modal-body').html(progress_bar_tmpl); + + // 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 +return { + FolderContentView: FolderContentView +}; + +}); This diff is so big that we needed to truncate the remainder. Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.