From 5616b289cbcf7f813c251328e8b772c32d982467 Mon Sep 17 00:00:00 2001 From: Trevor Wennblom Date: Wed, 9 Apr 2014 21:02:33 +0000 Subject: [PATCH 01/28] job_directory -> jobs_directory --- job_conf.xml.sample_advanced | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/job_conf.xml.sample_advanced b/job_conf.xml.sample_advanced index 9e0b589b627..da3b34c1dfb 100644 --- a/job_conf.xml.sample_advanced +++ b/job_conf.xml.sample_advanced @@ -110,7 +110,7 @@ + + + + + + + diff --git a/test/qunit/tests/workflow_editor_tests.js b/test/qunit/tests/workflow_editor_tests.js new file mode 100644 index 00000000000..e065c1125de --- /dev/null +++ b/test/qunit/tests/workflow_editor_tests.js @@ -0,0 +1,379 @@ +/* global define, QUnit, module, test, ok, equal, deepEqual, notEqual */ +/* global Workflow, CanvasManager, InputTerminal, Connector, add_node */ +define([ + "galaxy.workflow_editor.canvas", + "jquery", + "sinon-qunit" +], function( + workflowEditor, + $, + sinon +){ + "use strict"; + + // globals cosumed by workflow editor + window.show_form_for_tool = sinon.spy(); + window.workflow = null; + window.canvas_manager = null; + + // Stub used over stubbing issubtype for unit testing datatype comparisons. + var issubtypeStub = null; + + QUnit.moduleStart(function() { + if( issubtypeStub === null) { + issubtypeStub = sinon.stub( window, "issubtype" ); + } + }); + QUnit.moduleDone(function() { + if( issubtypeStub !== null) { + issubtypeStub.restore(); + issubtypeStub = null; + } + }); + + var with_canvas_container = function( f ) { + var canvas_container = $("
"); + $("body").append( canvas_container ); + f( canvas_container ); + canvas_container.remove(); + }; + + var with_workflow_global = function( f ) { + var overview = $( "
" ); + var canvas_viewport = $( "
" ); + + $("body").append( overview, canvas_viewport ); + window.canvas_manager = new CanvasManager( canvas_viewport, overview ); + with_canvas_container( function( canvas_container ) { + window.workflow = new Workflow( canvas_container ); + f( window.workflow ); + window.workflow = null; + } ); + window.canvas_manager = null; + overview.remove(); + canvas_viewport.remove(); + }; + + module( "Input terminal model test", { + setup: function() { + this.node = { }; + this.element = $( "
" ); + this.input_terminal = new InputTerminal( this.element, [ "txt" ] ); + this.input_terminal.node = this.node; + }, + test_connector: function( attr ) { + var connector = attr || {}; + this.input_terminal.connectors.push( connector ); + return connector; + }, + with_test_connector: function( attr, f ) { + this.test_connector( attr ); + f(); + this.reset_connectors(); + }, + reset_connectors: function( ) { + this.input_terminal.connectors = []; + }, + test_accept: function( other ) { + other = other || { node: {}, datatypes: [ "txt" ] }; + return this.input_terminal.can_accept( other ); + } + } ); + + test( "test connect", function() { + this.node.changed = sinon.spy(); + + var connector = {}; + this.input_terminal.connect( connector ); + + // Assert node changed called + ok( this.node.changed.called ); + // Assert connectors updated + ok( this.input_terminal.connectors[ 0 ] === connector ); + } ); + + test( "test disconnect", function() { + this.node.changed = sinon.spy(); + + var connector = this.test_connector( {} ); + this.input_terminal.disconnect( connector ); + + // Assert node changed called + ok( this.node.changed.called ); + // Assert connectors updated + equal( this.input_terminal.connectors.length, 0 ); + } ); + + test( "test redraw", function() { + var connector = this.test_connector( { redraw: sinon.spy() } ); + this.input_terminal.redraw(); + // Assert connectors were redrawn + ok( connector.redraw.called ); + } ); + + test( "test destroy", function() { + var connector = this.test_connector( { destroy: sinon.spy() } ); + + this.input_terminal.destroy(); + // Assert connectors were redrawn + ok( connector.destroy.called ); + } ); + + test( "can accept correct datatype", function() { + issubtypeStub.returns(true); + ok( this.test_accept() ) ; + } ); + + test( "cannot accept incorrect datatypes", function() { + issubtypeStub.returns(false); + ok( ! this.test_accept() ); + } ); + + test( "can accept inputs", function() { + issubtypeStub.returns(false); + // Other is data input module - always accept (currently - could be + // more intelligent by looking at what else input is connected to. + var other = { node: {}, datatypes: [ "input" ] }; + ok( this.test_accept( other ) ); + } ); + + test( "cannot accept when already connected", function() { + issubtypeStub.returns(true); + var self = this; + // If other is subtype but already connected, cannot accept + this.with_test_connector( {}, function() { + ok( ! self.test_accept() ); + } ); + } ); + + module( "Connector test", { + + } ); + + test( "connects only if both valid handles", function() { + var input = { connect: sinon.spy() }; + var output = { connect: sinon.spy() }; + new Connector( input, null ); + new Connector( null, output ); + // Not attempts to connect... + ok( ! input.connect.called ); + ok( ! output.connect.called ); + + new Connector( input, output ); + ok( input.connect.called ); + ok( output.connect.called ); + }); + + test( "default attributes", function() { + var input = { connect: sinon.spy() }; + var output = { connect: sinon.spy() }; + var connector = new Connector( input, output ); + + equal( connector.dragging, false ); + equal( connector.canvas, null ); + equal( connector.inner_color, "#FFFFFF" ); + equal( connector.outer_color, "#D8B365" ); + } ); + + test( "destroy", function() { + var input = { connect: sinon.spy(), disconnect: sinon.spy() }; + var output = { connect: sinon.spy(), disconnect: sinon.spy() }; + var connector = new Connector( input, output ); + + connector.destroy(); + ok( input.disconnect.called ); + ok( output.disconnect.called ); + } ); + + test( "initial redraw", function() { + with_canvas_container( function( canvas_container ) { + var input = { connect: sinon.spy(), element: $("
") }; + var output = { connect: sinon.spy(), element: $("
") }; + var connector = new Connector( input, output ); + + connector.redraw(); + // Ensure canvas gets set + ok( connector.canvas ); + // Ensure it gest added to canvas container + equal( canvas_container.children()[ 0 ], connector.canvas ); + } ); + } ); + + module( "Node unit test", { + setup: function() { + this.input_terminal = { destroy: sinon.spy(), redraw: sinon.spy() }; + this.output_terminal = { destroy: sinon.spy(), redraw: sinon.spy() }; + this.element = $("
"); + this.node = new Node( this.element ); + this.node.input_terminals.i1 = this.input_terminal; + this.node.output_terminals.o1 = this.output_terminal; + }, + $: function( selector ) { + return $( this.node.element.find( selector ) ); + }, + expect_workflow_node_changed: function( f ) { + var node = this.node; + with_workflow_global( function( workflow ) { + var node_changed_spy = sinon.spy( workflow, "node_changed" ); + f(); + ok( node_changed_spy.calledWith( node ) ); + } ); + }, + init_field_data_simple: function() { + var data = { + data_inputs: [ {name: "input1", extensions: [ "data" ] } ], + data_outputs: [ {name: "output1", extensions: [ "data" ] } ], + }; + this.node.init_field_data( data ); + }, + update_field_data_with_new_input: function() { + var new_data = { + data_inputs: [ + { name: "input1", extensions: [ "data" ] }, + { name: "extra_0|input1", extensions: [ "data" ] }, + ], + data_outputs: [ {name: "output1", extensions: [ "data" ] } ], + post_job_actions: "{}" + }; + this.node.update_field_data( new_data ); + } + } ); + + test( "make active", function() { + ok( ! this.element.hasClass( "toolForm-active" ) ); + this.node.make_active(); + ok( this.element.hasClass( "toolForm-active" ) ); + } ); + + test( "destroy", function() { + var test = this; + with_workflow_global( function( workflow ) { + var remove_node_spy = sinon.spy( workflow, "remove_node" ); + test.node.destroy(); + ok( test.input_terminal.destroy.called ); + ok( test.output_terminal.destroy.called ); + ok( remove_node_spy.calledWith( test.node ) ); + } ); + } ); + + test( "error", function() { + // Test body of toolFormBody div updated and workflow notified of change. + var test = this; + this.expect_workflow_node_changed( function() { + test.node.error( "TOOL ERROR" ); + equal( $( test.$(".toolFormBody").children()[ 0 ] ).html(), "TOOL ERROR" ); + } ); + } ); + + test( "init_field_data properties", function() { + var node = this.node; + this.expect_workflow_node_changed( function( ) { + var data = { + data_inputs: [], + data_outputs: [], + type: "tool", + name: "cat1", + form_html: "
", + tool_state: "ok", + tool_errors: false, + tooltip: "tool tooltip", + annotation: "tool annotation", + workflow_outputs: [ "out1" ], + }; + node.init_field_data( data ); + equal( node.type, "tool" ); + equal( node.name, "cat1" ); + equal( node.form_html, "" ); + equal( node.tool_state, "ok" ); + equal( node.tooltip, "tool tooltip" ); + equal( node.annotation, "tool annotation" ); + deepEqual( node.post_job_actions, {} ); + deepEqual( node.workflow_outputs, [ "out1" ] ); + } ); + } ); + + test( "init_field_data data", function() { + var test = this; + this.expect_workflow_node_changed( function( ) { + // pre-init not tool form body... + equal( test.$( ".output-terminal" ).length, 0 ); + equal( test.$( ".input-terminal" ).length, 0 ); + equal( test.$( ".rule" ).length, 0 ); + + test.init_field_data_simple(); + + // After init tool form should have three "rows"/divs - , inputs div, one output, and rule... + equal( test.$( ".output-terminal" ).length, 1 ); + equal( test.$( ".input-terminal" ).length, 1 ); + equal( test.$( ".rule" ).length, 1 ); + + equal( test.$( ".toolFormBody" ).children().length, 3 ); + } ); + } ); + + test( "update_field_data updated data inputs and outputs", function() { + var test = this; + this.expect_workflow_node_changed( function( ) { + // Call init with one input and output. + test.init_field_data_simple(); + + test.update_field_data_with_new_input(); + + // Now there are 2 inputs... + equal( test.$( ".input-terminal" ).length, 2 ); + equal( test.$( ".output-terminal" ).length, 1 ); + equal( test.$( ".rule" ).length, 1 ); + } ); + } ); + + test( "update_field_data preserves connectors", function() { + var test = this; + var node = this.node; + this.expect_workflow_node_changed( function( ) { + // Call init with one input and output. + test.init_field_data_simple(); + + var connector = new Connector(); + var old_input_terminal = node.input_terminals.input1; + old_input_terminal.connectors.push( connector ); + + test.update_field_data_with_new_input(); + + var new_input_terminal = node.input_terminals.input1; + equal( old_input_terminal, old_input_terminal ); + notEqual( old_input_terminal, new_input_terminal ); + equal( connector, new_input_terminal.connectors[ 0 ] ); + } ); + } ); + + test( "update_field_data destroys old terminals", function() { + var test = this; + var node = this.node; + this.expect_workflow_node_changed( function( ) { + var data = { + data_inputs: [ { name: "input1", extensions: [ "data" ] }, + { name: "willDisappear", extensions: [ "data" ] } ], + data_outputs: [ {name: "output1", extensions: [ "data" ] } ], + }; + node.init_field_data( data ); + + var old_input_terminal = node.input_terminals.willDisappear; + var destroy_spy = sinon.spy( old_input_terminal, "destroy" ); + // Update + test.update_field_data_with_new_input(); + + ok( destroy_spy.called ); + } ); + } ); + + module( "add_node" ); + + test( "node added to workflow", function() { + with_workflow_global( function( workflow ) { + var add_node_spy = sinon.spy( workflow, "add_node" ); + var node = add_node( "tool", "Cat Files", "cat1" ); + ok( add_node_spy.calledWith( node ) ); + } ); + } ); + +}); \ No newline at end of file From 86ee4fdabfaf431d0263ae3921424f8e80d63fde Mon Sep 17 00:00:00 2001 From: John Chilton Date: Thu, 10 Apr 2014 13:31:48 -0500 Subject: [PATCH 16/28] Simplify enable_output_terminal and enable_output_terminal in workflow editor. These functions were taking in a single element and then looping through it. I hope this is not some intententional jQuery pattern to change the value of 'this' I don't quite understand and is just a remnant of when some loop over inputs was on the inside of this function or some other such refactoring. --- .../scripts/galaxy.workflow_editor.canvas.js | 177 +++++++++--------- 1 file changed, 87 insertions(+), 90 deletions(-) diff --git a/static/scripts/galaxy.workflow_editor.canvas.js b/static/scripts/galaxy.workflow_editor.canvas.js index f7e1d3f2d79..c0c9f5b6afe 100644 --- a/static/scripts/galaxy.workflow_editor.canvas.js +++ b/static/scripts/galaxy.workflow_editor.canvas.js @@ -172,101 +172,98 @@ function Node( element ) { } $.extend( Node.prototype, { new_input_terminal : function( input ) { - var t = $("
"); + var t = $("
")[ 0 ]; this.enable_input_terminal( t, input.name, input.extensions, input.multiple ); return t; }, - enable_input_terminal : function( elements, name, types, multiple ) { + enable_input_terminal : function( element, name, types, multiple ) { var node = this; - $(elements).each( function() { - var terminal = this.terminal = new InputTerminal( this, types, multiple ); - terminal.node = node; - terminal.name = name; - $(this).bind( "dropinit", function( e, d ) { - // Accept a dragable if it is an output terminal and has a - // compatible type - return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal ); - }).bind( "dropstart", function( e, d ) { - if (d.proxy.terminal) { - d.proxy.terminal.connectors[0].inner_color = "#BBFFBB"; - } - }).bind( "dropend", function ( e, d ) { - if (d.proxy.terminal) { - d.proxy.terminal.connectors[0].inner_color = "#FFFFFF"; - } - }).bind( "drop", function( e, d ) { - ( new Connector( d.drag.terminal, terminal ) ).redraw(); - }).bind( "hover", function() { - // If connected, create a popup to allow disconnection - if ( terminal.connectors.length > 0 ) { - // Create callout - var t = $("
") - .css( { display: 'none' } ) - .appendTo( "body" ) - .append( - $("
").append( - $("
").addClass("fa-icon-button fa fa-times").click( function() { - $.each( terminal.connectors, function( _, x ) { - if (x) { - x.destroy(); - } - }); - t.remove(); - }))) - .bind( "mouseleave", function() { - $(this).remove(); - }); - // Position it and show - t.css({ - top: $(this).offset().top - 2, - left: $(this).offset().left - t.width(), - 'padding-right': $(this).width() - }).show(); - } - }); - node.input_terminals[name] = terminal; + + var terminal = element.terminal = new InputTerminal( element, types, multiple ); + terminal.node = node; + terminal.name = name; + $(element).bind( "dropinit", function( e, d ) { + // Accept a dragable if it is an output terminal and has a + // compatible type + return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal ); + }).bind( "dropstart", function( e, d ) { + if (d.proxy.terminal) { + d.proxy.terminal.connectors[0].inner_color = "#BBFFBB"; + } + }).bind( "dropend", function ( e, d ) { + if (d.proxy.terminal) { + d.proxy.terminal.connectors[0].inner_color = "#FFFFFF"; + } + }).bind( "drop", function( e, d ) { + ( new Connector( d.drag.terminal, terminal ) ).redraw(); + }).bind( "hover", function() { + // If connected, create a popup to allow disconnection + if ( terminal.connectors.length > 0 ) { + // Create callout + var t = $("
") + .css( { display: 'none' } ) + .appendTo( "body" ) + .append( + $("
").append( + $("
").addClass("fa-icon-button fa fa-times").click( function() { + $.each( terminal.connectors, function( _, x ) { + if (x) { + x.destroy(); + } + }); + t.remove(); + }))) + .bind( "mouseleave", function() { + $(this).remove(); + }); + // Position it and show + t.css({ + top: $(element).offset().top - 2, + left: $(element).offset().left - t.width(), + 'padding-right': $(element).width() + }).show(); + } }); + node.input_terminals[name] = terminal; }, - enable_output_terminal : function( elements, name, type ) { + enable_output_terminal : function( element, name, type ) { var node = this; - $(elements).each( function() { - var terminal_element = this; - var terminal = this.terminal = new OutputTerminal( this, type ); - terminal.node = node; - terminal.name = name; - $(this).bind( "dragstart", function( e, d ) { - $( d.available ).addClass( "input-terminal-active" ); - // Save PJAs in the case of change datatype actions. - workflow.check_changes_in_active_form(); - // Drag proxy div - var h = $( '
' ) - .appendTo( "#canvas-container" ).get(0); - // Terminal and connection to display noodle while dragging - h.terminal = new OutputTerminal( h ); - var c = new Connector(); - c.dragging = true; - c.connect( this.terminal, h.terminal ); - return h; - }).bind( "drag", function ( e, d ) { - var onmove = function() { - var po = $(d.proxy).offsetParent().offset(), - x = d.offsetX - po.left, - y = d.offsetY - po.top; - $(d.proxy).css( { left: x, top: y } ); - d.proxy.terminal.redraw(); - // FIXME: global - canvas_manager.update_viewport_overlay(); - }; - onmove(); - $("#canvas-container").get(0).scroll_panel.test( e, onmove ); - }).bind( "dragend", function ( e, d ) { - d.proxy.terminal.connectors[0].destroy(); - $(d.proxy).remove(); - $( d.available ).removeClass( "input-terminal-active" ); - $("#canvas-container").get(0).scroll_panel.stop(); - }); - node.output_terminals[name] = terminal; + var terminal_element = element; + var terminal = element.terminal = new OutputTerminal( element, type ); + terminal.node = node; + terminal.name = name; + $(element).bind( "dragstart", function( e, d ) { + $( d.available ).addClass( "input-terminal-active" ); + // Save PJAs in the case of change datatype actions. + workflow.check_changes_in_active_form(); + // Drag proxy div + var h = $( '
' ) + .appendTo( "#canvas-container" ).get(0); + // Terminal and connection to display noodle while dragging + h.terminal = new OutputTerminal( h ); + var c = new Connector(); + c.dragging = true; + c.connect( element.terminal, h.terminal ); + return h; + }).bind( "drag", function ( e, d ) { + var onmove = function() { + var po = $(d.proxy).offsetParent().offset(), + x = d.offsetX - po.left, + y = d.offsetY - po.top; + $(d.proxy).css( { left: x, top: y } ); + d.proxy.terminal.redraw(); + // FIXME: global + canvas_manager.update_viewport_overlay(); + }; + onmove(); + $("#canvas-container").get(0).scroll_panel.test( e, onmove ); + }).bind( "dragend", function ( e, d ) { + d.proxy.terminal.connectors[0].destroy(); + $(d.proxy).remove(); + $( d.available ).removeClass( "input-terminal-active" ); + $("#canvas-container").get(0).scroll_panel.stop(); }); + node.output_terminals[name] = terminal; }, redraw : function () { $.each( this.input_terminals, function( _, t ) { @@ -342,7 +339,7 @@ $.extend( Node.prototype, { } $.each( data.data_outputs, function( i, output ) { var t = $( "
" ); - node.enable_output_terminal( t, output.name, output.extensions ); + node.enable_output_terminal( t[ 0 ], output.name, output.extensions ); var label = output.name; if ( output.extensions.indexOf( 'input' ) < 0 ) { label = label + " (" + output.extensions.join(", ") + ")"; @@ -429,8 +426,8 @@ $.extend( Node.prototype, { $(this).find( ".input-terminal" ).each( function() { var c = this.terminal.connectors[0]; if ( c ) { - t[0].terminal.connectors[0] = c; - c.handle2 = t[0].terminal; + t.terminal.connectors[0] = c; + c.handle2 = t.terminal; } }); $(this).remove(); From 0dd3187401e28551bf73bb6081960783d5722b69 Mon Sep 17 00:00:00 2001 From: Martin Cech Date: Thu, 10 Apr 2014 15:05:33 -0400 Subject: [PATCH 17/28] data libraries: API refactoring and improvements; backbone decoupling; role UI first implementation --- .../webapps/galaxy/api/folder_contents.py | 147 ++-- lib/galaxy/webapps/galaxy/api/folders.py | 11 +- lib/galaxy/webapps/galaxy/api/libraries.py | 14 +- .../webapps/galaxy/api/library_contents.py | 3 +- static/scripts/galaxy.library.js | 40 +- .../mvc/library/library-folderlist-view.js | 761 ++++-------------- .../mvc/library/library-librarylist-view.js | 45 +- .../mvc/library/library-libraryrow-view.js | 25 +- .../library/library-librarytoolbar-view.js | 26 +- static/scripts/mvc/library/library-model.js | 10 +- static/scripts/packed/galaxy.library.js | 2 +- .../mvc/library/library-folderlist-view.js | 2 +- .../mvc/library/library-librarylist-view.js | 2 +- .../mvc/library/library-libraryrow-view.js | 2 +- .../library/library-librarytoolbar-view.js | 2 +- .../packed/mvc/library/library-model.js | 2 +- static/style/blue/base.css | 1 + static/style/blue/library.css | 1 + static/style/src/less/library.less | 6 + 19 files changed, 329 insertions(+), 773 deletions(-) diff --git a/lib/galaxy/webapps/galaxy/api/folder_contents.py b/lib/galaxy/webapps/galaxy/api/folder_contents.py index bad6f8ce18d..0725bd2c096 100644 --- 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 FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrary 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.' ) + + 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 ) - # We didn't find the folder or user does not have an access to it. - if not folder: - trans.response.status = 400 - return "Invalid folder id ( %s ) specified." % str( folder_id ) - if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ): - log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, folder.id ) ) - trans.response.status = 400 - return "Invalid folder id ( %s ) specified." % str( folder_id ) + 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 @@ class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrary # 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 @@ class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrary 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 @@ class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibrary Creates a new folder. This should be superseded by the LibraryController. """ - pass + raise exceptions.NotImplemented( 'Creating the library folder content is not implemented.' ) @web.expose_api def update( self, trans, id, library_id, payload, **kwd ): """ PUT /api/folders/{encoded_folder_id}/contents """ - pass + raise exceptions.NotImplemented( 'Updating the library folder content is not implemented.' ) # 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 --git a/lib/galaxy/webapps/galaxy/api/folders.py b/lib/galaxy/webapps/galaxy/api/folders.py index 6c086334326..e9bec4529d9 100644 --- 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 @@ class FoldersController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinIt """ GET /api/folders/ This would normally display a list of folders. However, that would - be across multiple libraries, so it's not implemented yet. + be across multiple libraries, so it's not implemented. """ - pass + raise exceptions.NotImplemented( 'Listing all accessible library folders is not implemented.' ) @web.expose_api def show( self, trans, id, **kwd ): diff --git a/lib/galaxy/webapps/galaxy/api/libraries.py b/lib/galaxy/webapps/galaxy/api/libraries.py index afd0da5397d..c29b5d11a82 100644 --- a/lib/galaxy/webapps/galaxy/api/libraries.py +++ b/lib/galaxy/webapps/galaxy/api/libraries.py @@ -7,7 +7,7 @@ from galaxy import exceptions from galaxy.web import _future_expose_api as expose_api from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous from galaxy.model.orm import and_, not_, or_ -from galaxy.web.base.controller import BaseAPIController, url_for +from galaxy.web.base.controller import BaseAPIController import logging log = logging.getLogger( __name__ ) @@ -61,7 +61,6 @@ class LibrariesController( BaseAPIController ): if trans.app.security_agent.library_is_public( library, contents=False ): item[ 'public' ] = True current_user_roles = trans.get_current_user_roles() - # can_user_add = trans.app.security_agent.can_add_library_item( current_user_roles, library.root_folder ) if not trans.user_is_admin(): item['can_user_add'] = trans.app.security_agent.can_add_library_item( current_user_roles, library ) item['can_user_modify'] = trans.app.security_agent.can_modify_library_item( current_user_roles, library ) @@ -98,7 +97,7 @@ class LibrariesController( BaseAPIController ): deleted = util.string_as_bool( deleted ) try: decoded_library_id = trans.security.decode_id( library_id ) - except Exception: + except TypeError: raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id ) try: library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id ) @@ -144,7 +143,14 @@ class LibrariesController( BaseAPIController ): library.root_folder = root_folder trans.sa_session.add_all( ( library, root_folder ) ) trans.sa_session.flush() - return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) + + item = library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) + item['can_user_add'] = True + item['can_user_modify'] = True + item['can_user_manage'] = True + if trans.app.security_agent.library_is_public( library, contents=False ): + item[ 'public' ] = True + return item @expose_api def update( self, trans, id, **kwd ): diff --git a/lib/galaxy/webapps/galaxy/api/library_contents.py b/lib/galaxy/webapps/galaxy/api/library_contents.py index 192d9970853..ed1c8780534 100644 --- a/lib/galaxy/webapps/galaxy/api/library_contents.py +++ b/lib/galaxy/webapps/galaxy/api/library_contents.py @@ -17,8 +17,7 @@ import logging log = logging.getLogger( __name__ ) -class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems, - UsesHistoryDatasetAssociationMixin ): +class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems, UsesHistoryDatasetAssociationMixin ): @expose_api def index( self, trans, library_id, **kwd ): diff --git a/static/scripts/galaxy.library.js b/static/scripts/galaxy.library.js index 1901497a8fb..9b9448b0486 100644 --- 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 @@ var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({ } }); -// galaxy library wrapper View +// ============================================================================ +// Main controller of Galaxy Library var GalaxyLibrary = Backbone.View.extend({ - toolbarView: null, + libraryToolbarView: null, libraryListView: null, library_router: null, - folderContentView: null, + folderToolbarView: null, + folderListView: null, initialize : function(){ Galaxy.libraries = this; @@ -59,25 +63,26 @@ var GalaxyLibrary = Backbone.View.extend({ this.library_router.on('route:libraries', function() { // initialize and render the toolbar first - Galaxy.libraries.toolbarView = new mod_librarytoolbar_view.ToolbarView(); + Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView(); // initialize and render libraries second Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView(); }); this.library_router.on('route:folder_content', function(id) { - // render folder contents - if (!Galaxy.libraries.folderContentView) {Galaxy.libraries.folderContentView = new mod_folderlist_view.FolderContentView();} - Galaxy.libraries.folderContentView.render({id: id}); + // TODO place caching here, sessionstorage/localstorage? + Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id}); + Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id}); }); this.library_router.on('route:download', function(folder_id, format) { - if ($('#center').find(':checked').length === 0) { + if ($('#center').find(':checked').length === 0) { + mod_toastr.info('You have to select some datasets to download') // this happens rarely when there is a server/data error and client gets an actual response instead of an attachment // we don't know what was selected so we can't download again, we redirect to the folder provided Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true}); } else { // send download stream - Galaxy.libraries.folderContentView.download(folder_id, format); + Galaxy.libraries.folderToolbarView.download(folder_id, format); Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: false, replace: true}); } }); @@ -86,7 +91,6 @@ var GalaxyLibrary = Backbone.View.extend({ } }); -// return return { GalaxyApp: GalaxyLibrary }; diff --git a/static/scripts/mvc/library/library-folderlist-view.js b/static/scripts/mvc/library/library-folderlist-view.js index 21e8f289c40..a0bd9a3f8a7 100644 --- 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('
'); - tmpl_array.push('

Data Libraries Beta Test. This is work in progress. Please report problems & ideas via email and Trello.

'); - - // TOOLBAR - tmpl_array.push('
'); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - - tmpl_array.push('
'); - - // BREADCRUMBS - tmpl_array.push(''); - - - // FOLDER CONTENT - tmpl_array.push(''); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' <% _.each(items, function(content_item) { %>'); - tmpl_array.push(' <% if (content_item.get("type") === "folder") { %>'); // folder - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); // size - tmpl_array.push(' '); // time updated - tmpl_array.push(' '); - tmpl_array.push(' <% } else { %>'); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' '); // dataset - tmpl_array.push(' '); // data type - tmpl_array.push(' '); // size - tmpl_array.push(' '); // time updated - tmpl_array.push(' '); - tmpl_array.push(' <% } %> '); - tmpl_array.push(' <% }); %>'); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push('
namedata typesizedate (UTC)
" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..
'); - tmpl_array.push(' '); - tmpl_array.push(' '); - tmpl_array.push(' <%- content_item.get("name") %>'); - tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>'); // empty folder - tmpl_array.push(' (empty folder)'); - tmpl_array.push(' <% } %>'); - tmpl_array.push(' folder<%= _.escape(content_item.get("item_count")) %> item(s)<%= _.escape(content_item.get("time_updated")) %>
'); - tmpl_array.push(' '); - tmpl_array.push(' <%- content_item.get("name") %><%= _.escape(content_item.get("data_type")) %><%= _.escape(content_item.get("readable_size")) %><%= _.escape(content_item.get("time_updated")) %>
'); - - tmpl_array.push('
'); - return tmpl_array.join(''); - }, - templateDatasetModal : function(){ - var tmpl_array = []; - - tmpl_array.push(''); - - return tmpl_array.join(''); - }, - - templateHistorySelectInModal : function(){ - var tmpl_array = []; - - tmpl_array.push(''); - tmpl_array.push('Select history: '); - tmpl_array.push(''); - tmpl_array.push(''); - - return tmpl_array.join(''); - }, - - templateBulkImportInModal : function(){ - var tmpl_array = []; - - tmpl_array.push(''); - tmpl_array.push('Select history: '); - tmpl_array.push(''); - tmpl_array.push(''); - - return tmpl_array.join(''); - }, - - templateProgressBar : function (){ - var tmpl_array = []; - - tmpl_array.push('
'); - tmpl_array.push('Importing selected datasets to history <%= _.escape(history_name) %>'); - tmpl_array.push('
'); - tmpl_array.push('
'); - tmpl_array.push('
'); - tmpl_array.push(' 0% Complete'); - tmpl_array.push('
'); - tmpl_array.push('
'); - tmpl_array.push(''); - - return tmpl_array.join(''); - }, - - templateNewFolderInModal: function(){ - tmpl_array = []; - - tmpl_array.push('
'); - tmpl_array.push(''); - tmpl_array.push(''); - tmpl_array.push(''); - tmpl_array.push(''); - tmpl_array.push('
'); - - return tmpl_array.join(''); - }, - -// MMMMMMMMMMMMMMM -// === EVENTS ==== -// MMMMMMMMMMMMMMM - - // event binding - events: { - 'click #select-all-checkboxes' : 'selectAll', - 'click #toolbtn_bulk_import' : 'modalBulkImport', - 'click #toolbtn_dl' : 'bulkDownload', - 'click #toolbtn_create_folder' : 'createFolderFromModal', - 'click .library-dataset' : 'showDatasetDetails', - 'click .dataset_row' : 'selectClickedRow' - }, - -// MMMMMMMMMMMMMMMMMM -// === FUNCTIONS ==== -// MMMMMMMMMMMMMMMMMM - - //render the folder view - render: function (options) { - //hack to show scrollbars - $("#center").css('overflow','auto'); - - view = this; - var that = this; - - var folderContainer = new mod_library_model.FolderContainer({id: options.id}); - folderContainer.url = folderContainer.attributes.urlRoot + options.id + '/contents'; - - folderContainer.fetch({ - success: function (container) { - - // prepare nice size strings - for (var i = 0; i < folderContainer.attributes.folder.models.length; i++) { - var model = folderContainer.attributes.folder.models[i] - if (model.get('type') === 'file'){ - model.set('readable_size', that.size_to_string(model.get('file_size'))) - } - }; - - // find the upper id - var path = folderContainer.full_path; - var upper_folder_id; - if (path.length === 1){ // library is above us - upper_folder_id = 0; - } else { - upper_folder_id = path[path.length-2][0]; - } - - var template = _.template(that.templateFolder(), { path: folderContainer.full_path, items: folderContainer.attributes.folder.models, id: options.id, upper_folder_id: upper_folder_id }); - // var template = _.template(that.templateFolder(), { path: folderContainer.full_path, items: folderContainer.attributes.folder.models, id: options.id }); - that.$el.html(template); + this.folderContainer = new mod_library_model.FolderContainer({id: this.options.id}); + this.folderContainer.url = this.folderContainer.attributes.urlRoot + this.options.id + '/contents'; + this.folderContainer.fetch({ + success: function (folderContainer) { + that.render(); }, - error: function(){ - mod_toastr.error('An error occured :('); - } - }) - }, + error: function(){ + mod_toastr.error('An error occured :('); + } + }); + }, + + render: function (options) { + this.options = _.defaults(this.options || {}, options); + var template = this.templateFolder(); + var contains_file = false; + + // TODO move to server + // prepare nice size strings + for (var i = 0; i < this.folderContainer.attributes.folder.models.length; i++) { + var model = this.folderContainer.attributes.folder.models[i]; + if (model.get('type') === 'file'){ + contains_file = true; + model.set('readable_size', this.size_to_string(model.get('file_size'))); + } + } + + // TODO move to server + // find the upper id in the full path + var path = this.folderContainer.attributes.metadata.full_path; + var upper_folder_id; + if (path.length === 1){ // the library is above us + upper_folder_id = 0; + } else { + upper_folder_id = path[path.length-2][0]; + } + + this.$el.html(template({ path: this.folderContainer.attributes.metadata.full_path, items: this.folderContainer.attributes.folder.models, id: this.options.id, upper_folder_id: upper_folder_id })); + + if (this.folderContainer.attributes.folder.models.length > 0){ + this.renderRows(); + } + if (this.folderContainer.attributes.metadata.can_add_library_item === true){ + Galaxy.libraries.folderToolbarView.configureElements({ can_add_library_item: this.folderContainer.attributes.metadata.can_add_library_item, contains_file: contains_file }); + } + + // initialize the library tooltips + $("#center [data-toggle]").tooltip(); + //hack to show scrollbars + $("#center").css('overflow','auto'); + }, + + renderRows: function(){ + for (var i = 0; i < this.folderContainer.attributes.folder.models.length; i++) { + var folder_item = this.folderContainer.attributes.folder.models[i]; + var rowView = new mod_library_folderrow_view.FolderRowView(folder_item); + this.$el.find('#folder_list_body').append(rowView.el); + } + }, // convert size to nice string - size_to_string : function (size) - { - // identify unit - var unit = ""; - if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else - if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else - if (size >= 100000) { size = size / 100000; unit = "MB"; } else - if (size >= 100) { size = size / 100; unit = "KB"; } else - { size = size * 10; unit = "b"; } - // return formatted string - return (Math.round(size) / 10) + unit; - }, - - //show modal with current dataset info - showDatasetDetails : function(event){ - // prevent default - event.preventDefault(); - - //TODO check whether we already have the data - - //load the ID of the row - var id = $(event.target).parent().parent().parent().attr('id'); - if (typeof id === 'undefined'){ - id = $(event.target).parent().attr('id'); - } - if (typeof id === 'undefined'){ - id = $(event.target).parent().parent().attr('id') - } - - //create new item - var item = new mod_library_model.Item(); - var histories = new mod_library_model.GalaxyHistories(); - item.id = id; - var self = this; - - //fetch the dataset info - item.fetch({ - success: function (item) { - // TODO can render here already - //fetch user histories for import purposes - histories.fetch({ - success: function (histories){ - self.renderModalAfterFetch(item, histories) - }, - error: function(){ - mod_toastr.error('An error occured during fetching histories:('); - self.renderModalAfterFetch(item) - } - }); - }, - error: function(){ - mod_toastr.error('An error occured during loading dataset details :('); - } - }); - }, - - // show the current dataset in a modal - renderModalAfterFetch : function(item, histories){ - var size = this.size_to_string(item.get('file_size')); - var template = _.template(this.templateDatasetModal(), { item : item, size : size }); - // make modal - var self = this; - this.modal = Galaxy.modal; - this.modal.show({ - closing_events : true, - title : 'Dataset Details', - body : template, - buttons : { - 'Import' : function() { self.importCurrentIntoHistory() }, - 'Download' : function() { self.downloadCurrent() }, - 'Close' : function() { self.modal.hide() } - } - }); - - $(".peek").html('Peek:' + item.get("peek")); - - // show the import-into-history footer only if the request for histories succeeded - if (typeof history.models !== undefined){ - var history_footer_tmpl = _.template(this.templateHistorySelectInModal(), {histories : histories.models}); - $(this.modal.elMain).find('.buttons').prepend(history_footer_tmpl); - // preset last selected history if we know it - if (self.lastSelectedHistory.length > 0) { - $(this.modal.elMain).find('#dataset_import_single').val(self.lastSelectedHistory); - } - } - }, - - // download dataset shown currently in modal - downloadCurrent : function(){ - //disable the buttons - this.modal.disableButton('Import'); - this.modal.disableButton('Download'); - - var library_dataset_id = []; - library_dataset_id.push($('#id_row').attr('data-id')); - var url = '/api/libraries/datasets/download/uncompressed'; - var data = {'ldda_ids' : library_dataset_id}; - - // we assume the view is existent - folderContentView.processDownload(url, data); - this.modal.enableButton('Import'); - this.modal.enableButton('Download'); - }, - - // import dataset shown currently in modal into selected history - importCurrentIntoHistory : function(){ - //disable the buttons - this.modal.disableButton('Import'); - this.modal.disableButton('Download'); - - var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val(); - this.lastSelectedHistory = history_id; //save selected history for further use - - var library_dataset_id = $('#id_row').attr('data-id'); - var historyItem = new mod_library_model.HistoryItem(); - var self = this; - historyItem.url = historyItem.urlRoot + history_id + '/contents'; - - // save the dataset into selected history - historyItem.save({ content : library_dataset_id, source : 'library' }, { success : function(){ - mod_toastr.success('Dataset imported'); - //enable the buttons - self.modal.enableButton('Import'); - self.modal.enableButton('Download'); - }, error : function(){ - mod_toastr.error('An error occured! Dataset not imported. Please try again.') - //enable the buttons - self.modal.enableButton('Import'); - self.modal.enableButton('Download'); - } - }); - }, + size_to_string : function (size){ + // identify unit + var unit = ""; + if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else + if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else + if (size >= 100000) { size = size / 100000; unit = "MB"; } else + if (size >= 100) { size = size / 100; unit = "KB"; } else + { size = size * 10; unit = "b"; } + // return formatted string + return (Math.round(size) / 10) + unit; + }, // select all datasets selectAll : function (event) { var selected = event.target.checked; that = this; // Iterate each checkbox - $(':checkbox').each(function () { - this.checked = selected; + $(':checkbox').each(function() { + this.checked = selected; $row = $(this.parentElement.parentElement); // Change color of selected/unselected (selected) ? that.makeDarkRow($row) : that.makeWhiteRow($row); }); // Show the tools in menu - this.checkTools(); + // this.checkTools(); }, // Check checkbox on row itself or row checkbox click @@ -485,7 +153,7 @@ var FolderContentView = Backbone.View.extend({ this.makeWhiteRow($row); } } - this.checkTools(); + // this.checkTools(); }, makeDarkRow: function($row){ @@ -507,207 +175,56 @@ var FolderContentView = Backbone.View.extend({ $row.find('span').removeClass('fa-file'); }, - // show toolbar in case something is selected - checkTools : function(){ - var checkedValues = $('#folder_table').find(':checked'); - if(checkedValues.length > 0){ - $('#toolbtn_bulk_import').show(); - $('#toolbtn_dl').show(); - } else { - $('#toolbtn_bulk_import').hide(); - $('#toolbtn_dl').hide(); - } - }, +// MMMMMMMMMMMMMMMMMM +// === TEMPLATES ==== +// MMMMMMMMMMMMMMMMMM - // show bulk import modal - modalBulkImport : function(){ - var self = this; - // fetch histories - var histories = new mod_library_model.GalaxyHistories(); - histories.fetch({ - success: function (histories){ - // make modal - var history_modal_tmpl = _.template(self.templateBulkImportInModal(), {histories : histories.models}); - self.modal = Galaxy.modal; - self.modal.show({ - closing_events : true, - title : 'Import into History', - body : history_modal_tmpl, - buttons : { - 'Import' : function() {self.importAllIntoHistory()}, - 'Close' : function() {self.modal.hide();} - } - }); - }, - error: function(){ - mod_toastr.error('An error occured :('); - } - }); - }, + // main template for folder browsing + templateFolder : function (){ + var tmpl_array = []; - // import all selected datasets into history - importAllIntoHistory : function (){ - //disable the button to prevent multiple submission - this.modal.disableButton('Import'); + // BREADCRUMBS + tmpl_array.push(''); - 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(''); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); - 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(' '); + tmpl_array.push('
namedata typesizedate (UTC)
" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..
'); - // 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+=''; - }); - //send request - $('
'+inputs+'
') - .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 --git a/static/scripts/mvc/library/library-librarylist-view.js b/static/scripts/mvc/library/library-librarylist-view.js index f183fbd00df..5bea6fe4228 100644 --- 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 @@ var LibraryListView = Backbone.View.extend({ rowViews: {}, // initialize - initialize : function(){ + initialize : function(options){ + this.options = _.defaults(this.options || {}, options); var viewContext = this; this.rowViews = {}; @@ -43,7 +44,7 @@ var LibraryListView = Backbone.View.extend({ error: function(model, response){ mod_toastr.error('An error occured. Please try again.'); } - }) + }); }, /** Renders the libraries table either from the object's own collection, @@ -52,9 +53,8 @@ var LibraryListView = Backbone.View.extend({ render: function (options) { var template = this.templateLibraryList(); var libraries_to_render = null; - var include_deleted = true; var include_deleted = Galaxy.libraries.preferences.get('with_deleted'); - var models = null + var models = null; if (typeof options !== 'undefined'){ include_deleted = typeof options.with_deleted !== 'undefined' ? options.with_deleted : false; models = typeof options.models !== 'undefined' ? options.models : null; @@ -64,7 +64,7 @@ var LibraryListView = Backbone.View.extend({ if (include_deleted){ // show all the libraries libraries_to_render = this.collection.models; } else{ // show only undeleted libraries - libraries_to_render = this.collection.where({deleted: false});; + libraries_to_render = this.collection.where({deleted: false}); } } else if (models !== null){ libraries_to_render = models; @@ -74,7 +74,9 @@ var LibraryListView = Backbone.View.extend({ this.$el.html(template({length: libraries_to_render.length, order: Galaxy.libraries.preferences.get('sort_order') })); - this.renderRows(libraries_to_render); + if (libraries_to_render.length > 0){ + this.renderRows(libraries_to_render); + } // initialize the library tooltips $("#center [data-toggle]").tooltip(); // modification of upper DOM element to show scrollbars due to the #center element inheritance @@ -92,9 +94,9 @@ var LibraryListView = Backbone.View.extend({ var rowView = new mod_library_libraryrow_view.LibraryRowView(library); this.$el.find('#library_list_body').append(rowView.el); // save new rowView to cache - this.rowViews[library.get('id')] = rowView; + this.rowViews[library.get('id')] = rowView; } - }; + } }, sort_clicked : function(){ @@ -115,17 +117,17 @@ var LibraryListView = Backbone.View.extend({ if (order === 'asc'){ // this.collection.sort_order = 'asc'; this.collection.comparator = function(libraryA, libraryB){ - if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) return 1; // after - if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) return -1; // before + if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) {return 1;} // after + if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) {return -1;} // before return 0; // equal - } + }; } else if (order === 'desc'){ // this.collection.sort_order = 'desc'; this.collection.comparator = function(libraryA, libraryB){ - if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) return -1; // before - if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) return 1; // after + if (libraryA.get('name').toLowerCase() > libraryB.get('name').toLowerCase()) {return -1;} // before + if (libraryB.get('name').toLowerCase() > libraryA.get('name').toLowerCase()) {return 1;} // after return 0; // equal - } + }; } this.collection.sort(); } @@ -140,7 +142,7 @@ var LibraryListView = Backbone.View.extend({ tmpl_array.push('
'); tmpl_array.push('<% if(length === 0) { %>'); - tmpl_array.push("
I see no libraries. Why don't you create one?
"); + tmpl_array.push('
There are no libraries visible to you. If you expected some to show up please consult the library security wikipage.
'); tmpl_array.push('<% } else{ %>'); tmpl_array.push(''); tmpl_array.push(' '); @@ -175,7 +177,7 @@ var LibraryListView = Backbone.View.extend({ redirectToHome: function(){ window.location = '../'; - }, + }, redirectToLogin: function(){ window.location = '/user/login'; }, @@ -193,7 +195,7 @@ var LibraryListView = Backbone.View.extend({ title : 'Create New Library', body : this.templateNewLibraryInModal(), buttons : { - 'Create' : function() {self.create_new_library_event()}, + 'Create' : function() {self.create_new_library_event();}, 'Close' : function() {self.modal.hide();} } }); @@ -245,7 +247,6 @@ var LibraryListView = Backbone.View.extend({ } }); -// return return { LibraryListView: LibraryListView }; diff --git a/static/scripts/mvc/library/library-libraryrow-view.js b/static/scripts/mvc/library/library-libraryrow-view.js index b7deca3a5aa..3184f6e4ca3 100644 --- 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 @@ var LibraryRowView = Backbone.View.extend({ render: function(library){ if (typeof library === 'undefined'){ - var library = Galaxy.libraries.libraryListView.collection.get(this.$el.data('id')); + library = Galaxy.libraries.libraryListView.collection.get(this.$el.data('id')); } this.prepareButtons(library); var tmpl = this.templateRow(); @@ -51,7 +51,7 @@ var LibraryRowView = Backbone.View.extend({ repaint: function(library){ /* need to hide manually because of the element removal in setElement invoked in render() */ - $(".tooltip").hide(); + $(".tooltip").hide(); /* we need to store the old element to be able to replace it with new one */ var old_element = this.$el; @@ -83,13 +83,13 @@ var LibraryRowView = Backbone.View.extend({ vis_config.undelete_library_btn = false; if (library.get('can_user_add') === true){ vis_config.upload_library_btn = true; - } + } if (library.get('can_user_modify') === true){ vis_config.edit_library_btn = true; - } + } if (library.get('can_user_manage') === true){ vis_config.permission_library_btn = true; - } + } } } else if (this.edit_mode === true){ vis_config.upload_library_btn = false; @@ -136,7 +136,7 @@ var LibraryRowView = Backbone.View.extend({ is_changed = true; } else{ mod_toastr.warning('Library name has to be at least 3 characters long'); - return + return; } } @@ -183,7 +183,7 @@ var LibraryRowView = Backbone.View.extend({ Galaxy.libraries.libraryListView.collection.add(library); row_view.edit_mode = false; if (Galaxy.libraries.preferences.get('with_deleted') === false){ - $(".tooltip").hide(); + $('.tooltip').hide(); row_view.$el.remove(); } else if (Galaxy.libraries.preferences.get('with_deleted') === true){ row_view.repaint(library); @@ -247,12 +247,11 @@ var LibraryRowView = Backbone.View.extend({ tmpl_array.push(' '); tmpl_array.push(' '); - return _.template(tmpl_array.join('')); + return _.template(tmpl_array.join('')); } }); - // return return { LibraryRowView: LibraryRowView }; diff --git a/static/scripts/mvc/library/library-librarytoolbar-view.js b/static/scripts/mvc/library/library-librarytoolbar-view.js index f713575e8ca..bc35c73c054 100644 --- 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 @@ var ToolbarView = Backbone.View.extend({ render: function(){ var toolbar_template = this.templateToolBar(); - this.$el.html(toolbar_template({admin_user: Galaxy.currUser.isAdmin(), anon_user: Galaxy.currUser.isAnonymous()})) + var is_admin = Galaxy.currUser.isAdmin(); + var is_anonym = Galaxy.currUser.isAnonymous(); + this.$el.html(toolbar_template({admin_user: is_admin, anon_user: is_anonym})); if (Galaxy.currUser.isAdmin() === true){ this.$el.find('#include_deleted_chk')[0].checked = Galaxy.libraries.preferences.get('with_deleted'); } }, delegate_modal: function(event){ - // probably should refactor to have this functionality in this view, not in the library view + // probably should refactor to have this functionality in this view, not in the library list view Galaxy.libraries.libraryListView.show_library_modal(event); }, @@ -48,7 +50,7 @@ var ToolbarView = Backbone.View.extend({ templateToolBar: function(){ tmpl_array = []; - tmpl_array.push('
'); + tmpl_array.push('
'); // TOOLBAR tmpl_array.push('
'); tmpl_array.push('

Data Libraries Beta Test. This is work in progress. Please report problems & ideas via email and Trello.

'); @@ -60,16 +62,16 @@ var ToolbarView = Backbone.View.extend({ tmpl_array.push(' <% } %>'); tmpl_array.push('
'); tmpl_array.push('
'); + // table with libraries will append here tmpl_array.push('
'); tmpl_array.push('
'); return _.template(tmpl_array.join('')); } -}) +}); -// return return { - ToolbarView: ToolbarView + LibraryToolbarView: LibraryToolbarView }; }); diff --git a/static/scripts/mvc/library/library-model.js b/static/scripts/mvc/library/library-model.js index d159bc4409e..6942ae53753 100644 --- a/static/scripts/mvc/library/library-model.js +++ b/static/scripts/mvc/library/library-model.js @@ -66,16 +66,14 @@ define([], function() { var FolderContainer = Backbone.Model.extend({ defaults : { folder : new Folder(), - full_path : "unknown", urlRoot : "/api/folders/", id : "unknown" }, parse : function(obj) { - this.full_path = obj[0].full_path; - // response is not a simple array, it contains metadata - // this will update the inner collection - this.get("folder").reset(obj[1].folder_contents); - return obj; + // response is not a simple array, it contains metadata + // this will update the inner collection + this.get("folder").reset(obj.folder_contents); + return obj; } }); diff --git a/static/scripts/packed/galaxy.library.js b/static/scripts/packed/galaxy.library.js index 1e2cf49375f..592aecc523d 100644 --- a/static/scripts/packed/galaxy.library.js +++ b/static/scripts/packed/galaxy.library.js @@ -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 --git a/static/scripts/packed/mvc/library/library-folderlist-view.js b/static/scripts/packed/mvc/library/library-folderlist-view.js index 0ab07cf8b01..d940ceb3eeb 100644 --- a/static/scripts/packed/mvc/library/library-folderlist-view.js +++ b/static/scripts/packed/mvc/library/library-folderlist-view.js @@ -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('
');f.push('

Data Libraries Beta Test. This is work in progress. Please report problems & ideas via email and Trello.

');f.push('
');f.push(' ');f.push(' ');f.push(' ");f.push("
");f.push('");f.push('
');f.push(" ");f.push(' ');f.push(' ');f.push(" ");f.push(" ");f.push(" ");f.push(" ");f.push(" ");f.push(" ");f.push(' ');f.push(" ");f.push(" ");f.push(" ");f.push(" ");f.push(" ");f.push(" ");f.push(" <% _.each(items, function(content_item) { %>");f.push(' <% if (content_item.get("type") === "folder") { %>');f.push(' ');f.push(" ");f.push(" ");f.push(" ");f.push(" ");f.push(' ');f.push(' ');f.push(" ");f.push(" <% } else { %>");f.push(' ');f.push(" ");f.push(' ');f.push(' ');f.push(' ');f.push(' ');f.push(' ');f.push(" ");f.push(" <% } %> ");f.push(" <% }); %>");f.push(" ");f.push(" ");f.push("
namedata typesizedate (UTC)
" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..
");f.push(' ');f.push(" ");f.push(' <%- content_item.get("name") %>');f.push(' <% if (content_item.get("item_count") === 0) { %>');f.push(' (empty folder)');f.push(" <% } %>");f.push(" folder<%= _.escape(content_item.get("item_count")) %> item(s)<%= _.escape(content_item.get("time_updated")) %>
");f.push(' ');f.push(" <%- content_item.get("name") %><%= _.escape(content_item.get("data_type")) %><%= _.escape(content_item.get("readable_size")) %><%= _.escape(content_item.get("time_updated")) %>
");f.push("
");return f.join("")},templateDatasetModal:function(){var f=[];f.push('");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('');f.push("Select history: ");f.push('");f.push("");return f.join("")},templateBulkImportInModal:function(){var f=[];f.push('');f.push("Select history: ");f.push('");f.push("");return f.join("")},templateProgressBar:function(){var f=[];f.push('
');f.push("Importing selected datasets to history <%= _.escape(history_name) %>");f.push("
");f.push('
');f.push('
');f.push(' 0% Complete');f.push("
");f.push("
");f.push("");return f.join("")},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('
');tmpl_array.push("
");tmpl_array.push('');tmpl_array.push('');tmpl_array.push("
");tmpl_array.push("
");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=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+=''});$('
'+f+"
").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;j0){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=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('");g.push('');g.push(" ");g.push(' ');g.push(' ');g.push(" ");g.push(" ");g.push(" ");g.push(" ");g.push(" ");g.push(' ');g.push(" ");g.push(' ');g.push(" ");g.push(" ");g.push(" ");g.push(" ");g.push(" ");g.push(" ");g.push(" ");g.push("
namedata typesizedate (UTC)
" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..
");return _.template(g.join(""))}});return{FolderListView:b}}); \ No newline at end of file diff --git a/static/scripts/packed/mvc/library/library-librarylist-view.js b/static/scripts/packed/mvc/library/library-librarylist-view.js index 3e75fd5abc6..52e4dae9cfb 100644 --- a/static/scripts/packed/mvc/library/library-librarylist-view.js +++ b/static/scripts/packed/mvc/library/library-librarylist-view.js @@ -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;lj.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('
');tmpl_array.push("<% if(length === 0) { %>");tmpl_array.push("
I see no libraries. Why don't you create one?
");tmpl_array.push("<% } else{ %>");tmpl_array.push('');tmpl_array.push(" ");tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push("
name descriptionsynopsis
");tmpl_array.push("<% }%>");tmpl_array.push("
");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('
');tmpl_array.push("
");tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push("
");tmpl_array.push("
");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;lj.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('
');tmpl_array.push("<% if(length === 0) { %>");tmpl_array.push('
There are no libraries visible to you. If you expected some to show up please consult the library security wikipage.
');tmpl_array.push("<% } else{ %>");tmpl_array.push('');tmpl_array.push(" ");tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push("
name descriptionsynopsis
");tmpl_array.push("<% }%>");tmpl_array.push("
");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('
');tmpl_array.push("
");tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push("
");tmpl_array.push("
");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 --git a/static/scripts/packed/mvc/library/library-libraryrow-view.js b/static/scripts/packed/mvc/library/library-libraryrow-view.js index 00853bdb50c..b6572a33e35 100644 --- a/static/scripts/packed/mvc/library/library-libraryrow-view.js +++ b/static/scripts/packed/mvc/library/library-libraryrow-view.js @@ -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(' " style="display:none;" data-id="<%- library.get("id") %>">');tmpl_array.push(" <% if(!edit_mode) { %>");tmpl_array.push(' "><%- library.get("name") %>');tmpl_array.push(' <%= _.escape(library.get("description")) %>');tmpl_array.push(' <%= _.escape(library.get("synopsis")) %>');tmpl_array.push(" <% } else if(edit_mode){ %>");tmpl_array.push(' ">');tmpl_array.push(' ">');tmpl_array.push(' ">');tmpl_array.push(" <% } %>");tmpl_array.push(' ');tmpl_array.push(' <% if(library.get("deleted") === true) { %>');tmpl_array.push(' ');tmpl_array.push(' <% } else if(library.get("public") === true) { %>');tmpl_array.push(' ');tmpl_array.push(" <% }%>");tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push(" ");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(' " style="display:none;" data-id="<%- library.get("id") %>">');tmpl_array.push(" <% if(!edit_mode) { %>");tmpl_array.push(' "><%- library.get("name") %>');tmpl_array.push(' <%= _.escape(library.get("description")) %>');tmpl_array.push(' <%= _.escape(library.get("synopsis")) %>');tmpl_array.push(" <% } else if(edit_mode){ %>");tmpl_array.push(' ">');tmpl_array.push(' ">');tmpl_array.push(' ">');tmpl_array.push(" <% } %>");tmpl_array.push(' ');tmpl_array.push(' <% if(library.get("deleted") === true) { %>');tmpl_array.push(' ');tmpl_array.push(' <% } else if(library.get("public") === true) { %>');tmpl_array.push(' ');tmpl_array.push(" <% }%>");tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push(" ");return _.template(tmpl_array.join(""))}});return{LibraryRowView:a}}); \ No newline at end of file diff --git a/static/scripts/packed/mvc/library/library-librarytoolbar-view.js b/static/scripts/packed/mvc/library/library-librarytoolbar-view.js index 64acfd29113..6369a270cc9 100644 --- a/static/scripts/packed/mvc/library/library-librarytoolbar-view.js +++ b/static/scripts/packed/mvc/library/library-librarytoolbar-view.js @@ -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('
');tmpl_array.push('
');tmpl_array.push('

Data Libraries Beta Test. This is work in progress. Please report problems & ideas via email and Trello.

');tmpl_array.push(" <% if(admin_user === true) { %>");tmpl_array.push('
');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push("
");tmpl_array.push(" <% } %>");tmpl_array.push("
");tmpl_array.push('
');tmpl_array.push("
");tmpl_array.push("
");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('
');tmpl_array.push('
');tmpl_array.push('

Data Libraries Beta Test. This is work in progress. Please report problems & ideas via email and Trello.

');tmpl_array.push(" <% if(admin_user === true) { %>");tmpl_array.push('
');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push("
");tmpl_array.push(" <% } %>");tmpl_array.push("
");tmpl_array.push('
');tmpl_array.push("
");tmpl_array.push("
");return _.template(tmpl_array.join(""))}});return{LibraryToolbarView:e}}); \ No newline at end of file diff --git a/static/scripts/packed/mvc/library/library-model.js b/static/scripts/packed/mvc/library/library-model.js index bd1d114f95e..a752fc3d196 100644 --- a/static/scripts/packed/mvc/library/library-model.js +++ b/static/scripts/packed/mvc/library/library-model.js @@ -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 --git a/static/style/blue/base.css b/static/style/blue/base.css index deef41dd0e1..6b043bf9e0d 100644 --- a/static/style/blue/base.css +++ b/static/style/blue/base.css @@ -1299,6 +1299,7 @@ td.right-center{vertical-align:middle !important;text-align:right} .library_table td{border-top:1px solid #5f6990 !important} .library_table th{border-bottom:2px solid #5f6990 !important} .library_table a{color:#0A143D}.library_table a:hover{color:maroon} +.library_style_container{width:95%;margin:auto;margin-top:2em;overflow:auto !important} tr.light td{background-color:white;color:black} tr.light:hover td{background-color:#f5e8cc} tr.dark td{background-color:#d6b161;color:white} diff --git a/static/style/blue/library.css b/static/style/blue/library.css index 83979d703f5..bb0e982e116 100644 --- a/static/style/blue/library.css +++ b/static/style/blue/library.css @@ -10,6 +10,7 @@ td.right-center{vertical-align:middle !important;text-align:right} .library_table td{border-top:1px solid #5f6990 !important} .library_table th{border-bottom:2px solid #5f6990 !important} .library_table a{color:#0A143D}.library_table a:hover{color:maroon} +.library_style_container{width:95%;margin:auto;margin-top:2em;overflow:auto !important} tr.light td{background-color:white;color:black} tr.light:hover td{background-color:#f5e8cc} tr.dark td{background-color:#d6b161;color:white} diff --git a/static/style/src/less/library.less b/static/style/src/less/library.less index ccd059e920b..9d1a83c0625 100644 --- a/static/style/src/less/library.less +++ b/static/style/src/less/library.less @@ -49,6 +49,12 @@ td.right-center{ } } } +.library_style_container{ + width: 95%; + margin: auto; + margin-top:2em; + overflow: auto !important; +} tr.light td { From 4bea6249f32616bb3fe79d7c3b7f50e13e15bd77 Mon Sep 17 00:00:00 2001 From: Martin Cech Date: Thu, 10 Apr 2014 15:07:01 -0400 Subject: [PATCH 18/28] forgotten files for previous commit data libraries: API refactoring and improvements; backbone decoupling; role UI first implementation --- .../mvc/library/library-folderrow-view.js | 310 +++++++++++++++++ .../mvc/library/library-foldertoolbar-view.js | 320 ++++++++++++++++++ .../mvc/library/library-folderrow-view.js | 1 + .../mvc/library/library-foldertoolbar-view.js | 1 + 4 files changed, 632 insertions(+) create mode 100644 static/scripts/mvc/library/library-folderrow-view.js create mode 100644 static/scripts/mvc/library/library-foldertoolbar-view.js create mode 100644 static/scripts/packed/mvc/library/library-folderrow-view.js create mode 100644 static/scripts/packed/mvc/library/library-foldertoolbar-view.js diff --git a/static/scripts/mvc/library/library-folderrow-view.js b/static/scripts/mvc/library/library-folderrow-view.js new file mode 100644 index 00000000000..70b4fb9b61f --- /dev/null +++ b/static/scripts/mvc/library/library-folderrow-view.js @@ -0,0 +1,310 @@ +// dependencies +define([ + "galaxy.masthead", + "utils/utils", + "libs/toastr", + "mvc/library/library-model"], +function(mod_masthead, + mod_utils, + mod_toastr, + mod_library_model) { + +// galaxy library row view +var FolderRowView = Backbone.View.extend({ + // last selected history in modal for UX + lastSelectedHistory: '', + + events: { + 'click .library-dataset' : 'showDatasetDetails' + }, + + options: { + type: null + }, + + initialize : function(folder_item){ + this.render(folder_item); + }, + + render: function(folder_item){ + // if (typeof folder_item === 'undefined'){ + // folder_item = Galaxy.libraries.libraryFolderView.collection.get(this.$el.data('id')); + // } + var template = null; + if (folder_item.get('type') === 'folder'){ + this.options.type = 'folder'; + template = this.templateRowFolder(); + } else { + this.options.type = 'file'; + template = this.templateRowFile(); + } + this.setElement(template({content_item:folder_item})); + this.$el.show(); + return this; + }, + + //show modal with current dataset info + showDatasetDetails : function(event){ + // prevent default + event.preventDefault(); + + var id = this.id; + + //create new item + var item = new mod_library_model.Item(); + var histories = new mod_library_model.GalaxyHistories(); + item.id = id; + var self = this; + + //fetch the dataset info + item.fetch({ + success: function (item) { + // TODO can start rendering here already + //fetch user histories for import purposes + histories.fetch({ + success: function (histories){ + self.renderModalAfterFetch(item, histories); + }, + error: function(){ + mod_toastr.error('An error occured during fetching histories:('); + self.renderModalAfterFetch(item); + } + }); + }, + error: function(){ + mod_toastr.error('An error occured during loading dataset details :('); + } + }); +}, + + // show the current dataset in a modal + renderModalAfterFetch : function(item, histories){ + var size = this.size_to_string(item.get('file_size')); + var template = _.template(this.templateDatasetModal(), { item : item, size : size }); + // make modal + var self = this; + this.modal = Galaxy.modal; + this.modal.show({ + closing_events : true, + title : 'Dataset Details', + body : template, + buttons : { + 'Import' : function() { self.importCurrentIntoHistory(); }, + 'Download' : function() { self.downloadCurrent(); }, + 'Close' : function() { self.modal.hide(); } + } + }); + + $(".peek").html(item.get("peek")); + + // show the import-into-history footer only if the request for histories succeeded + if (typeof history.models !== undefined){ + var history_footer_tmpl = _.template(this.templateHistorySelectInModal(), {histories : histories.models}); + $(this.modal.elMain).find('.buttons').prepend(history_footer_tmpl); + // preset last selected history if we know it + if (self.lastSelectedHistory.length > 0) { + $(this.modal.elMain).find('#dataset_import_single').val(self.lastSelectedHistory); + } + } + }, + + // TODO this is dup func, unify + // convert size to nice string + size_to_string : function (size){ + // identify unit + var unit = ""; + if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else + if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else + if (size >= 100000) { size = size / 100000; unit = "MB"; } else + if (size >= 100) { size = size / 100; unit = "KB"; } else + { size = size * 10; unit = "b"; } + // return formatted string + return (Math.round(size) / 10) + unit; + }, + + // download dataset shown currently in modal + downloadCurrent : function(){ + //disable the buttons + this.modal.disableButton('Import'); + this.modal.disableButton('Download'); + + var library_dataset_id = []; + library_dataset_id.push($('#id_row').attr('data-id')); + var url = '/api/libraries/datasets/download/uncompressed'; + var data = {'ldda_ids' : library_dataset_id}; + + this.processDownload(url, data); + this.modal.enableButton('Import'); + this.modal.enableButton('Download'); + }, + + // TODO this is dup func, unify + // create hidden form and submit through POST to initialize download + processDownload: function(url, data, method){ + //url and data options required + if( url && data ){ + //data can be string of parameters or array/object + data = typeof data == 'string' ? data : $.param(data); + //split params into form inputs + var inputs = ''; + $.each(data.split('&'), function(){ + var pair = this.split('='); + inputs+=''; + }); + //send request + $('
'+inputs+'
') + .appendTo('body').submit().remove(); + + mod_toastr.info('Your download will begin soon'); + } + }, + + // import dataset shown currently in modal into selected history + importCurrentIntoHistory : function(){ + //disable the buttons + this.modal.disableButton('Import'); + this.modal.disableButton('Download'); + + var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val(); + this.lastSelectedHistory = history_id; //save selected history for further use + + var library_dataset_id = $('#id_row').attr('data-id'); + var historyItem = new mod_library_model.HistoryItem(); + var self = this; + historyItem.url = historyItem.urlRoot + history_id + '/contents'; + + // save the dataset into selected history + historyItem.save({ content : library_dataset_id, source : 'library' }, { success : function(){ + mod_toastr.success('Dataset imported'); + //enable the buttons + self.modal.enableButton('Import'); + self.modal.enableButton('Download'); + }, error : function(){ + mod_toastr.error('An error occured! Dataset not imported. Please try again.'); + //enable the buttons + self.modal.enableButton('Import'); + self.modal.enableButton('Download'); + } + }); + }, + + templateRowFolder: function() { + tmpl_array = []; + + tmpl_array.push(''); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' <%- content_item.get("name") %>'); + tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>'); // empty folder + tmpl_array.push(' (empty folder)'); + tmpl_array.push(' <% } %>'); + tmpl_array.push(' '); + tmpl_array.push(' folder'); + tmpl_array.push(' <%= _.escape(content_item.get("item_count")) %> item(s)'); // size + tmpl_array.push(' <%= _.escape(content_item.get("time_updated")) %>'); // time updated + tmpl_array.push(''); + + return _.template(tmpl_array.join('')); + }, + + templateRowFile: function(){ + tmpl_array = []; + + tmpl_array.push(''); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' <%- content_item.get("name") %>'); // dataset + tmpl_array.push(' <%= _.escape(content_item.get("data_type")) %>'); // data type + tmpl_array.push(' <%= _.escape(content_item.get("readable_size")) %>'); // size + tmpl_array.push(' <%= _.escape(content_item.get("time_updated")) %>'); // time updated + tmpl_array.push(''); + + return _.template(tmpl_array.join('')); + }, + +templateDatasetModal : function(){ + var tmpl_array = []; + + tmpl_array.push(''); + + return tmpl_array.join(''); +}, + +templateHistorySelectInModal : function(){ + var tmpl_array = []; + + tmpl_array.push(''); + tmpl_array.push('Select history: '); + tmpl_array.push(''); + tmpl_array.push(''); + + return tmpl_array.join(''); +} + +}); + +return { + FolderRowView: FolderRowView +}; + +}); diff --git a/static/scripts/mvc/library/library-foldertoolbar-view.js b/static/scripts/mvc/library/library-foldertoolbar-view.js new file mode 100644 index 00000000000..7b702a782dd --- /dev/null +++ b/static/scripts/mvc/library/library-foldertoolbar-view.js @@ -0,0 +1,320 @@ +// dependencies +define([ + "galaxy.masthead", + "utils/utils", + "libs/toastr", + "mvc/library/library-model"], +function(mod_masthead, + mod_utils, + mod_toastr, + mod_library_model) { + +var FolderToolbarView = Backbone.View.extend({ + el: '#center', + + events: { + 'click #toolbtn_create_folder' : 'createFolderFromModal', + 'click #toolbtn_bulk_import' : 'modalBulkImport' + }, + + defaults: { + 'can_add_library_item' : false, + 'contains_file' : false + }, + + modal : null, + + initialize: function(options){ + this.options = _.defaults(options || {}, this.defaults); + this.render(); + }, + + render: function(options){ + this.options = _.extend(this.options, options); + var toolbar_template = this.templateToolBar(); + var is_admin = Galaxy.currUser.isAdmin(); + this.$el.html(toolbar_template({id: this.options.id, admin_user: is_admin})); + }, + + configureElements: function(options){ + this.options = _.extend(this.options, options); + if (this.options.can_add_library_item === true){ + $('#toolbtn_create_folder').show(); + $('#toolbtn_upload_files').show(); + } + if (this.options.contains_file === true){ + $('#toolbtn_bulk_import').show(); + $('#toolbtn_dl').show(); + } + this.$el.find('[data-toggle]').tooltip(); + }, + + // shows modal for creating folder + createFolderFromModal: function(){ + event.preventDefault(); + event.stopPropagation(); + + // create modal + var self = this; + var template = this.templateNewFolderInModal(); + this.modal = Galaxy.modal; + this.modal.show({ + closing_events : true, + title : 'Create New Folder', + body : template(), + buttons : { + 'Create' : function() {self.create_new_folder_event();}, + 'Close' : function() {self.modal.hide(); self.modal = null;} + } + }); + }, + + // create the new folder from modal + create_new_folder_event: function(){ + var folderDetails = this.serialize_new_folder(); + if (this.validate_new_folder(folderDetails)){ + var folder = new mod_library_model.FolderAsModel(); + url_items = Backbone.history.fragment.split('/'); + current_folder_id = url_items[url_items.length-1]; + folder.url = folder.urlRoot + '/' + current_folder_id ; + + var self = this; + folder.save(folderDetails, { + success: function (folder) { + self.modal.hide(); + mod_toastr.success('Folder created'); + Galaxy.libraries.folderListView.render({id: current_folder_id}); + }, + error: function(){ + mod_toastr.error('An error occured :('); + } + }); + } else { + mod_toastr.error('Folder\'s name is missing'); + } + return false; + }, + + // serialize data from the modal + serialize_new_folder : function(){ + return { + name: $("input[name='Name']").val(), + description: $("input[name='Description']").val() + }; + }, + + // validate new folder info + validate_new_folder: function(folderDetails){ + return folderDetails.name !== ''; + }, + + + // show bulk import modal + modalBulkImport : function(){ + var checkedValues = $('#folder_table').find(':checked'); + if(checkedValues.length === 0){ + mod_toastr.info('You have to select some datasets first'); + } else { + var self = this; + // fetch histories + var template = this.templateBulkImportInModal(); + var histories = new mod_library_model.GalaxyHistories(); + histories.fetch({ + success: function (histories){ + // make modal + // var history_modal_tmpl = template({histories : histories.models}); + self.modal = Galaxy.modal; + self.modal.show({ + closing_events : true, + title : 'Import into History', + body : template({histories : histories.models}), + buttons : { + 'Import' : function() {self.importAllIntoHistory();}, + 'Close' : function() {self.modal.hide();} + } + }); + }, + error: function(){ + mod_toastr.error('An error occured :('); + } + }); + } + }, + + // import all selected datasets into history + importAllIntoHistory : function (){ + //disable the button to prevent multiple submission + this.modal.disableButton('Import'); + + var history_id = $("select[name=dataset_import_bulk] option:selected").val(); + var history_name = $("select[name=dataset_import_bulk] option:selected").text(); + + var dataset_ids = []; + $('#folder_table').find(':checked').each(function(){ + if (this.parentElement.parentElement.id !== '') { + dataset_ids.push(this.parentElement.parentElement.id); + } + }); + var progress_bar_tmpl = this.templateProgressBar(); + $(this.modal.elMain).find('.modal-body').html(progress_bar_tmpl({ history_name : history_name })); + + // init the progress bar + var progressStep = 100 / dataset_ids.length; + this.initProgress(progressStep); + + // prepare the dataset objects to be imported + var datasets_to_import = []; + for (var i = dataset_ids.length - 1; i >= 0; i--) { + library_dataset_id = dataset_ids[i]; + var historyItem = new mod_library_model.HistoryItem(); + var self = this; + historyItem.url = historyItem.urlRoot + history_id + '/contents'; + historyItem.content = library_dataset_id; + historyItem.source = 'library'; + datasets_to_import.push(historyItem); + } + // call the recursive function to call ajax one after each other (request FIFO queue) + this.chainCall(datasets_to_import); + }, + + chainCall: function(history_item_set){ + var self = this; + var popped_item = history_item_set.pop(); + if (typeof popped_item === "undefined") { + mod_toastr.success('All datasets imported'); + this.modal.hide(); + return; + } + var promise = $.when(popped_item.save({content: popped_item.content, source: popped_item.source})).done(function(a1){ + self.updateProgress(); + self.chainCall(history_item_set); + }); + }, + + initProgress: function(progressStep){ + this.progress = 0; + this.progressStep = progressStep; + }, + + updateProgress: function(){ + this.progress += this.progressStep; + $('.progress-bar-import').width(Math.round(this.progress) + '%'); + txt_representation = Math.round(this.progress) + '% Complete'; + $('.completion_span').text(txt_representation); + }, + + // download selected datasets + download : function(folder_id, format){ + var dataset_ids = []; + $('#folder_table').find(':checked').each(function(){ + if (this.parentElement.parentElement.id !== '') { + dataset_ids.push(this.parentElement.parentElement.id); + } + }); + + var url = '/api/libraries/datasets/download/' + format; + var data = {'ldda_ids' : dataset_ids}; + this.processDownload(url, data, 'get'); + }, + + // create hidden form and submit through POST to initialize download + processDownload: function(url, data, method){ + //url and data options required + if( url && data ){ + //data can be string of parameters or array/object + data = typeof data == 'string' ? data : $.param(data); + //split params into form inputs + var inputs = ''; + $.each(data.split('&'), function(){ + var pair = this.split('='); + inputs+=''; + }); + //send request + $('
'+inputs+'
') + .appendTo('body').submit().remove(); + + mod_toastr.info('Your download will begin soon'); + } + }, + + templateToolBar: function(){ + tmpl_array = []; + + // CONTAINER + tmpl_array.push('
'); + tmpl_array.push('

Data Libraries Beta Test. This is work in progress. Please report problems & ideas via email and Trello.

'); + // TOOLBAR + tmpl_array.push('
'); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push(' '); + tmpl_array.push('
'); + tmpl_array.push('
'); + // library items will append here + tmpl_array.push('
'); + tmpl_array.push('
'); + + return _.template(tmpl_array.join('')); + }, + + templateNewFolderInModal: function(){ + tmpl_array = []; + + tmpl_array.push('
'); + tmpl_array.push('
'); + tmpl_array.push(''); + tmpl_array.push(''); + tmpl_array.push('
'); + tmpl_array.push('
'); + + return _.template(tmpl_array.join('')); + }, + + + templateBulkImportInModal : function(){ + var tmpl_array = []; + + tmpl_array.push(''); + tmpl_array.push('Select history: '); + tmpl_array.push(''); + tmpl_array.push(''); + + return _.template(tmpl_array.join('')); + }, + + templateProgressBar : function (){ + var tmpl_array = []; + + tmpl_array.push('
'); + tmpl_array.push('Importing selected datasets to history <%= _.escape(history_name) %>'); + tmpl_array.push('
'); + tmpl_array.push('
'); + tmpl_array.push('
'); + tmpl_array.push(' 0% Complete'); + tmpl_array.push('
'); + tmpl_array.push('
'); + tmpl_array.push(''); + + return _.template(tmpl_array.join('')); + } +}); + +return { + FolderToolbarView: FolderToolbarView +}; + +}); diff --git a/static/scripts/packed/mvc/library/library-folderrow-view.js b/static/scripts/packed/mvc/library/library-folderrow-view.js new file mode 100644 index 00000000000..47fd065beab --- /dev/null +++ b/static/scripts/packed/mvc/library/library-folderrow-view.js @@ -0,0 +1 @@ +define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .library-dataset":"showDatasetDetails"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";g=this.templateRowFile()}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(i){i.preventDefault();var j=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=j;var f=this;h.fetch({success:function(k){g.fetch({success:function(l){f.renderModalAfterFetch(k,l)},error:function(){e.error("An error occured during fetching histories:(");f.renderModalAfterFetch(k)}})},error:function(){e.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+=''});$('
'+f+"
").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var h=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=h;var f=$("#id_row").attr("data-id");var i=new c.HistoryItem();var g=this;i.url=i.urlRoot+h+"/contents";i.save({content:f,source:"library"},{success:function(){e.success("Dataset imported");g.modal.enableButton("Import");g.modal.enableButton("Download")},error:function(){e.error("An error occured! Dataset not imported. Please try again.");g.modal.enableButton("Import");g.modal.enableButton("Download")}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('');tmpl_array.push(" ");tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push(" ");tmpl_array.push(" ");tmpl_array.push(' <%- content_item.get("name") %>');tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>');tmpl_array.push(" (empty folder)");tmpl_array.push(" <% } %>");tmpl_array.push(" ");tmpl_array.push(" folder");tmpl_array.push(' <%= _.escape(content_item.get("item_count")) %> item(s)');tmpl_array.push(' <%= _.escape(content_item.get("time_updated")) %>');tmpl_array.push("");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('');tmpl_array.push(" ");tmpl_array.push(' ');tmpl_array.push(" ");tmpl_array.push(' ');tmpl_array.push(' <%- content_item.get("name") %>');tmpl_array.push(' <%= _.escape(content_item.get("data_type")) %>');tmpl_array.push(' <%= _.escape(content_item.get("readable_size")) %>');tmpl_array.push(' <%= _.escape(content_item.get("time_updated")) %>');tmpl_array.push("");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('');f.push("Select history: ");f.push('");f.push("");return f.join("")}});return{FolderRowView:a}}); \ No newline at end of file diff --git a/static/scripts/packed/mvc/library/library-foldertoolbar-view.js b/static/scripts/packed/mvc/library/library-foldertoolbar-view.js new file mode 100644 index 00000000000..b673edc51fe --- /dev/null +++ b/static/scripts/packed/mvc/library/library-foldertoolbar-view.js @@ -0,0 +1 @@ +define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({el:"#center",events:{"click #toolbtn_create_folder":"createFolderFromModal","click #toolbtn_bulk_import":"modalBulkImport"},defaults:{can_add_library_item:false,contains_file:false},modal:null,initialize:function(f){this.options=_.defaults(f||{},this.defaults);this.render()},render:function(f){this.options=_.extend(this.options,f);var h=this.templateToolBar();var g=Galaxy.currUser.isAdmin();this.$el.html(h({id:this.options.id,admin_user:g}))},configureElements:function(f){this.options=_.extend(this.options,f);if(this.options.can_add_library_item===true){$("#toolbtn_create_folder").show();$("#toolbtn_upload_files").show()}if(this.options.contains_file===true){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}this.$el.find("[data-toggle]").tooltip()},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;var g=this.templateNewFolderInModal();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:g(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){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 c.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();e.success("Folder created");Galaxy.libraries.folderListView.render({id:current_folder_id})},error:function(){e.error("An error occured :(")}})}else{e.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""},modalBulkImport:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{var h=this;var i=this.templateBulkImportInModal();var g=new c.GalaxyHistories();g.fetch({success:function(j){h.modal=Galaxy.modal;h.modal.show({closing_events:true,title:"Import into History",body:i({histories:j.models}),buttons:{Import:function(){h.importAllIntoHistory()},Close:function(){h.modal.hide()}}})},error:function(){e.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=this.templateProgressBar();$(this.modal.elMain).find(".modal-body").html(n({history_name:m}));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 c.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"){e.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+=''});$('
'+f+"
").appendTo("body").submit().remove();e.info("Your download will begin soon")}},templateToolBar:function(){tmpl_array=[];tmpl_array.push('
');tmpl_array.push('

Data Libraries Beta Test. This is work in progress. Please report problems & ideas via email and Trello.

');tmpl_array.push('
');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ');tmpl_array.push(' ");tmpl_array.push("
");tmpl_array.push('
');tmpl_array.push("
");tmpl_array.push("
");return _.template(tmpl_array.join(""))},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('
');tmpl_array.push("
");tmpl_array.push('');tmpl_array.push('');tmpl_array.push("
");tmpl_array.push("
");return _.template(tmpl_array.join(""))},templateBulkImportInModal:function(){var f=[];f.push('');f.push("Select history: ");f.push('");f.push("");return _.template(f.join(""))},templateProgressBar:function(){var f=[];f.push('
');f.push("Importing selected datasets to history <%= _.escape(history_name) %>");f.push("
");f.push('
');f.push('
');f.push(' 0% Complete');f.push("
");f.push("
");f.push("");return _.template(f.join(""))}});return{FolderToolbarView:a}}); \ No newline at end of file From c3a29f9fb6d65509e35ece9043f7ae5776add5bd Mon Sep 17 00:00:00 2001 From: Daniel Blankenberg Date: Thu, 10 Apr 2014 15:55:26 -0400 Subject: [PATCH 19/28] Add a link to a tool's toolshed repository if it was installed from a ToolShed. --- templates/webapps/galaxy/tool_form.mako | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/templates/webapps/galaxy/tool_form.mako b/templates/webapps/galaxy/tool_form.mako index 3cc057e261e..54e22ed8372 100644 --- a/templates/webapps/galaxy/tool_form.mako +++ b/templates/webapps/galaxy/tool_form.mako @@ -378,3 +378,10 @@
%endif +%if tool.tool_shed_repository: + <% tool_url = tool.tool_shed_repository.get_sharable_url( tool.app ) %> + %if tool_url: +
+ ${ render_msg( 'This tool was installed from a ToolShed, you may be able to find additional information by following this link: %s' % ( tool_url, tool_url ), 'info' ) } + %endif +%endif From 8f179efe715b6b1132fe3166551336b2df51891f Mon Sep 17 00:00:00 2001 From: Carl Eberhard Date: Thu, 10 Apr 2014 16:28:16 -0400 Subject: [PATCH 20/28] Metrics: initial commit of client side logger --- .../packed/galaxy.workflow_editor.canvas.js | 2 +- static/scripts/packed/galaxy.workflows.js | 2 +- static/scripts/packed/utils/metrics-logger.js | 1 + static/scripts/utils/metrics-logger.js | 386 ++++++++++++++++++ 4 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 static/scripts/packed/utils/metrics-logger.js create mode 100644 static/scripts/utils/metrics-logger.js diff --git a/static/scripts/packed/galaxy.workflow_editor.canvas.js b/static/scripts/packed/galaxy.workflow_editor.canvas.js index a15d9116073..2536ea4b2a6 100644 --- a/static/scripts/packed/galaxy.workflow_editor.canvas.js +++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js @@ -1 +1 @@ -function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}OutputTerminal.prototype=new Terminal();function InputTerminal(b,c,a){Terminal.call(this,b);this.datatypes=c;this.multiple=a}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1||this.multiple){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};if(!this.handle1||!this.handle2){return}var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{new_input_terminal:function(a){var b=$("
");this.enable_input_terminal(b,a.name,a.extensions,a.multiple);return b},enable_input_terminal:function(f,b,c,a){var d=this;$(f).each(function(){var g=this.terminal=new InputTerminal(this,c,a);g.node=d;g.name=b;$(this).bind("dropinit",function(h,i){return $(i.drag).hasClass("output-terminal")&&g.can_accept(i.drag.terminal)}).bind("dropstart",function(h,i){if(i.proxy.terminal){i.proxy.terminal.connectors[0].inner_color="#BBFFBB"}}).bind("dropend",function(h,i){if(i.proxy.terminal){i.proxy.terminal.connectors[0].inner_color="#FFFFFF"}}).bind("drop",function(h,i){(new Connector(i.drag.terminal,g)).redraw()}).bind("hover",function(){if(g.connectors.length>0){var h=$("
").css({display:"none"}).appendTo("body").append($("
").append($("
").addClass("fa-icon-button fa fa-times").click(function(){$.each(g.connectors,function(j,i){if(i){i.destroy()}});h.remove()}))).bind("mouseleave",function(){$(this).remove()});h.css({top:$(this).offset().top-2,left:$(this).offset().left-h.width(),"padding-right":$(this).width()}).show()}});d.input_terminals[b]=g})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j,k){$(k.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var i=$('
').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var l=new Connector();l.dragging=true;l.connect(this.terminal,i.terminal);return i}).bind("drag",function(i,j){var h=function(){var l=$(j.proxy).offsetParent().offset(),k=j.offsetX-l.left,m=j.offsetY-l.top;$(j.proxy).css({left:k,top:m});j.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h,i){i.proxy.terminal.connectors[0].destroy();$(i.proxy).remove();$(i.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(h){var g=this.element;if(h.type){this.type=h.type}this.name=h.name;this.form_html=h.form_html;this.tool_state=h.tool_state;this.tool_errors=h.tool_errors;this.tooltip=h.tooltip?h.tooltip:"";this.annotation=h.annotation;this.post_job_actions=h.post_job_actions?h.post_job_actions:{};this.workflow_outputs=h.workflow_outputs?h.workflow_outputs:[];if(this.tool_errors){g.addClass("tool-node-error")}else{g.removeClass("tool-node-error")}var d=this;var c=Math.max(150,g.width());var a=g.find(".toolFormBody");a.find("div").remove();var i=$("
").appendTo(a);$.each(h.data_inputs,function(k,f){var j=d.new_input_terminal(f);var b=$("
"+f.label+"
");b.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(b);c=Math.max(c,b.outerWidth());b.css({position:"",left:"",top:"",display:""});b.remove();i.append(b.prepend(j))});if((h.data_inputs.length>0)&&(h.data_outputs.length>0)){a.append($("
"))}$.each(h.data_outputs,function(k,b){var j=$("
");d.enable_output_terminal(j,b.name,b.extensions);var f=b.name;if(b.extensions.indexOf("input")<0){f=f+" ("+b.extensions.join(", ")+")"}var m=$("
"+f+"
");if(d.type=="tool"){var l=$("
").css({display:"none"}).append($("
").append($("").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(b.name,d.workflow_outputs)!=-1){d.workflow_outputs.splice($.inArray(b.name,d.workflow_outputs),1);l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{d.workflow_outputs.push(b.name);l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});l.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});l.show();m.append(l);if($.inArray(b.name,d.workflow_outputs)===-1){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}m.hover(function(){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")},function(){if($.inArray(b.name,d.workflow_outputs)===-1){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}})}m.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(m);c=Math.max(c,m.outerWidth()+17);m.css({position:"",left:"",top:"",display:""});m.detach();a.append(m.append(j))});g.css("width",Math.min(250,Math.max(g.width(),c)));workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;this.annotation=f.annotation;var g=$.parseJSON(f.post_job_actions);this.post_job_actions=g?g:{};if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var h=c.find("div.inputs");var b=$("
");var a=h.find("div.input-data-row");$.each(f.data_inputs,function(l,j){var k=d.new_input_terminal(j);h.find("div[name='"+j.name+"']").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){k[0].terminal.connectors[0]=i;i.handle2=k[0].terminal}});$(this).remove()});b.append($("
"+j.label+"
").prepend(k))});h.replaceWith(b);h.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="
"+d+"
";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("
No node selected
")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("
");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("
"+j+"
");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("
");var h="
loading tool info...
";m.append(h);g.form_html=h;i.append(m);var k=$("
");k.append($("
").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-qA){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-qu){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}}); \ No newline at end of file +function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}OutputTerminal.prototype=new Terminal();function InputTerminal(b,c,a){Terminal.call(this,b);this.datatypes=c;this.multiple=a}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1||this.multiple){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};if(!this.handle1||!this.handle2){return}var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{new_input_terminal:function(a){var b=$("
")[0];this.enable_input_terminal(b,a.name,a.extensions,a.multiple);return b},enable_input_terminal:function(f,b,d,a){var g=this;var c=f.terminal=new InputTerminal(f,d,a);c.node=g;c.name=b;$(f).bind("dropinit",function(h,i){return $(i.drag).hasClass("output-terminal")&&c.can_accept(i.drag.terminal)}).bind("dropstart",function(h,i){if(i.proxy.terminal){i.proxy.terminal.connectors[0].inner_color="#BBFFBB"}}).bind("dropend",function(h,i){if(i.proxy.terminal){i.proxy.terminal.connectors[0].inner_color="#FFFFFF"}}).bind("drop",function(h,i){(new Connector(i.drag.terminal,c)).redraw()}).bind("hover",function(){if(c.connectors.length>0){var h=$("
").css({display:"none"}).appendTo("body").append($("
").append($("
").addClass("fa-icon-button fa fa-times").click(function(){$.each(c.connectors,function(j,i){if(i){i.destroy()}});h.remove()}))).bind("mouseleave",function(){$(this).remove()});h.css({top:$(f).offset().top-2,left:$(f).offset().left-h.width(),"padding-right":$(f).width()}).show()}});g.input_terminals[b]=c},enable_output_terminal:function(d,a,f){var g=this;var c=d;var b=d.terminal=new OutputTerminal(d,f);b.node=g;b.name=a;$(d).bind("dragstart",function(j,k){$(k.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var i=$('
').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var l=new Connector();l.dragging=true;l.connect(d.terminal,i.terminal);return i}).bind("drag",function(i,j){var h=function(){var l=$(j.proxy).offsetParent().offset(),k=j.offsetX-l.left,m=j.offsetY-l.top;$(j.proxy).css({left:k,top:m});j.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h,i){i.proxy.terminal.connectors[0].destroy();$(i.proxy).remove();$(i.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});g.output_terminals[a]=b},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(h){var g=this.element;if(h.type){this.type=h.type}this.name=h.name;this.form_html=h.form_html;this.tool_state=h.tool_state;this.tool_errors=h.tool_errors;this.tooltip=h.tooltip?h.tooltip:"";this.annotation=h.annotation;this.post_job_actions=h.post_job_actions?h.post_job_actions:{};this.workflow_outputs=h.workflow_outputs?h.workflow_outputs:[];if(this.tool_errors){g.addClass("tool-node-error")}else{g.removeClass("tool-node-error")}var d=this;var c=Math.max(150,g.width());var a=g.find(".toolFormBody");a.find("div").remove();var i=$("
").appendTo(a);$.each(h.data_inputs,function(k,f){var j=d.new_input_terminal(f);var b=$("
"+f.label+"
");b.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(b);c=Math.max(c,b.outerWidth());b.css({position:"",left:"",top:"",display:""});b.remove();i.append(b.prepend(j))});if((h.data_inputs.length>0)&&(h.data_outputs.length>0)){a.append($("
"))}$.each(h.data_outputs,function(k,b){var j=$("
");d.enable_output_terminal(j[0],b.name,b.extensions);var f=b.name;if(b.extensions.indexOf("input")<0){f=f+" ("+b.extensions.join(", ")+")"}var m=$("
"+f+"
");if(d.type=="tool"){var l=$("
").css({display:"none"}).append($("
").append($("").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(b.name,d.workflow_outputs)!=-1){d.workflow_outputs.splice($.inArray(b.name,d.workflow_outputs),1);l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{d.workflow_outputs.push(b.name);l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});l.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});l.show();m.append(l);if($.inArray(b.name,d.workflow_outputs)===-1){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}m.hover(function(){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")},function(){if($.inArray(b.name,d.workflow_outputs)===-1){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}})}m.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(m);c=Math.max(c,m.outerWidth()+17);m.css({position:"",left:"",top:"",display:""});m.detach();a.append(m.append(j))});g.css("width",Math.min(250,Math.max(g.width(),c)));workflow.node_changed(this)},update_field_data:function(d){var b=$(this.element),c=this;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{};if(this.tool_errors){b.addClass("tool-node-error")}else{b.removeClass("tool-node-error")}var g=b.find("div.inputs");var a=$("
");$.each(d.data_inputs,function(k,h){var j=c.new_input_terminal(h);g.find("div[name='"+h.name+"']").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j.terminal.connectors[0]=i;i.handle2=j.terminal}});$(this).remove()});a.append($("
"+h.label+"
").prepend(j))});g.replaceWith(a);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="
"+d+"
";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("
No node selected
")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("
");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("
"+j+"
");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("
");var h="
loading tool info...
";m.append(h);g.form_html=h;i.append(m);var k=$("
");k.append($("
").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-qA){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-qu){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}}); \ No newline at end of file diff --git a/static/scripts/packed/galaxy.workflows.js b/static/scripts/packed/galaxy.workflows.js index 32ca6a53869..3c353ebb802 100644 --- a/static/scripts/packed/galaxy.workflows.js +++ b/static/scripts/packed/galaxy.workflows.js @@ -1 +1 @@ -$(function(){if(window.lt_ie_7){show_modal("Browser not supported","Sorry, the workflow editor is not supported for IE6 and below.");return}$("#tool-search-query").click(function(){$(this).focus();$(this).select()}).keyup(function(){$(this).css("font-style","normal");if(this.value.length<3){reset_tool_search(false)}else{if(this.value!=this.lastValue){$(this).addClass("search_active");var g=this.value+"*";if(this.timer){clearTimeout(this.timer)}$("#search-spinner").show();this.timer=setTimeout(function(){$.get(tool_search_url,{query:g},function(i){$("#search-no-results").hide();$(".toolSectionWrapper").hide();$(".toolSectionWrapper").find(".toolTitle").hide();if(i.length!=0){var h=$.map(i,function(k,j){return"link-"+k});$(h).each(function(j,k){$("[id='"+k+"']").parent().addClass("search_match");$("[id='"+k+"']").parent().show().parent().parent().show().parent().show()});$(".toolPanelLabel").each(function(){var l=$(this);var k=l.next();var j=true;while(k.length!==0&&k.hasClass("toolTitle")){if(k.is(":visible")){j=false;break}else{k=k.next()}}if(j){l.hide()}})}else{$("#search-no-results").show()}$("#search-spinner").hide()},"json")},200)}}this.lastValue=this.value});canvas_manager=new CanvasManager($("#canvas-viewport"),$("#overview"));reset();$.ajax({url:get_datatypes_url,dataType:"json",cache:false,success:function(g){populate_datatype_info(g);$.ajax({url:load_workflow_url,data:{id:workflow_id,_:"true"},dataType:"json",cache:false,success:function(h){reset();workflow.from_simple(h);workflow.has_changes=false;workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview();upgrade_message="";$.each(h.upgrade_messages,function(j,i){upgrade_message+=("
  • Step "+(parseInt(j,10)+1)+": "+workflow.nodes[j].name+"
      ");$.each(i,function(k,l){upgrade_message+="
    • "+l+"
    • "});upgrade_message+="
  • "});if(upgrade_message){show_modal("Workflow loaded with changes","Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.
      "+upgrade_message+"
    ",{Continue:hide_modal})}else{hide_modal()}show_workflow_parameters()},beforeSubmit:function(h){show_message("Loading workflow","progress")}})}});$(document).ajaxStart(function(){active_ajax_call=true;$(document).bind("ajaxStop.global",function(){active_ajax_call=false})});$(document).ajaxError(function(i,g){var h=g.responseText||g.statusText||"Could not connect to server";show_modal("Server error",h,{"Ignore error":hide_modal});return false});make_popupmenu($("#workflow-options-button"),{Save:save_current_workflow,Run:function(){window.location=run_workflow_url},"Edit Attributes":c,"Auto Re-layout":f,Close:close_editor});function b(){workflow.clear_active_node();$(".right-content").hide();var j="";for(var h in workflow.nodes){var i=workflow.nodes[h];if(i.type=="tool"){j+="
    Step "+i.id+" - "+i.name+"
    ";for(var k in i.output_terminals){var g=i.output_terminals[k];if($.inArray(g.name,i.workflow_outputs)!=-1){j+="

    "+g.name+"

    "}else{j+="

    "+g.name+"

    "}}j+="
    "}}$("#output-fill-area").html(j);$("#output-fill-area input").bind("click",function(){var n=this.name.split("|")[0];var l=this.name.split("|")[1];if(this.checked){if($.inArray(l,workflow.nodes[n].workflow_outputs)==-1){workflow.nodes[n].workflow_outputs.push(l)}}else{while($.inArray(l,workflow.nodes[n].workflow_outputs)!=-1){var m=$.inArray(l,workflow.nodes[n].workflow_outputs);workflow.nodes[n].workflow_outputs=workflow.nodes[n].workflow_outputs.slice(0,m).concat(workflow.nodes[n].workflow_outputs.slice(m+1))}}workflow.has_changes=true});$("#workflow-output-area").show()}function f(){workflow.layout();workflow.fit_canvas_to_nodes();scroll_to_nodes();canvas_manager.draw_overview()}function c(){workflow.clear_active_node();$(".right-content").hide();$("#edit-attributes").show()}overview_size=$.jStorage.get("overview-size");if(overview_size!==undefined){$("#overview-border").css({width:overview_size,height:overview_size})}if($.jStorage.get("overview-off")){d()}else{e()}$("#overview-border").bind("dragend",function(h,j){var k=$(this).offsetParent();var i=k.offset();var g=Math.max(k.width()-(j.offsetX-i.left),k.height()-(j.offsetY-i.top));$.jStorage.set("overview-size",g+"px")});function e(){$.jStorage.set("overview-off",false);$("#overview-border").css("right","0px");$("#close-viewport").css("background-position","0px 0px")}function d(){$.jStorage.set("overview-off",true);$("#overview-border").css("right","20000px");$("#close-viewport").css("background-position","12px 0px")}$("#close-viewport").click(function(){if($("#overview-border").css("right")==="0px"){d()}else{e()}});window.onbeforeunload=function(){if(workflow&&workflow.has_changes){return"There are unsaved changes to your workflow which will be lost."}};$("div.toolSectionBody").hide();$("div.toolSectionTitle > span").wrap("");var a=null;$("div.toolSectionTitle").each(function(){var g=$(this).next("div.toolSectionBody");$(this).click(function(){if(g.is(":hidden")){if(a){a.slideUp("fast")}a=g;g.slideDown("fast")}else{g.slideUp("fast");a=null}})});async_save_text("workflow-name","workflow-name",rename_async_url,"new_name");$("#workflow-tag").click(function(){$(".tag-area").click();return false});async_save_text("workflow-annotation","workflow-annotation",annotate_async_url,"new_annotation",25,true,4)});function reset(){if(workflow){workflow.remove_all()}workflow=new Workflow($("#canvas-container"))}function scroll_to_nodes(){var a=$("#canvas-viewport");var d=$("#canvas-container");var c,b;if(d.width().toolForm:last>.toolFormTitle>.buttons").click(function(){action_to_rem=$(this).closest(".toolForm",".action_tag").children(".action_tag:first").text();$(this).closest(".toolForm").remove();delete workflow.active_node.post_job_actions[action_to_rem];workflow.active_form_has_changes=true})}function display_pja_list(){return pja_list}function display_file_list(b){addlist="";return addlist}function new_pja(d,b,a){if(a.post_job_actions===undefined){a.post_job_actions={}}if(a.post_job_actions[d+b]===undefined){var c={};c.action_type=d;c.output_name=b;a.post_job_actions[d+b]=null;a.post_job_actions[d+b]=c;display_pja(c,a);workflow.active_form_has_changes=true;return true}else{return false}}function show_workflow_parameters(){var c=/\$\{.+?\}/g;var b=[];var f=$("#workflow-parameters-container");var e=$("#workflow-parameters-box");var a="";var d=[];$.each(workflow.nodes,function(g,h){var i=h.form_html.match(c);if(i){d=d.concat(i)}if(h.post_job_actions){$.each(h.post_job_actions,function(j,l){if(l.action_arguments){$.each(l.action_arguments,function(m,n){var o=n.match(c);if(o){d=d.concat(o)}})}});if(d){$.each(d,function(j,l){if($.inArray(l,b)===-1){b.push(l)}})}}});if(b&&b.length!==0){$.each(b,function(g,h){a+="
    "+h.substring(2,h.length-1)+"
    "});f.html(a);e.show()}else{f.html(a);e.hide()}}function show_form_for_tool(c,b){$(".right-content").hide();$("#right-content").show().html(c);if(b){$("#right-content").find(".toolForm:first").after("

    Edit Step Attributes
    Add an annotation or notes to this step; annotations are available when a workflow is viewed.
    ")}if(b&&b.type=="tool"){pjastr="

    Edit Step Actions
    "+display_pja_list()+"
    "+display_file_list(b)+"
    Create
    ";pjastr+="
    Add actions to this step; actions are applied when this workflow step completes.
    ";$("#right-content").find(".toolForm").after(pjastr);for(var a in b.post_job_actions){if(a!="undefined"){display_pja(b.post_job_actions[a],b)}}$("#add_pja").click(function(){new_pja($("#new_pja_list").val(),$("#node_data_list").val(),b)})}$("#right-content").find("form").ajaxForm({type:"POST",dataType:"json",success:function(d){workflow.active_form_has_changes=false;b.update_field_data(d);show_workflow_parameters()},beforeSubmit:function(d){d.push({name:"tool_state",value:b.tool_state});d.push({name:"_",value:"true"})}}).each(function(){var d=this;$(this).find("select[refresh_on_change='true']").change(function(){$(d).submit()});$(this).find(".popupmenu").each(function(){var g=$(this).parents("div.form-row").attr("id");var e=$('▼');var f={};$(this).find("button").each(function(){var h=$(this).attr("name");var i=$(this).attr("value");f[$(this).text()]=function(){$(d).append("").submit()}});e.insertAfter(this);$(this).remove();make_popupmenu(e,f)});$(this).find("input,textarea,select").each(function(){$(this).bind("focus click",function(){workflow.active_form_has_changes=true})})})}var close_editor=function(){workflow.check_changes_in_active_form();if(workflow&&workflow.has_changes){do_close=function(){window.onbeforeunload=undefined;window.document.location=workflow_index_url};show_modal("Close workflow editor","There are unsaved changes to your workflow which will be lost.",{Cancel:hide_modal,"Save Changes":function(){save_current_workflow(null,do_close)}},{"Don't Save":do_close})}else{window.document.location=workflow_index_url}};var save_current_workflow=function(b,c){show_message("Saving workflow","progress");workflow.check_changes_in_active_form();if(!workflow.has_changes){hide_modal();if(c){c()}return}workflow.rectify_workflow_outputs();var a=function(d){$.ajax({url:save_workflow_url,type:"POST",data:{id:workflow_id,workflow_data:function(){return JSON.stringify(workflow.to_simple())},_:"true"},dataType:"json",success:function(g){var e=$("
    ").text(g.message);if(g.errors){e.addClass("warningmark");var f=$("