Skip to content

Commit

Permalink
Merging with dev
Browse files Browse the repository at this point in the history
  • Loading branch information
anuprulez committed May 30, 2017
2 parents 094dbe9 + d61ab16 commit 6dba0c7
Show file tree
Hide file tree
Showing 19 changed files with 260 additions and 181 deletions.
13 changes: 11 additions & 2 deletions client/galaxy/scripts/apps/analysis.js
Expand Up @@ -9,7 +9,8 @@ var jQuery = require( 'jquery' ),
UserPreferences = require( 'mvc/user/user-preferences' ),
CustomBuilds = require( 'mvc/user/user-custom-builds' ),
Tours = require( 'mvc/tours' ),
Workflows = require( 'mvc/workflow/workflow' );
Workflows = require( 'mvc/workflow/workflow' ),
WorkflowsConfigureMenu = require( 'mvc/workflow/workflow-configure-menu' );

/** define the 'Analyze Data'/analysis/main/home page for Galaxy
* * has a masthead
Expand Down Expand Up @@ -81,12 +82,16 @@ window.app = function app( options, bootstrapped ){
'(/)workflow(/)' : 'show_workflows',
'(/)custom_builds' : 'show_custom_builds',
'(/)workflow/run(/)' : 'show_run',
'(/)workflow/configure_menu(/)' : 'show_configure_menu',
'(/)workflow/import_workflow' : 'show_import_workflow',
'(/)custom_builds' : 'show_custom_builds'
},

require_login: [
'show_user',
'show_user_form'
'show_user_form',
'show_workflows',
'show_configure_menu'
],

loginRequired: function() {
Expand Down Expand Up @@ -125,6 +130,10 @@ window.app = function app( options, bootstrapped ){
this.page.display( new Workflows.Import_Workflow_View() );
},

show_configure_menu : function(){
this.page.display( new WorkflowsConfigureMenu.View() );
},

show_custom_builds : function() {
var self = this;
var historyPanel = this.page.historyPanel.historyView;
Expand Down
153 changes: 153 additions & 0 deletions client/galaxy/scripts/mvc/workflow/workflow-configure-menu.js
@@ -0,0 +1,153 @@
/** Configure Workflow Menu View */
define( [], function() {
var View = Backbone.View.extend({

initialize: function( options ) {
this.setElement( '<div/>' );
this.render();
},

render: function() {
var self = this;
$.getJSON( Galaxy.root + 'api/workflows/menu/', function( response ) {
var workflows = response.workflows,
ids_in_menu = response.ids_in_menu,
$el_config_worflow = null;

// Add configure workflow header
self.$el.empty().append( self._templateConfigWorkflowHeader() );
$el_config_worflow = self.$el.find( '.configure-workflows' );
$el_config_worflow.append( self._templateActionButtons() );
if( workflows.length > 0 ) {
$el_config_worflow.append( self._templateConfigureWorkflow( self, workflows, ids_in_menu ) );
self.save_workflow_menu( self );
self.make_checked( self, ids_in_menu );
self.register_check_uncheck_all( self );
}
else {
$el_config_worflow.append( self._templateNoWorkflow() );
}
});
},

/** Register check and uncheck all callbacks*/
register_check_uncheck_all: function( self ) {
var $el_check_all = self.$el.find( '.check-all-wf' ),
$el_uncheck_all = self.$el.find( '.uncheck-all-wf' );

$el_check_all.click(function( e ) {
self.check_uncheck_all( self, true );
});
$el_uncheck_all.click(function( e ) {
self.check_uncheck_all( self, false );
});
},

/** Check or uncheck all workflows */
check_uncheck_all: function( self, checked ) {
$.each(self.$el.find( '.wf-config-item' ), function() {
var wf_checkbox = $( this )[0];
wf_checkbox.checked = checked;
});
},

/** Make the worflows as checked if present in the menu */
make_checked: function( self, ids_in_menu ) {
$.each(self.$el.find( '.wf-config-item' ), function() {
var wf_checkbox = $( this )[0];
_.each( ids_in_menu, function( id ) {
if ( parseInt( wf_checkbox.value ) === id ) {
wf_checkbox.checked = true;
}
});
});
},

/** Save the changes for workflow menu */
save_workflow_menu: function( self ) {
var $el_save_workflow_menu = self.$el.find( '.wf-save-menu' );
$el_save_workflow_menu.click( function( e ) {
var ids = [];
$.each(self.$el.find( '.wf-config-item' ), function() {
var wf_checkbox = $( this )[0];
if( wf_checkbox.checked || wf_checkbox.checked === 'true' ) {
ids.push( parseInt( wf_checkbox.value ) );
}
});
$.ajax({
type: 'PUT',
url: Galaxy.root + 'api/workflows/menu/',
data: JSON.stringify( { 'workflow_ids': ids } ),
contentType : 'application/json'
}).done( function( response ) {
window.location = Galaxy.root + 'workflow?status='+ response.status +'&message=' + response.message;
});
});
},

/** Template for actions buttons */
_templateActionButtons: function() {
return '<ul class="manage-table-actions">' +
'<li>' +
'<a class="fa fa-check-square-o wf-action check-all-wf" title="Select all workflows" href="#">' +
'</a>' +
'</li>' +
'<li>' +
'<a class="fa fa-square-o wf-action uncheck-all-wf" title="Unselect all workflows" href="#">' +
'</a>' +
'</li>' +
'</ul>';
},

/** Template for configure workflow table */
_templateConfigureWorkflow: function( self, workflows, ids_in_menu ) {
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">Show in menu</th>' +
'</tr></thead>';
_.each( workflows, function( wf ) {
trHtml = trHtml + '<tr>' +
'<td class="wf-td">' + _.escape( wf.name ) +'</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">' + self._templateInputCheckbox( self, wf, ids_in_menu ) + '</td>' +
'</tr>';
});
tableHtml = tableHtml + '<tbody class="workflow-config-menu">' + trHtml + '</tbody></table>';
tableHtml = tableHtml + '<a class="action-button wf-save-menu wf-action fa fa-floppy-o" href="#" title="Save">' +
'<span>Save</span>' +
'</a>' +
'<a class="action-button wf-back wf-action fa fa-arrow-left" href="'+ Galaxy.root +'workflow" title="Back to workflow">' +
'<span>Back to workflow</span>' +
'</a>';
return tableHtml;
},

/** Template for no workflow */
_templateNoWorkflow: function() {
return '<div class="wf-nodata"> You do not have any accessible workflows. </div>';
},

/** Template for checkboxes */
_templateInputCheckbox: function( self, wf ) {
return '<input type="checkbox" class="wf-config-item" name="workflow_ids" value="'+ wf.id +'" />';
},

/** Template for main config workflow menu */
_templateConfigWorkflowHeader: function() {
return '<div class="page-container">' +
'<div class="configure-workflows wf">' +
'<h2>Configure workflow menu</h2>' +
'</div>'+
'</div>';
}
});

return {
View : View
};
});
2 changes: 1 addition & 1 deletion client/galaxy/scripts/mvc/workflow/workflow.js
Expand Up @@ -45,7 +45,7 @@ define( [ 'mvc/tool/tool-form-composite', 'mvc/form/form-view', 'mvc/ui/ui-misc'

if( message && message !== null && message !== "" ) {
$el_message.addClass( status + 'message' );
$el_message.html( '<p>' + message + '</p>' );
$el_message.html( '<p>' + _.escape(message) + '</p>' );
}
else {
$el_message.html("");
Expand Down
6 changes: 5 additions & 1 deletion client/galaxy/style/less/base.less
Expand Up @@ -1787,6 +1787,10 @@ div.toolTitleNoSection
padding-left: 1%;
}

.other-options {
.wf-back {
margin-left: 0.5%;
}

.other-options, .configure-workflows {
margin-bottom: 2%;
}
2 changes: 1 addition & 1 deletion lib/galaxy/jobs/runners/__init__.py
Expand Up @@ -419,7 +419,7 @@ def set_defaults( self, files_dir ):
job_name += '_%s' % self.job_wrapper.tool.old_id
if self.job_wrapper.user:
job_name += '_%s' % self.job_wrapper.user
self.job_name = ''.join( map( lambda x: x if x in ( string.letters + string.digits + '_' ) else '_', job_name ) )
self.job_name = ''.join( map( lambda x: x if x in ( string.ascii_letters + string.digits + '_' ) else '_', job_name ) )

@staticmethod
def default_job_file( files_dir, id_tag ):
Expand Down
2 changes: 1 addition & 1 deletion lib/galaxy/jobs/runners/drmaa.py
Expand Up @@ -394,7 +394,7 @@ def _job_name(self, job_wrapper):
job_name += '_%s' % job_wrapper.tool.old_id
if external_runjob_script is None:
job_name += '_%s' % job_wrapper.user
job_name = ''.join( x if x in ( string.letters + string.digits + '_' ) else '_' for x in job_name )
job_name = ''.join( x if x in ( string.ascii_letters + string.digits + '_' ) else '_' for x in job_name )
if self.restrict_job_name_length:
job_name = job_name[:self.restrict_job_name_length]
return job_name
75 changes: 65 additions & 10 deletions lib/galaxy/webapps/galaxy/api/workflows.py
Expand Up @@ -53,7 +53,59 @@ def __get_full_shed_url( self, url ):
def index(self, trans, **kwd):
"""
GET /api/workflows
"""
return self.get_workflows_list( trans, False, kwd )

@expose_api
def get_workflow_menu( self, trans, **kwd ):
"""
Get workflows present in the tools panel
GET /api/workflows/menu
"""
user = trans.get_user()
ids_in_menu = [ x.stored_workflow_id for x in user.stored_workflow_menu_entries ]
return {
'ids_in_menu': ids_in_menu,
'workflows': self.get_workflows_list( trans, True, kwd )
}

@expose_api
def set_workflow_menu( self, trans, **kwd ):
"""
Save workflow menu to be shown in the tool panel
PUT /api/workflows/menu
"""
payload = kwd.get( 'payload' )
user = trans.get_user()
workflow_ids = payload.get( 'workflow_ids' )
if workflow_ids is None:
workflow_ids = []
elif type( workflow_ids ) != list:
workflow_ids = [ workflow_ids ]
sess = trans.sa_session
# This explicit remove seems like a hack, need to figure out
# how to make the association do it automatically.
for m in user.stored_workflow_menu_entries:
sess.delete( m )
user.stored_workflow_menu_entries = []
q = sess.query( model.StoredWorkflow )
# To ensure id list is unique
seen_workflow_ids = set()
for id in workflow_ids:
if id in seen_workflow_ids:
continue
else:
seen_workflow_ids.add( id )
m = model.StoredWorkflowMenuEntry()
m.stored_workflow = q.get( id )
user.stored_workflow_menu_entries.append( m )
sess.flush()
message = "Menu updated."
trans.set_message( message )
return { 'message': message, 'status': 'done' }

def get_workflows_list( self, trans, for_menu, kwd ):
"""
Displays a collection of workflows.
:param show_published: if True, show also published workflows
Expand All @@ -70,22 +122,28 @@ def index(self, trans, **kwd):
for wf in trans.sa_session.query( trans.app.model.StoredWorkflow ).filter(
filter1, trans.app.model.StoredWorkflow.table.c.deleted == false() ).order_by(
desc( trans.app.model.StoredWorkflow.table.c.update_time ) ).all():
item = wf.to_dict( value_mapper={ 'id': trans.security.encode_id } )
encoded_id = trans.security.encode_id(wf.id)
item['url'] = url_for('workflow', id=encoded_id)
if for_menu:
item = wf.to_dict()
else:
item = wf.to_dict( value_mapper={ 'id': trans.security.encode_id } )
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(
trans.app.model.StoredWorkflow.deleted == false() ).order_by(
desc( trans.app.model.StoredWorkflow.update_time ) ).all():
item = wf_sa.stored_workflow.to_dict( value_mapper={ 'id': trans.security.encode_id } )
encoded_id = trans.security.encode_id(wf_sa.stored_workflow.id)
item['url'] = url_for( 'workflow', id=encoded_id )
if for_menu:
item = wf_sa.stored_workflow.to_dict()
else:
item = wf_sa.stored_workflow.to_dict( value_mapper={ 'id': trans.security.encode_id } )
encoded_id = trans.security.encode_id(wf_sa.stored_workflow.id)
item['url'] = url_for( 'workflow', id=encoded_id )
item['slug'] = wf_sa.stored_workflow.slug
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)
if missing_tools:
workflows_missing_tools = []
Expand Down Expand Up @@ -117,9 +175,6 @@ def index(self, trans, **kwd):
for repo_tag in workflows_by_toolshed:
workflows.append( workflows_by_toolshed[ repo_tag ] )
return workflows
# import json
# log.debug(json.dumps(workflows_by_toolshed, indent=2))
# return workflows_by_toolshed
return rval

@expose_api
Expand Down
3 changes: 3 additions & 0 deletions lib/galaxy/webapps/galaxy/buildapp.py
Expand Up @@ -110,6 +110,7 @@ def paste_app_factory( global_conf, **kwargs ):
webapp.add_client_route( '/workflow' )
webapp.add_client_route( '/workflow/run' )
webapp.add_client_route( '/workflow/import_workflow' )
webapp.add_client_route( '/workflow/configure_menu' )
webapp.add_client_route( '/custom_builds' )

# ==== Done
Expand Down Expand Up @@ -291,6 +292,8 @@ def populate_api_routes( webapp, app ):
webapp.mapper.connect( '/api/genomes/{id}/sequences', controller='genomes', action='sequences' )
webapp.mapper.resource( 'visualization', 'visualizations', path_prefix='/api' )
webapp.mapper.connect( '/api/workflows/build_module', action='build_module', controller="workflows" )
webapp.mapper.connect( '/api/workflows/menu', action='get_workflow_menu', controller="workflows", conditions=dict( method=[ "GET" ] ) )
webapp.mapper.connect( '/api/workflows/menu', action='set_workflow_menu', controller="workflows", conditions=dict( method=[ "PUT" ] ) )
webapp.mapper.resource( 'workflow', 'workflows', path_prefix='/api' )
webapp.mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
webapp.mapper.connect( '/api/histories/{history_id}/citations', action='citations', controller="histories" )
Expand Down

0 comments on commit 6dba0c7

Please sign in to comment.