mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-10-25 00:12:08 +08:00
Merge pull request #4047 from bgruening/workflowexport_mako
New Workflow Management Screen UI using JavaScript
This commit is contained in:
@@ -8,9 +8,10 @@ var jQuery = require( 'jquery' ),
|
||||
HistoryPanel = require( './history-panel' ),
|
||||
PAGE = require( 'layout/page' ),
|
||||
ToolForm = require( 'mvc/tool/tool-form' ),
|
||||
UserPreferences = require( 'mvc/user/user-preferences' );
|
||||
CustomBuilds = require( 'mvc/user/user-custom-builds' );
|
||||
Tours = require( 'mvc/tours' );
|
||||
UserPreferences = require( 'mvc/user/user-preferences' ),
|
||||
CustomBuilds = require( 'mvc/user/user-custom-builds' ),
|
||||
Tours = require( 'mvc/tours' ),
|
||||
Workflows = require( 'mvc/workflow/workflow' );
|
||||
|
||||
/** define the 'Analyze Data'/analysis/main/home page for Galaxy
|
||||
* * has a masthead
|
||||
@@ -121,6 +122,7 @@ window.app = function app( options, bootstrapped ){
|
||||
'(/)tours(/)(:tour_id)' : 'show_tours',
|
||||
'(/)user(/)' : 'show_user',
|
||||
'(/)user(/)(:form_id)' : 'show_user_form',
|
||||
'(/)workflow(/)' : 'show_workflows',
|
||||
'(/)custom_builds' : 'show_custom_builds'
|
||||
},
|
||||
|
||||
@@ -153,6 +155,10 @@ window.app = function app( options, bootstrapped ){
|
||||
centerPanel.display( new UserPreferences.Forms( { form_id: form_id, user_id: Galaxy.params.id } ) );
|
||||
},
|
||||
|
||||
show_workflows : function(){
|
||||
centerPanel.display( new Workflows.View() );
|
||||
},
|
||||
|
||||
show_custom_builds : function() {
|
||||
var self = this;
|
||||
if ( !Galaxy.currHistoryPanel || !Galaxy.currHistoryPanel.model || !Galaxy.currHistoryPanel.model.id ) {
|
||||
|
||||
@@ -63,9 +63,9 @@ var ToolPanel = LeftPanel.extend({
|
||||
_renderWorkflowMenu : function(){
|
||||
var self = this;
|
||||
// add internal workflow list
|
||||
self.$( '#internal-workflows' ).append( self._templateTool({
|
||||
self.$( '#internal-workflows' ).append( self._templateAllWorkflow({
|
||||
title : _l( 'All workflows' ),
|
||||
href : 'workflow/list_for_run'
|
||||
href : 'workflow'
|
||||
}));
|
||||
_.each( self.stored_workflow_menu_entries, function( menu_entry ){
|
||||
self.$( '#internal-workflows' ).append( self._templateTool({
|
||||
@@ -85,6 +85,16 @@ var ToolPanel = LeftPanel.extend({
|
||||
].join('');
|
||||
},
|
||||
|
||||
/** build a link to 'All Workflows' */
|
||||
_templateAllWorkflow: function( tool ) {
|
||||
return [
|
||||
'<div class="toolTitle">',
|
||||
// global
|
||||
'<a href="', Galaxy.root, tool.href, '">', tool.title, '</a>',
|
||||
'</div>'
|
||||
].join('');
|
||||
},
|
||||
|
||||
/** override to include inital menu dom and workflow section */
|
||||
_templateBody : function(){
|
||||
return [
|
||||
|
||||
@@ -33,9 +33,13 @@ var Collection = Backbone.Collection.extend({
|
||||
this.add({
|
||||
id : 'workflow',
|
||||
title : _l('Workflow'),
|
||||
url : 'workflow',
|
||||
tooltip : _l('Chain tools into workflows'),
|
||||
disabled : !Galaxy.user.id
|
||||
disabled : !Galaxy.user.id,
|
||||
url : 'workflow',
|
||||
target : 'galaxy_main',
|
||||
onclick : function() {
|
||||
window.location = Galaxy.root + 'workflow';
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/** Workflow view */
|
||||
define( [], function() {
|
||||
|
||||
/** View of the main workflow list page */
|
||||
var View = Backbone.View.extend({
|
||||
|
||||
initialize: function() {
|
||||
this.setElement( '<div/>' );
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this,
|
||||
min_query_length = 3;
|
||||
$.getJSON( Galaxy.root + 'api/workflows/', function( workflows ) {
|
||||
var $el_workflow = null;
|
||||
// Add workflow header
|
||||
self.$el.empty().append( self._templateHeader() );
|
||||
// Add user actions message if any
|
||||
self.build_messages( self );
|
||||
$el_workflow = self.$el.find( '.user-workflows' );
|
||||
// Add the actions buttons
|
||||
$el_workflow.append( self._templateActionButtons() );
|
||||
if( workflows.length > 0) {
|
||||
$el_workflow.append( self._templateWorkflowTable( self, workflows) );
|
||||
self.adjust_actiondropdown( $el_workflow );
|
||||
// Register delete and run workflow events
|
||||
_.each( workflows, function( wf ) {
|
||||
self.confirm_delete( self, wf );
|
||||
});
|
||||
// Register search workflow event
|
||||
self.search_workflow( self, self.$el.find( '.search-wf' ), self.$el.find( '.workflow-search tr' ), min_query_length );
|
||||
}
|
||||
else {
|
||||
$el_workflow.append( self._templateNoWorkflow() );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Build messages after user action */
|
||||
build_messages: function( self ) {
|
||||
var $el_message = self.$el.find( '.response-message' ),
|
||||
status = self.get_querystring( 'status' ),
|
||||
message = self.get_querystring( 'message' );
|
||||
|
||||
if( message && message !== null && message !== "" ) {
|
||||
$el_message.addClass( status + 'message' );
|
||||
$el_message.html( '<p>' + message + '</p>' );
|
||||
}
|
||||
else {
|
||||
$el_message.html("");
|
||||
}
|
||||
},
|
||||
|
||||
/** Add confirm box before removing/unsharing workflow */
|
||||
confirm_delete: function( self, workflow ) {
|
||||
var $el_wf_link = self.$el.find( '.link-confirm-' + workflow.id ),
|
||||
$el_shared_wf_link = self.$el.find( '.link-confirm-shared-' + workflow.id );
|
||||
$el_wf_link.click( function() {
|
||||
return confirm( "Are you sure you want to delete workflow '" + workflow.name + "'?" );
|
||||
});
|
||||
$el_shared_wf_link.click( function() {
|
||||
return confirm( "Are you sure you want to remove the shared workflow '" + workflow.name + "'?" );
|
||||
});
|
||||
},
|
||||
|
||||
/** Implement client side workflow search/filtering */
|
||||
search_workflow: function( self, $el_searchinput, $el_tabletr, min_querylen ) {
|
||||
$el_searchinput.on( 'keyup', function () {
|
||||
var query = $( this ).val();
|
||||
// Filter when query is at least 3 characters
|
||||
// otherwise show all rows
|
||||
if( query.length >= min_querylen ) {
|
||||
// Ignore the query's case using 'i'
|
||||
var regular_expression = new RegExp( query, 'i' );
|
||||
$el_tabletr.hide();
|
||||
$el_tabletr.filter(function () {
|
||||
// Apply regular expression on each row's text
|
||||
// and show when there is a match
|
||||
return regular_expression.test( $( this ).text() );
|
||||
}).show();
|
||||
}
|
||||
else {
|
||||
$el_tabletr.show();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Get querystrings from url */
|
||||
get_querystring: function( key ) {
|
||||
return decodeURIComponent( window.location.search.replace(new RegExp("^(?:.*[&\\?]" + encodeURIComponent( key ).replace(/[\.\+\*]/g, "\\$&") + "(?:\\=([^&]*))?)?.*$", "i"), "$1") );
|
||||
},
|
||||
|
||||
/** Ajust the position of dropdown with respect to table */
|
||||
adjust_actiondropdown: function( $el ) {
|
||||
$el.on( 'show.bs.dropdown', function () {
|
||||
$el.css( "overflow", "inherit" );
|
||||
});
|
||||
|
||||
$el.on( 'hide.bs.dropdown', function () {
|
||||
$el.css( "overflow", "auto" );
|
||||
});
|
||||
},
|
||||
|
||||
/** Template for no workflow */
|
||||
_templateNoWorkflow: function() {
|
||||
return '<div class="wf-nodata"> You have no workflows. </div>';
|
||||
},
|
||||
|
||||
/** Template for actions buttons */
|
||||
_templateActionButtons: function() {
|
||||
return '<ul class="manage-table-actions">' +
|
||||
'<li>' +
|
||||
'<input class="search-wf form-control" type="text" autocomplete="off" placeholder="search for workflow...">' +
|
||||
'</li>' +
|
||||
'<li>' +
|
||||
'<a class="action-button fa fa-plus wf-action" id="new-workflow" title="Create new workflow" href="'+ Galaxy.root +'workflow/create">' +
|
||||
'</a>' +
|
||||
'</li>' +
|
||||
'<li>' +
|
||||
'<a class="action-button fa fa-upload wf-action" id="import-workflow" title="Upload or import workflow" href="'+ Galaxy.root +'workflow/import_workflow">' +
|
||||
'</a>' +
|
||||
'</li>' +
|
||||
'</ul>';
|
||||
},
|
||||
|
||||
/** Template for workflow table */
|
||||
_templateWorkflowTable: function( self, workflows ) {
|
||||
var tableHtml = "", trHtml = "";
|
||||
tableHtml = tableHtml + '<table class="table colored"><thead>' +
|
||||
'<tr class="header">' +
|
||||
'<th class="wf-td">Name</th>' +
|
||||
'<th class="wf-td">Owner</th>' +
|
||||
'<th class="wf-td"># of Steps</th>' +
|
||||
'<th class="wf-td">Published</th>' +
|
||||
'</tr></thead>';
|
||||
_.each( workflows, function( wf ) {
|
||||
trHtml = trHtml + '<tr>' +
|
||||
'<td class="wf-td wf-dpd">' +
|
||||
'<div class="dropdown">' +
|
||||
'<button class="menubutton" type="button" data-toggle="dropdown">' +
|
||||
_.escape( wf.name ) + '<span class="caret"></span>' +
|
||||
'</button>' +
|
||||
self._templateActions( wf ) +
|
||||
'</div>' +
|
||||
'</td>' +
|
||||
'<td>' + ( wf.owner === Galaxy.user.attributes.username ? "You" : wf.owner ) +'</td>' +
|
||||
'<td class="wf-td">' + wf.number_of_steps + '</td>' +
|
||||
'<td class="wf-td">' + ( wf.published ? "Yes" : "No" ) + '</td>' +
|
||||
'</tr>';
|
||||
});
|
||||
return tableHtml + '<tbody class="workflow-search">' + trHtml + '</tbody></table>';
|
||||
},
|
||||
|
||||
/** Template for user actions for workflows */
|
||||
_templateActions: function( workflow ) {
|
||||
if( workflow.owner === Galaxy.user.attributes.username ) {
|
||||
return '<ul class="dropdown-menu action-dpd">' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/editor?id='+ workflow.id +'">Edit</a></li>' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/run?id='+ workflow.id +'" target="galaxy_main">Run</a></li>' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/sharing?id='+ workflow.id +'">Share or Download</a></li>' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/copy?id='+ workflow.id +'">Copy</a></li>' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/rename?id='+ workflow.id +'">Rename</a></li>' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/display_by_id?id='+ workflow.id +'">View</a></li>' +
|
||||
'<li><a class="link-confirm-'+ workflow.id +'" href="'+ Galaxy.root +'workflow/delete?id='+ workflow.id +'">Delete</a></li>' +
|
||||
'</ul>';
|
||||
}
|
||||
else {
|
||||
return '<ul class="dropdown-menu action-dpd">' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/display_by_username_and_slug?username='+ workflow.owner +'&slug='+ workflow.slug +'">View</a></li>' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/run?id='+ workflow.id +'" target="galaxy_main">Run</a></li>' +
|
||||
'<li><a href="'+ Galaxy.root +'workflow/copy?id='+ workflow.id +'">Copy</a></li>' +
|
||||
'<li><a class="link-confirm-shared-'+ workflow.id +'" href="'+ Galaxy.root +'workflow/sharing?unshare_me=True&id='+ workflow.id +'">Remove</a></li>' +
|
||||
'</ul>';
|
||||
}
|
||||
},
|
||||
|
||||
/** Main template */
|
||||
_templateHeader: function() {
|
||||
return '<div class="page-container">' +
|
||||
'<div class="user-workflows wf">' +
|
||||
'<div class="response-message"></div>' +
|
||||
'<h2>Your workflows</h2>' +
|
||||
'</div>'+
|
||||
'<div class="other-options wf">' +
|
||||
'<h2>Other options</h2>' +
|
||||
'<a class="action-button fa fa-cog wf-action" href="'+ Galaxy.root +'workflow/configure_menu" title="Configure your workflow menu">' +
|
||||
'<span>Configure your workflow menu</span>' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
View : View
|
||||
};
|
||||
});
|
||||
@@ -1766,4 +1766,27 @@ div.toolTitleNoSection
|
||||
color:black;
|
||||
text-align:left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// workflow
|
||||
.wf {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.wf-action span {
|
||||
padding-left: 3px;
|
||||
font-family: "Lucida Grande", verdana, arial, helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.wf-td {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.wf-nodata {
|
||||
padding-left: 1%;
|
||||
}
|
||||
|
||||
.other-options {
|
||||
margin-bottom: 2%;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ class WorkflowsAPIController(BaseAPIController, UsesStoredWorkflowMixin, UsesAnn
|
||||
encoded_id = trans.security.encode_id(wf.id)
|
||||
item['url'] = url_for('workflow', id=encoded_id)
|
||||
item['owner'] = wf.user.username
|
||||
item['number_of_steps'] = len( wf.latest_workflow.steps )
|
||||
rval.append(item)
|
||||
for wf_sa in trans.sa_session.query( trans.app.model.StoredWorkflowUserShareAssociation ).filter_by(
|
||||
user=trans.user ).join( 'stored_workflow' ).filter(
|
||||
@@ -74,6 +75,8 @@ class WorkflowsAPIController(BaseAPIController, UsesStoredWorkflowMixin, UsesAnn
|
||||
encoded_id = trans.security.encode_id(wf_sa.stored_workflow.id)
|
||||
item['url'] = url_for( 'workflow', id=encoded_id )
|
||||
item['owner'] = wf_sa.stored_workflow.user.username
|
||||
item['number_of_steps'] = len( wf_sa.stored_workflow.latest_workflow.steps )
|
||||
item['slug'] = wf_sa.stored_workflow.slug
|
||||
rval.append(item)
|
||||
return rval
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ def paste_app_factory( global_conf, **kwargs ):
|
||||
webapp.add_client_route( '/tours/{tour_id}' )
|
||||
webapp.add_client_route( '/user' )
|
||||
webapp.add_client_route( '/user/{form_id}' )
|
||||
webapp.add_client_route( '/workflow' )
|
||||
webapp.add_client_route( '/custom_builds' )
|
||||
|
||||
# ==== Done
|
||||
|
||||
@@ -155,10 +155,6 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
|
||||
__myexp_url = "www.myexperiment.org:80"
|
||||
|
||||
@web.expose
|
||||
def index( self, trans ):
|
||||
return self.list( trans )
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
def list_grid( self, trans, **kwargs ):
|
||||
@@ -179,52 +175,9 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
"""
|
||||
Render workflow main page (management of existing workflows)
|
||||
"""
|
||||
user = trans.get_user()
|
||||
workflows = trans.sa_session.query( model.StoredWorkflow ) \
|
||||
.filter_by( user=user, deleted=False ) \
|
||||
.order_by( desc( model.StoredWorkflow.table.c.update_time ) ) \
|
||||
.all()
|
||||
shared_by_others = trans.sa_session \
|
||||
.query( model.StoredWorkflowUserShareAssociation ) \
|
||||
.filter_by( user=user ) \
|
||||
.join( 'stored_workflow' ) \
|
||||
.filter( model.StoredWorkflow.deleted == expression.false() ) \
|
||||
.order_by( desc( model.StoredWorkflow.update_time ) ) \
|
||||
.all()
|
||||
|
||||
# Legacy issue: all shared workflows must have slugs.
|
||||
slug_set = False
|
||||
for workflow_assoc in shared_by_others:
|
||||
if self.create_item_slug( trans.sa_session, workflow_assoc.stored_workflow ):
|
||||
slug_set = True
|
||||
if slug_set:
|
||||
trans.sa_session.flush()
|
||||
|
||||
return trans.fill_template( "workflow/list.mako",
|
||||
workflows=workflows,
|
||||
shared_by_others=shared_by_others )
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
def list_for_run( self, trans ):
|
||||
"""
|
||||
Render workflow list for analysis view (just allows running workflow
|
||||
or switching to management view)
|
||||
"""
|
||||
user = trans.get_user()
|
||||
workflows = trans.sa_session.query( model.StoredWorkflow ) \
|
||||
.filter_by( user=user, deleted=False ) \
|
||||
.order_by( desc( model.StoredWorkflow.table.c.update_time ) ) \
|
||||
.all()
|
||||
shared_by_others = trans.sa_session \
|
||||
.query( model.StoredWorkflowUserShareAssociation ) \
|
||||
.filter_by( user=user ) \
|
||||
.filter( model.StoredWorkflow.deleted == expression.false() ) \
|
||||
.order_by( desc( model.StoredWorkflow.table.c.update_time ) ) \
|
||||
.all()
|
||||
return trans.fill_template( "workflow/list_for_run.mako",
|
||||
workflows=workflows,
|
||||
shared_by_others=shared_by_others )
|
||||
# Take care of proxy prefix in url as well
|
||||
redirect_url = url_for( '/' ) + 'workflow'
|
||||
return trans.response.send_redirect( redirect_url )
|
||||
|
||||
@web.expose
|
||||
def list_published( self, trans, **kwargs ):
|
||||
@@ -425,8 +378,11 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
stored.name = san_new_name
|
||||
stored.latest_workflow.name = san_new_name
|
||||
trans.sa_session.flush()
|
||||
trans.set_message( "Workflow renamed to '%s'." % san_new_name )
|
||||
return self.list( trans )
|
||||
message = 'Workflow renamed to: %s' % escape( san_new_name )
|
||||
trans.set_message( message )
|
||||
# Take care of proxy prefix in url as well
|
||||
redirect_url = url_for( '/' ) + 'workflow?status=done&message=%s' % escape( message )
|
||||
return trans.response.send_redirect( redirect_url )
|
||||
else:
|
||||
return form( url_for(controller='workflow', action='rename', id=trans.security.encode_id(stored.id) ),
|
||||
"Rename workflow",
|
||||
@@ -543,7 +499,7 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
if (save_as_name):
|
||||
new_stored.name = '%s' % save_as_name
|
||||
else:
|
||||
new_stored.name = "Copy of '%s'" % stored.name
|
||||
new_stored.name = "Copy of %s" % stored.name
|
||||
new_stored.latest_workflow = stored.latest_workflow
|
||||
# Copy annotation.
|
||||
annotation_obj = self.get_item_annotation_obj( trans.sa_session, stored.user, stored )
|
||||
@@ -551,15 +507,17 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
self.add_item_annotation( trans.sa_session, trans.get_user(), new_stored, annotation_obj.annotation )
|
||||
new_stored.copy_tags_from(trans.user, stored)
|
||||
if not owner:
|
||||
new_stored.name += " shared by '%s'" % stored.user.email
|
||||
new_stored.name += " shared by %s" % stored.user.email
|
||||
new_stored.user = user
|
||||
# Persist
|
||||
session = trans.sa_session
|
||||
session.add( new_stored )
|
||||
session.flush()
|
||||
# Display the management page
|
||||
trans.set_message( 'Created new workflow with name "%s"' % escape( new_stored.name ) )
|
||||
return self.list( trans )
|
||||
message = 'Created new workflow with name: %s' % escape( new_stored.name )
|
||||
trans.set_message( message )
|
||||
return_url = url_for( '/' ) + 'workflow?status=done&message=%s' % escape( message )
|
||||
trans.response.send_redirect( return_url )
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "create workflows" )
|
||||
@@ -652,8 +610,9 @@ class WorkflowController( BaseUIController, SharableMixin, UsesStoredWorkflowMix
|
||||
trans.sa_session.add( stored )
|
||||
trans.sa_session.flush()
|
||||
# Display the management page
|
||||
trans.set_message( "Workflow '%s' deleted" % escape( stored.name ) )
|
||||
return self.list( trans )
|
||||
message = "Workflow deleted: %s" % escape( stored.name )
|
||||
trans.set_message( message )
|
||||
return trans.response.send_redirect( url_for( '/' ) + 'workflow?status=done&message=%s' % escape( message ) )
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "edit workflows" )
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"workflow.js","sources":["../../../src/mvc/workflow/workflow.js"],"names":["define","View","Backbone","extend","initialize","this","setElement","render","self","min_query_length","$","getJSON","Galaxy","root","workflows","$el_workflow","$el","empty","append","_templateHeader","build_messages","find","_templateActionButtons","length","_templateWorkflowTable","adjust_actiondropdown","_","each","wf","confirm_delete","search_workflow","_templateNoWorkflow","$el_message","status","get_querystring","message","addClass","html","workflow","$el_wf_link","id","$el_shared_wf_link","click","confirm","name","$el_searchinput","$el_tabletr","min_querylen","on","query","val","regular_expression","RegExp","hide","filter","test","text","show","key","decodeURIComponent","window","location","search","replace","encodeURIComponent","css","tableHtml","trHtml","escape","_templateActions","owner","user","attributes","username","number_of_steps","published","slug"],"mappings":"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"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
define([],function(){var a=Backbone.View.extend({initialize:function(){this.setElement("<div/>"),this.render()},render:function(){var a=this,b=3;$.getJSON(Galaxy.root+"api/workflows/",function(c){var d=null;a.$el.empty().append(a._templateHeader()),a.build_messages(a),d=a.$el.find(".user-workflows"),d.append(a._templateActionButtons()),c.length>0?(d.append(a._templateWorkflowTable(a,c)),a.adjust_actiondropdown(d),_.each(c,function(b){a.confirm_delete(a,b)}),a.search_workflow(a,a.$el.find(".search-wf"),a.$el.find(".workflow-search tr"),b)):d.append(a._templateNoWorkflow())})},build_messages:function(a){var b=a.$el.find(".response-message"),c=a.get_querystring("status"),d=a.get_querystring("message");d&&null!==d&&""!==d?(b.addClass(c+"message"),b.html("<p>"+d+"</p>")):b.html("")},confirm_delete:function(a,b){var c=a.$el.find(".link-confirm-"+b.id),d=a.$el.find(".link-confirm-shared-"+b.id);c.click(function(){return confirm("Are you sure you want to delete workflow '"+b.name+"'?")}),d.click(function(){return confirm("Are you sure you want to remove the shared workflow '"+b.name+"'?")})},search_workflow:function(a,b,c,d){b.on("keyup",function(){var a=$(this).val();if(a.length>=d){var b=new RegExp(a,"i");c.hide(),c.filter(function(){return b.test($(this).text())}).show()}else c.show()})},get_querystring:function(a){return decodeURIComponent(window.location.search.replace(new RegExp("^(?:.*[&\\?]"+encodeURIComponent(a).replace(/[\.\+\*]/g,"\\$&")+"(?:\\=([^&]*))?)?.*$","i"),"$1"))},adjust_actiondropdown:function(a){a.on("show.bs.dropdown",function(){a.css("overflow","inherit")}),a.on("hide.bs.dropdown",function(){a.css("overflow","auto")})},_templateNoWorkflow:function(){return'<div class="wf-nodata"> You have no workflows. </div>'},_templateActionButtons:function(){return'<ul class="manage-table-actions"><li><input class="search-wf form-control" type="text" autocomplete="off" placeholder="search for workflow..."></li><li><a class="action-button fa fa-plus wf-action" id="new-workflow" title="Create new workflow" href="'+Galaxy.root+'workflow/create"></a></li><li><a class="action-button fa fa-upload wf-action" id="import-workflow" title="Upload or import workflow" href="'+Galaxy.root+'workflow/import_workflow"></a></li></ul>'},_templateWorkflowTable:function(a,b){var c="",d="";return c+='<table class="table colored"><thead><tr class="header"><th class="wf-td">Name</th><th class="wf-td">Owner</th><th class="wf-td"># of Steps</th><th class="wf-td">Published</th></tr></thead>',_.each(b,function(b){d=d+'<tr><td class="wf-td wf-dpd"><div class="dropdown"><button class="menubutton" type="button" data-toggle="dropdown">'+_.escape(b.name)+'<span class="caret"></span></button>'+a._templateActions(b)+"</div></td><td>"+(b.owner===Galaxy.user.attributes.username?"You":b.owner)+'</td><td class="wf-td">'+b.number_of_steps+'</td><td class="wf-td">'+(b.published?"Yes":"No")+"</td></tr>"}),c+'<tbody class="workflow-search">'+d+"</tbody></table>"},_templateActions:function(a){return a.owner===Galaxy.user.attributes.username?'<ul class="dropdown-menu action-dpd"><li><a href="'+Galaxy.root+"workflow/editor?id="+a.id+'">Edit</a></li><li><a href="'+Galaxy.root+"workflow/run?id="+a.id+'" target="galaxy_main">Run</a></li><li><a href="'+Galaxy.root+"workflow/sharing?id="+a.id+'">Share or Download</a></li><li><a href="'+Galaxy.root+"workflow/copy?id="+a.id+'">Copy</a></li><li><a href="'+Galaxy.root+"workflow/rename?id="+a.id+'">Rename</a></li><li><a href="'+Galaxy.root+"workflow/display_by_id?id="+a.id+'">View</a></li><li><a class="link-confirm-'+a.id+'" href="'+Galaxy.root+"workflow/delete?id="+a.id+'">Delete</a></li></ul>':'<ul class="dropdown-menu action-dpd"><li><a href="'+Galaxy.root+"workflow/display_by_username_and_slug?username="+a.owner+"&slug="+a.slug+'">View</a></li><li><a href="'+Galaxy.root+"workflow/run?id="+a.id+'" target="galaxy_main">Run</a></li><li><a href="'+Galaxy.root+"workflow/copy?id="+a.id+'">Copy</a></li><li><a class="link-confirm-shared-'+a.id+'" href="'+Galaxy.root+"workflow/sharing?unshare_me=True&id="+a.id+'">Remove</a></li></ul>'},_templateHeader:function(){return'<div class="page-container"><div class="user-workflows wf"><div class="response-message"></div><h2>Your workflows</h2></div><div class="other-options wf"><h2>Other options</h2><a class="action-button fa fa-cog wf-action" href="'+Galaxy.root+'workflow/configure_menu" title="Configure your workflow menu"><span>Configure your workflow menu</span></a></div></div>'}});return{View:a}});
|
||||
//# sourceMappingURL=../../../maps/mvc/workflow/workflow.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,122 +0,0 @@
|
||||
<%inherit file="/webapps/galaxy/base_panels.mako"/>
|
||||
|
||||
<%def name="init()">
|
||||
<%
|
||||
self.has_left_panel=False
|
||||
self.has_right_panel=False
|
||||
self.active_view="workflow"
|
||||
self.message_box_visible=False
|
||||
%>
|
||||
</%def>
|
||||
|
||||
<%def name="title()">Workflow home</%def>
|
||||
|
||||
<%def name="center_panel()">
|
||||
<div style="overflow: auto; height: 100%;">
|
||||
<div class="page-container" style="padding: 10px;">
|
||||
%if message:
|
||||
<%
|
||||
try:
|
||||
status
|
||||
except:
|
||||
status = "done"
|
||||
%>
|
||||
<p />
|
||||
<div class="${status}message">
|
||||
${h.to_unicode( message )}
|
||||
</div>
|
||||
%endif
|
||||
|
||||
<h2>Your workflows</h2>
|
||||
|
||||
<ul class="manage-table-actions">
|
||||
<li>
|
||||
<a class="action-button" id="new-workflow" href="${h.url_for( controller='workflow', action='create' )}">
|
||||
<img src="${h.url_for('/static/images/silk/add.png')}" />
|
||||
<span>Create new workflow</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="action-button" id="import-workflow" href="${h.url_for( controller='workflow', action='import_workflow' )}">
|
||||
<img src="${h.url_for('/static/images/fugue/arrow-090.png')}" />
|
||||
<span>Upload or import workflow</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
%if workflows:
|
||||
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" style="width:100%;">
|
||||
<tr class="header">
|
||||
<th>Name</th>
|
||||
<th># of Steps</th>
|
||||
## <th>Last Updated</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
%for i, workflow in enumerate( workflows ):
|
||||
<tr>
|
||||
<td>
|
||||
<div class="menubutton" style="float: left;" id="wf-${i}-popup">
|
||||
${h.to_unicode( workflow.name ) | h}
|
||||
</div>
|
||||
</td>
|
||||
<td>${len(workflow.latest_workflow.steps)}</td>
|
||||
## <td>${str(workflow.update_time)[:19]}</td>
|
||||
<td>
|
||||
<div popupmenu="wf-${i}-popup">
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='editor', id=trans.security.encode_id( workflow.id ) )}" target="_parent">Edit</a>
|
||||
<a class="action-button" href="${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id( workflow.id ) )}" target="_parent">Run</a>
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='sharing', id=trans.security.encode_id( workflow.id ) )}">Share or Download</a>
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='copy', id=trans.security.encode_id( workflow.id ) )}">Copy</a>
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='rename', id=trans.security.encode_id( workflow.id ) )}">Rename</a>
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='display_by_id', id=trans.security.encode_id( workflow.id ) )}" target="_top">View</a>
|
||||
<a class="action-button" confirm="Are you sure you want to delete workflow '${h.to_unicode( workflow.name ) | h}'?" href="${h.url_for( controller='workflow', action='delete', id=trans.security.encode_id( workflow.id ) )}">Delete</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</table>
|
||||
%else:
|
||||
You have no workflows.
|
||||
%endif
|
||||
|
||||
<h2>Workflows shared with you by others</h2>
|
||||
|
||||
%if shared_by_others:
|
||||
<table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
|
||||
<tr class="header">
|
||||
<th>Name</th>
|
||||
<th>Owner</th>
|
||||
<th># of Steps</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
%for i, association in enumerate( shared_by_others ):
|
||||
<% workflow = association.stored_workflow %>
|
||||
<tr>
|
||||
<td>
|
||||
<a class="menubutton" id="shared-${i}-popup" href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name ) | h}</a>
|
||||
</td>
|
||||
<td>${workflow.user.email}</td>
|
||||
<td>${len(workflow.latest_workflow.steps)}</td>
|
||||
<td>
|
||||
<div popupmenu="shared-${i}-popup">
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='display_by_username_and_slug', username=workflow.user.username, slug=workflow.slug )}" target="_top">View</a>
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id( workflow.id ) )}">Run</a>
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='copy', id=trans.security.encode_id( workflow.id ) )}">Copy</a>
|
||||
<a class="action-button" confirm="Are you sure you want to remove the shared workflow '${h.to_unicode( workflow.name ) | h}'?" href="${h.url_for( controller='workflow', action='sharing', unshare_me=True, id=trans.security.encode_id( workflow.id ))}">Remove</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</table>
|
||||
%else:
|
||||
No workflows have been shared with you.
|
||||
%endif
|
||||
|
||||
<h2>Other options</h2>
|
||||
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='configure_menu' )}">
|
||||
<span>Configure your workflow menu</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</%def>
|
||||
@@ -1,66 +0,0 @@
|
||||
<%inherit file="/base.mako"/>
|
||||
|
||||
<%def name="title()">Workflow home</%def>
|
||||
|
||||
<h2>Your workflows</h2>
|
||||
|
||||
<ul class="manage-table-actions">
|
||||
<li>
|
||||
<a class="action-button" href="${h.url_for( controller='workflow', action='index' )}" target="_parent">
|
||||
<span>Switch to workflow management view</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
%if workflows:
|
||||
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
|
||||
<tr class="header">
|
||||
<th>Name</th>
|
||||
<th># of Steps</th>
|
||||
## <th>Last Updated</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
%for i, workflow in enumerate( workflows ):
|
||||
<tr>
|
||||
<td>
|
||||
<a href="${h.url_for(controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${h.to_unicode( workflow.name ) | h}</a>
|
||||
<a id="wf-${i}-popup" class="popup-arrow" style="display: none;">▼</a>
|
||||
</td>
|
||||
<td>${len(workflow.latest_workflow.steps)}</td>
|
||||
## <td>${str(workflow.update_time)[:19]}</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</table>
|
||||
%else:
|
||||
|
||||
You have no workflows.
|
||||
|
||||
%endif
|
||||
|
||||
<h2>Workflows shared with you by others</h2>
|
||||
|
||||
%if shared_by_others:
|
||||
<table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
|
||||
<tr class="header">
|
||||
<th>Name</th>
|
||||
<th>Owner</th>
|
||||
<th># of Steps</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
%for i, association in enumerate( shared_by_others ):
|
||||
<% workflow = association.stored_workflow %>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name | h}</a>
|
||||
<a id="shared-${i}-popup" class="popup-arrow" style="display: none;">▼</a>
|
||||
</td>
|
||||
<td>${workflow.user.email | h}</td>
|
||||
<td>${len(workflow.latest_workflow.steps)}</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</table>
|
||||
%else:
|
||||
|
||||
No workflows have been shared with you.
|
||||
|
||||
%endif
|
||||
@@ -394,17 +394,16 @@ class NavigatesGalaxy(HasDriver):
|
||||
self.click_masthead_workflow()
|
||||
|
||||
def workflow_index_table_elements(self):
|
||||
self.wait_for_selector_visible(".manage-table tbody")
|
||||
table_elements = self.driver.find_elements_by_css_selector(".manage-table tbody > tr")
|
||||
# drop header
|
||||
return table_elements[1:]
|
||||
self.wait_for_selector_visible("tbody.workflow-search")
|
||||
table_elements = self.driver.find_elements_by_css_selector("tbody.workflow-search > tr")
|
||||
return table_elements
|
||||
|
||||
def workflow_index_click_option(self, option_title, workflow_index=0):
|
||||
table_elements = self.workflow_index_table_elements()
|
||||
workflow_row = table_elements[workflow_index]
|
||||
workflow_button = workflow_row.find_element_by_css_selector(".menubutton")
|
||||
workflow_button.click()
|
||||
menu_element = self.wait_for_selector_visible(".popmenu-wrapper .dropdown-menu")
|
||||
menu_element = self.wait_for_selector_visible("ul.action-dpd")
|
||||
menu_options = menu_element.find_elements_by_css_selector("li a")
|
||||
found_option = False
|
||||
for menu_option in menu_options:
|
||||
|
||||
@@ -45,7 +45,8 @@ class WorkflowManagementTestCase(SeleniumTestCase):
|
||||
assert 'CoolNewName' in renamed_workflow_button.text, renamed_workflow_button.text
|
||||
|
||||
def _workflow_import_from_url(self):
|
||||
self.click_selector(self.test_data["selectors"]["workflows"]["import_button"])
|
||||
element = self.wait_for_selector_clickable(self.test_data["selectors"]["workflows"]["import_button"])
|
||||
element.click()
|
||||
url = "https://raw.githubusercontent.com/galaxyproject/galaxy/dev/test/base/data/test_workflow_1.ga"
|
||||
form_element = self.driver.find_element_by_css_selector("#center form")
|
||||
url_element = form_element.find_element_by_css_selector("input[type='text']")
|
||||
|
||||
Reference in New Issue
Block a user