mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Added UI support for annotating histories, HDAs, workflows, and workflow steps. Numerous small changes as well: (a) added an 'edit workflow attributes' to workflow editor; (b) added 'Edit tags and Annotation' area to history panel; (c) added generic javascript method to ajax text updates. Also fixed public URL column bug.
This commit is contained in:
@@ -25,9 +25,13 @@ class OwnerColumn( grids.TextColumn ):
|
||||
# Item's public URL based on username and slug.
|
||||
class PublicURLColumn( grids.TextColumn ):
|
||||
def get_link( self, trans, grid, item ):
|
||||
if item.user.username:
|
||||
if item.user.username and item.slug:
|
||||
return dict( action='display_by_username_and_slug', username=item.user.username, slug=item.slug )
|
||||
else:
|
||||
elif not item.user.username:
|
||||
# TODO: provide link to set username.
|
||||
return None
|
||||
elif not item.user.slug:
|
||||
# TODO: provide link to set slg
|
||||
return None
|
||||
|
||||
class BaseController( object ):
|
||||
@@ -73,6 +77,55 @@ class BaseController( object ):
|
||||
item_class = None
|
||||
return item_class
|
||||
|
||||
def get_item_annotation_str( self, db_session, user, item ):
|
||||
""" Returns a user's annotation string for an item. """
|
||||
annotation_obj = self.get_item_annotation_obj( db_session, user, item )
|
||||
if annotation_obj:
|
||||
return annotation_obj.annotation
|
||||
return None
|
||||
|
||||
def get_item_annotation_obj( self, db_session, user, item ):
|
||||
""" Returns a user's annotation object for an item. """
|
||||
# Get annotation association. TODO: we could replace this eval() with a long if/else stmt, but this is more general without sacrificing
|
||||
try:
|
||||
annotation_assoc_class = eval( "model.%sAnnotationAssociation" % item.__class__.__name__ )
|
||||
except:
|
||||
# Item doesn't have an annotation association class and cannot be annotated.
|
||||
return False
|
||||
|
||||
# Get annotation association object.
|
||||
annotation_assoc = db_session.query( annotation_assoc_class ).filter_by( user=user )
|
||||
if item.__class__ == model.History:
|
||||
annotation_assoc = annotation_assoc.filter_by( history=item )
|
||||
elif item.__class__ == model.HistoryDatasetAssociation:
|
||||
annotation_assoc = annotation_assoc.filter_by( hda=item )
|
||||
elif item.__class__ == model.StoredWorkflow:
|
||||
annotation_assoc = annotation_assoc.filter_by( stored_workflow=item )
|
||||
elif item.__class__ == model.WorkflowStep:
|
||||
annotation_assoc = annotation_assoc.filter_by( workflow_step=item )
|
||||
return annotation_assoc.first()
|
||||
|
||||
def add_item_annotation( self, trans, item, annotation ):
|
||||
""" Add or update an item's annotation; a user can only have a single annotation for an item. """
|
||||
|
||||
# Get/create annotation association object.
|
||||
annotation_assoc = self.get_item_annotation_obj( trans.sa_session, trans.get_user(), item )
|
||||
if not annotation_assoc:
|
||||
# Create association.
|
||||
# TODO: we could replace this eval() with a long if/else stmt, but this is more general without sacrificing
|
||||
try:
|
||||
annotation_assoc_class = eval( "model.%sAnnotationAssociation" % item.__class__.__name__ )
|
||||
except:
|
||||
# Item doesn't have an annotation association class and cannot be annotated.
|
||||
return False
|
||||
annotation_assoc = annotation_assoc_class()
|
||||
item.annotations.append( annotation_assoc )
|
||||
annotation_assoc.user = trans.get_user()
|
||||
|
||||
# Set annotation.
|
||||
annotation_assoc.annotation = annotation
|
||||
return True
|
||||
|
||||
Root = BaseController
|
||||
|
||||
class SharingStatusColumn( grids.GridColumn ):
|
||||
|
||||
@@ -353,7 +353,7 @@ class HistoryController( BaseController, Sharable ):
|
||||
return trans.show_ok_message( "History deleted, a new history is active", refresh_frames=['history'] )
|
||||
@web.expose
|
||||
def rename_async( self, trans, id=None, new_name=None ):
|
||||
history = trans.sa_session.query( model.History ).get( id )
|
||||
history = self.get_history( trans, id )
|
||||
# Check that the history exists, and is either owned by the current
|
||||
# user (if logged in) or the current history
|
||||
assert history is not None
|
||||
@@ -365,6 +365,17 @@ class HistoryController( BaseController, Sharable ):
|
||||
history.name = new_name
|
||||
trans.sa_session.add( history )
|
||||
trans.sa_session.flush()
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy histories" )
|
||||
def annotate_async( self, trans, id, new_annotation=None, **kwargs ):
|
||||
history = self.get_history( trans, id )
|
||||
if new_annotation:
|
||||
self.add_item_annotation( trans, history, new_annotation )
|
||||
trans.sa_session.flush()
|
||||
return
|
||||
else:
|
||||
return "failed"
|
||||
|
||||
@web.expose
|
||||
@web.json
|
||||
|
||||
@@ -78,6 +78,7 @@ class RootController( BaseController ):
|
||||
query = query.filter( model.HistoryDatasetAssociation.deleted == False )
|
||||
return trans.stream_template_mako( "root/history.mako",
|
||||
history = history,
|
||||
annotation = self.get_item_annotation_str( trans.sa_session, trans.get_user(), history ),
|
||||
datasets = query.all(),
|
||||
hda_id = hda_id,
|
||||
show_deleted = show_deleted )
|
||||
@@ -304,6 +305,8 @@ class RootController( BaseController ):
|
||||
else:
|
||||
setattr( data.metadata, name, spec.unwrap( params.get (name, None) ) )
|
||||
data.datatype.after_setting_metadata( data )
|
||||
self.add_item_annotation( trans, data, params.annotation )
|
||||
|
||||
else:
|
||||
msg = ' (Metadata could not be changed because this dataset is currently being used as input or output. You must cancel or wait for these jobs to complete before changing metadata.)'
|
||||
trans.sa_session.flush()
|
||||
@@ -383,6 +386,7 @@ class RootController( BaseController ):
|
||||
messagetype = 'done'
|
||||
return trans.fill_template( "/dataset/edit_attributes.mako",
|
||||
data=data,
|
||||
data_annotation=self.get_item_annotation_str( trans.sa_session, trans.get_user(), data ),
|
||||
datatypes=ldatatypes,
|
||||
current_user_roles=current_user_roles,
|
||||
all_roles=all_roles,
|
||||
|
||||
@@ -303,6 +303,28 @@ class WorkflowController( BaseController, Sharable ):
|
||||
session.flush()
|
||||
# Redirect to load galaxy frames.
|
||||
return trans.response.send_redirect( url_for( controller='workflow' ) )
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
def edit_attributes( self, trans, id, **kwargs ):
|
||||
# Get workflow and do error checking.
|
||||
stored = get_stored_workflow( trans, id )
|
||||
if not stored:
|
||||
error( "You do not own this workflow or workflow ID is invalid." )
|
||||
|
||||
# Update workflow attributes if new values submitted.
|
||||
if 'name' in kwargs:
|
||||
# Rename workflow.
|
||||
stored.name = kwargs[ 'name' ]
|
||||
if 'annotation' in kwargs:
|
||||
# Set workflow annotation.
|
||||
self.add_item_annotation( trans, stored, kwargs[ 'annotation' ] )
|
||||
trans.sa_session.flush()
|
||||
|
||||
return trans.fill_template( 'workflow/edit_attributes.mako',
|
||||
stored=stored,
|
||||
annotation=self.get_item_annotation_str( trans.sa_session, trans.get_user(), stored )
|
||||
)
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
@@ -320,7 +342,29 @@ class WorkflowController( BaseController, Sharable ):
|
||||
else:
|
||||
return form( url_for( action='rename', id=trans.security.encode_id(stored.id) ), "Rename workflow", submit_text="Rename" ) \
|
||||
.add_text( "new_name", "Workflow Name", value=stored.name )
|
||||
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
def rename_async( self, trans, id, new_name=None, **kwargs ):
|
||||
stored = get_stored_workflow( trans, id )
|
||||
if new_name:
|
||||
stored.name = new_name
|
||||
trans.sa_session.flush()
|
||||
return
|
||||
else:
|
||||
return "failed"
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
def annotate_async( self, trans, id, new_annotation=None, **kwargs ):
|
||||
stored = get_stored_workflow( trans, id )
|
||||
if new_annotation:
|
||||
self.add_item_annotation( trans, stored, new_annotation )
|
||||
trans.sa_session.flush()
|
||||
return
|
||||
else:
|
||||
return "failed"
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "use Galaxy workflows" )
|
||||
def clone( self, trans, id ):
|
||||
@@ -400,11 +444,11 @@ class WorkflowController( BaseController, Sharable ):
|
||||
"""
|
||||
if not id:
|
||||
error( "Invalid workflow id" )
|
||||
id = trans.security.decode_id( id )
|
||||
return trans.fill_template( "workflow/editor.mako", workflow_id=id )
|
||||
stored = get_stored_workflow( trans, id )
|
||||
return trans.fill_template( "workflow/editor.mako", stored=stored, annotation=self.get_item_annotation_str( trans.sa_session, trans.get_user(), stored ) )
|
||||
|
||||
@web.json
|
||||
def editor_form_post( self, trans, type='tool', tool_id=None, **incoming ):
|
||||
def editor_form_post( self, trans, type='tool', tool_id=None, annotation=None, **incoming ):
|
||||
"""
|
||||
Accepts a tool state and incoming values, and generates a new tool
|
||||
form and some additional information, packed into a json dictionary.
|
||||
@@ -423,7 +467,8 @@ class WorkflowController( BaseController, Sharable ):
|
||||
'data_inputs': module.get_data_inputs(),
|
||||
'data_outputs': module.get_data_outputs(),
|
||||
'tool_errors': module.get_errors(),
|
||||
'form_html': module.get_config_form()
|
||||
'form_html': module.get_config_form(),
|
||||
'annotation': annotation
|
||||
}
|
||||
|
||||
@web.json
|
||||
@@ -445,7 +490,8 @@ class WorkflowController( BaseController, Sharable ):
|
||||
'tooltip': module.get_tooltip(),
|
||||
'data_inputs': module.get_data_inputs(),
|
||||
'data_outputs': module.get_data_outputs(),
|
||||
'form_html': module.get_config_form()
|
||||
'form_html': module.get_config_form(),
|
||||
'annotation': ""
|
||||
}
|
||||
|
||||
@web.json
|
||||
@@ -477,6 +523,11 @@ class WorkflowController( BaseController, Sharable ):
|
||||
# FIXME: Frontend should be able to handle workflow messages
|
||||
# as a dictionary not just the values
|
||||
data['upgrade_messages'][step.order_index] = upgrade_message.values()
|
||||
# Get user annotation.
|
||||
step_annotation = self.get_item_annotation_obj ( trans.sa_session, trans.get_user(), step )
|
||||
annotation_str = ""
|
||||
if step_annotation:
|
||||
annotation_str = step_annotation.annotation
|
||||
# Pack attributes into plain dictionary
|
||||
step_dict = {
|
||||
'id': step.order_index,
|
||||
@@ -489,6 +540,7 @@ class WorkflowController( BaseController, Sharable ):
|
||||
'data_inputs': module.get_data_inputs(),
|
||||
'data_outputs': module.get_data_outputs(),
|
||||
'form_html': module.get_config_form(),
|
||||
'annotation' : annotation_str
|
||||
}
|
||||
# Connections
|
||||
input_connections = step.input_connections
|
||||
@@ -551,6 +603,9 @@ class WorkflowController( BaseController, Sharable ):
|
||||
workflow.has_errors = True
|
||||
# Stick this in the step temporarily
|
||||
step.temp_input_connections = step_dict['input_connections']
|
||||
|
||||
# Save step annotation.
|
||||
self.add_item_annotation( trans, step, step_dict[ 'annotation' ] )
|
||||
# Second pass to deal with connections between steps
|
||||
for step in steps:
|
||||
# Input connections
|
||||
|
||||
@@ -656,3 +656,45 @@ div.permissionContainer {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
## Icon buttons.
|
||||
|
||||
.icon-button {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-left: 2px;
|
||||
## Allow alt text for screen readers
|
||||
text-indent: 20px;
|
||||
}
|
||||
|
||||
.icon-button.display {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: eye_icon.png;
|
||||
}
|
||||
|
||||
.icon-button.display:hover {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: eye_icon_dark.png;
|
||||
}
|
||||
|
||||
.icon-button.delete {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: delete_icon.png;
|
||||
}
|
||||
|
||||
.icon-button.delete:hover {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: delete_icon_dark.png;
|
||||
}
|
||||
|
||||
.icon-button.edit {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: pencil_icon.png;
|
||||
}
|
||||
|
||||
.icon-button.edit:hover {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: pencil_icon_dark.png;
|
||||
}
|
||||
@@ -110,3 +110,10 @@ div.permissionContainer{padding-left:20px;}
|
||||
.text-content fieldset{border-color:#ccc;border:1px solid #ccc;}
|
||||
.text-content th,.text-content td{border-bottom:1px solid #ddd;border-right:1px solid #ccc;}
|
||||
.text-content th,.text-content td{padding:.8em;}
|
||||
.icon-button{width:16px;height:16px;display:block;float:left;margin-left:2px;text-indent:20px;}
|
||||
.icon-button.edit{background:url(history-buttons.png) no-repeat 0px -52px;}
|
||||
.icon-button.edit:hover{background:url(history-buttons.png) no-repeat 0px -78px;}
|
||||
.icon-button.display{background:url(history-buttons.png) no-repeat 0px -0px;}
|
||||
.icon-button.display:hover{background:url(history-buttons.png) no-repeat 0px -26px;}
|
||||
.icon-button.delete{background:url(history-buttons.png) no-repeat 0px -104px;}
|
||||
.icon-button.delete:hover{background:url(history-buttons.png) no-repeat 0px -130px;}
|
||||
@@ -22,13 +22,6 @@ div.historyItem-queued .state-icon{background:url(history-states.png) no-repeat
|
||||
div.historyItem-noPermission{filter:alpha(opacity=60);-moz-opacity:.60;opacity:.60;}
|
||||
div.historyItemTitleBar.spinner .state-icon{background:url(data_running.gif) 0 1px no-repeat !important;}
|
||||
div.historyItemButtons{float:right;}
|
||||
.icon-button{width:16px;height:16px;display:block;float:left;margin-left:2px;text-indent:20px;}
|
||||
.icon-button.display{background:url(history-buttons.png) no-repeat 0px -0px;}
|
||||
.icon-button.display:hover{background:url(history-buttons.png) no-repeat 0px -26px;}
|
||||
.icon-button.edit{background:url(history-buttons.png) no-repeat 0px -52px;}
|
||||
.icon-button.edit:hover{background:url(history-buttons.png) no-repeat 0px -78px;}
|
||||
.icon-button.delete{background:url(history-buttons.png) no-repeat 0px -104px;}
|
||||
.icon-button.delete:hover{background:url(history-buttons.png) no-repeat 0px -130px;}
|
||||
div.historyItemBody div{padding-top:2px;}
|
||||
pre.peek{background:white;color:black;width:100%;overflow:auto;}
|
||||
pre.peek th{color:white;background:#023858;}
|
||||
|
||||
@@ -120,46 +120,6 @@ div.historyItemButtons {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-left: 2px;
|
||||
## Allow alt text for screen readers
|
||||
text-indent: 20px;
|
||||
}
|
||||
|
||||
.icon-button.display {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: eye_icon.png;
|
||||
}
|
||||
|
||||
.icon-button.display:hover {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: eye_icon_dark.png;
|
||||
}
|
||||
|
||||
.icon-button.edit {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: pencil_icon.png;
|
||||
}
|
||||
|
||||
.icon-button.edit:hover {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: pencil_icon_dark.png;
|
||||
}
|
||||
|
||||
.icon-button.delete {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: delete_icon.png;
|
||||
}
|
||||
|
||||
.icon-button.delete:hover {
|
||||
-sprite-group: history-buttons;
|
||||
-sprite-image: delete_icon_dark.png;
|
||||
}
|
||||
|
||||
div.historyItemBody div {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
@@ -207,3 +207,47 @@ var replace_dbkey_select = function()
|
||||
});
|
||||
}
|
||||
} // end replace_dbkey_select()
|
||||
|
||||
//
|
||||
// Edit and save text asynchronously.
|
||||
//
|
||||
function async_save_text(click_to_edit_elt, text_elt_id, save_url, text_parm_name, use_textarea, num_rows)
|
||||
{
|
||||
$("#" + click_to_edit_elt).click( function() {
|
||||
var old_text = $("#" + text_elt_id).text()
|
||||
if (use_textarea)
|
||||
var t = $("<textarea rows='" + num_rows + "'>" + old_text + "</textarea>" );
|
||||
else
|
||||
var t = $("<input type='text' value='" + old_text + "'></input>" );
|
||||
t.blur( function() {
|
||||
$(this).remove();
|
||||
$("#" + text_elt_id).show();
|
||||
});
|
||||
t.keyup( function( e ) {
|
||||
if ( e.keyCode == 27 ) {
|
||||
// Escape key
|
||||
$(this).trigger( "blur" );
|
||||
} else if ( e.keyCode == 13 ) {
|
||||
// Enter key
|
||||
new_text = this.value;
|
||||
$(this).trigger( "blur" );
|
||||
var ajax_data = new Object();
|
||||
ajax_data[text_parm_name] = new_text;
|
||||
$.ajax({
|
||||
url: save_url,
|
||||
data: ajax_data,
|
||||
error: function() { alert( "Text editing for elt " + text_elt_id + " failed" ) },
|
||||
success: function() {
|
||||
$("#" + text_elt_id).text( new_text );
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$("#" + text_elt_id).hide();
|
||||
t.insertAfter( $("#" + text_elt_id) );
|
||||
t.focus();
|
||||
t.select();
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -272,6 +272,7 @@ $.extend( Node.prototype, {
|
||||
this.tool_state = data.tool_state;
|
||||
this.tool_errors = data.tool_errors;
|
||||
this.tooltip = data.tooltip ? data.tooltip : ""
|
||||
this.annotation = data.annotation;
|
||||
|
||||
if ( this.tool_errors ) {
|
||||
f.addClass( "tool-node-error" );
|
||||
@@ -306,6 +307,7 @@ $.extend( Node.prototype, {
|
||||
node = this;
|
||||
this.tool_state = data.tool_state;
|
||||
this.form_html = data.form_html;
|
||||
this.annotation = data.annotation;
|
||||
this.tool_errors = data.tool_errors;
|
||||
if ( this.tool_errors ) {
|
||||
el.addClass( "tool-node-error" );
|
||||
@@ -405,7 +407,8 @@ $.extend( Workflow.prototype, {
|
||||
tool_state : node.tool_state,
|
||||
tool_errors : node.tool_errors,
|
||||
input_connections : input_connections,
|
||||
position : $(node.element).position()
|
||||
position : $(node.element).position(),
|
||||
annotation: node.annotation
|
||||
};
|
||||
nodes[ node.id ] = node_data;
|
||||
});
|
||||
|
||||
@@ -1 +1 @@
|
||||
$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});make_popup_menus()});function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ensure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></ul>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}var array_length=function(a){if(a.length){return a.length}var b=0;for(element in a){b++}return b};var replace_dbkey_select=function(){var c=$("select[name=dbkey]");var d=c.attr("value");if(c.length!=0){var e=$("<input id='dbkey-input' type='text'></input>");e.attr("size",40);e.attr("name",c.attr("name"));e.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var b=new Array();var a=new Object();c.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}b.push(h);a[h]=g;if(g==d){e.attr("value",h)}});if(e.attr("value")==""){e.attr("value","Click to Search or Select Build")}var f={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};e.autocomplete(b,f);c.replaceWith(e);$("form").submit(function(){var i=$("#dbkey-input");if(i.length!=0){var h=i.attr("value");var g=a[h];if(g!=null&&g!=undefined){i.attr("value",g)}else{if(d!=""){i.attr("value",d)}else{i.attr("value","?")}}}})}};
|
||||
$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};jQuery(document).ready(function(){jQuery("a[confirm]").click(function(){return confirm(jQuery(this).attr("confirm"))});make_popup_menus()});function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ensure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></ul>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}var array_length=function(a){if(a.length){return a.length}var b=0;for(element in a){b++}return b};var replace_dbkey_select=function(){var c=$("select[name=dbkey]");var d=c.attr("value");if(c.length!=0){var e=$("<input id='dbkey-input' type='text'></input>");e.attr("size",40);e.attr("name",c.attr("name"));e.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var b=new Array();var a=new Object();c.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}b.push(h);a[h]=g;if(g==d){e.attr("value",h)}});if(e.attr("value")==""){e.attr("value","Click to Search or Select Build")}var f={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};e.autocomplete(b,f);c.replaceWith(e);$("form").submit(function(){var i=$("#dbkey-input");if(i.length!=0){var h=i.attr("value");var g=a[h];if(g!=null&&g!=undefined){i.attr("value",g)}else{if(d!=""){i.attr("value",d)}else{i.attr("value","?")}}}})}};function async_save_text(d,c,a,e,f,b){$("#"+d).click(function(){var h=$("#"+c).text();if(f){var g=$("<textarea rows='"+b+"'>"+h+"</textarea>")}else{var g=$("<input type='text' value='"+h+"'></input>")}g.blur(function(){$(this).remove();$("#"+c).show()});g.keyup(function(j){if(j.keyCode==27){$(this).trigger("blur")}else{if(j.keyCode==13){new_text=this.value;$(this).trigger("blur");var i=new Object();i[e]=new_text;$.ajax({url:a,data:i,error:function(){alert("Text editing for elt "+c+" failed")},success:function(){$("#"+c).text(new_text)}})}}});$("#"+c).hide();g.insertAfter($("#"+c));g.focus();g.select();return false})};
|
||||
File diff suppressed because one or more lines are too long
@@ -58,21 +58,32 @@
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
%if trans.get_user() is not None:
|
||||
<%namespace file="../tagging_common.mako" import="render_individual_tagging_element" />
|
||||
<div class="form-row">
|
||||
<label>
|
||||
Tags:
|
||||
</label>
|
||||
<div style="float: left; width: 295px; margin-right: 10px; border-style: inset; border-width: 1px">
|
||||
<style>
|
||||
.tag-area {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
${render_individual_tagging_element(user=trans.get_user(), tagged_item=data, elt_context="edit_attributes.mako", use_toggle_link=False, in_form=True, input_size="30")}
|
||||
<%namespace file="../tagging_common.mako" import="render_individual_tagging_element" />
|
||||
<div class="form-row">
|
||||
<label>
|
||||
Tags:
|
||||
</label>
|
||||
<div style="float: left; width: 295px; margin-right: 10px; border-style: inset; border-width: 1px; margin-left: 2px">
|
||||
<style>
|
||||
.tag-area {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
${render_individual_tagging_element(user=trans.get_user(), tagged_item=data, elt_context="edit_attributes.mako", use_toggle_link=False, in_form=True, input_size="30")}
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="toolParamHelp">Apply tags to make it easy to search for and find items with the same tag.</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>
|
||||
Annotation / Notes:
|
||||
</label>
|
||||
<div style="float: left; width: 250px; margin-right: 10px;">
|
||||
<textarea name="annotation" cols="40" rows="2">${data_annotation}</textarea>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="toolParamHelp">Add an annotation or notes to a dataset; annotations are available when a history is viewed.</div>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
%endif
|
||||
%for name, spec in data.metadata.spec.items():
|
||||
%if spec.visible:
|
||||
|
||||
@@ -844,7 +844,7 @@
|
||||
## Item selection column
|
||||
%if show_item_checkboxes:
|
||||
<td style="width: 1.5em;">
|
||||
<input type="checkbox" id="${encoded_id}" name="id" value="${encoded_id}" class="grid-row-select-checkbox" />
|
||||
<input type="checkbox" name="id" value="${encoded_id}" id="${encoded_id}" class="grid-row-select-checkbox" />
|
||||
</td>
|
||||
%endif
|
||||
## Data columns
|
||||
|
||||
+43
-37
@@ -15,7 +15,7 @@
|
||||
<meta http-equiv="Pragma" content="no-cache">
|
||||
|
||||
${h.css( "base", "history", "autocomplete_tagging" )}
|
||||
${h.js( "jquery", "json2", "jquery.jstore-all", "jquery.autocomplete", "autocomplete_tagging" )}
|
||||
${h.js( "galaxy.base", "jquery", "json2", "jquery.jstore-all", "jquery.autocomplete", "autocomplete_tagging" )}
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
@@ -42,36 +42,20 @@ $(function() {
|
||||
$.jStore.remove("history_expand_state");
|
||||
}));
|
||||
|
||||
$("#history-rename").click( function() {
|
||||
var old_name = $("#history-name").text()
|
||||
var t = $("<input type='text' value='" + old_name + "'></input>" );
|
||||
t.blur( function() {
|
||||
$(this).remove();
|
||||
$("#history-name").show();
|
||||
});
|
||||
t.keyup( function( e ) {
|
||||
if ( e.keyCode == 27 ) {
|
||||
// Escape key
|
||||
$(this).trigger( "blur" );
|
||||
} else if ( e.keyCode == 13 ) {
|
||||
// Enter key
|
||||
new_value = this.value;
|
||||
$(this).trigger( "blur" );
|
||||
$.ajax({
|
||||
url: "${h.url_for( controller='history', action='rename_async', id=history.id )}",
|
||||
data: { "_": true, new_name: new_value },
|
||||
error: function() { alert( "Rename failed" ) },
|
||||
success: function() {
|
||||
$("#history-name").text( new_value );
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$("#history-name").hide();
|
||||
$("#history-name-area").append( t );
|
||||
t.focus();
|
||||
return false;
|
||||
});
|
||||
// Rename async.
|
||||
async_save_text("history-rename", "history-name", "${h.url_for( controller="/history", action="rename_async", id=trans.security.encode_id(history.id) )}", "new_name");
|
||||
|
||||
// Annotation async.
|
||||
// Tag async. Simply have the workflow tag element generate a click on the tag element to activate tagging.
|
||||
$('#workflow-tag').click( function()
|
||||
{
|
||||
$('.tag-area').click();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Annotate async.
|
||||
async_save_text("history-annotate", "history-annotation", "${h.url_for( controller="/history", action="annotate_async", id=trans.security.encode_id(history.id) )}", "new_annotation", true, 4);
|
||||
|
||||
// Updater
|
||||
updater({
|
||||
<% updateable = [data for data in reversed( datasets ) if data.visible and data.state not in [ "deleted", "empty", "error", "ok" ]] %>
|
||||
@@ -266,6 +250,9 @@ var updater_callback = function ( tracked_datasets ) {
|
||||
.historyItemBody {
|
||||
display: none;
|
||||
}
|
||||
div.form-row {
|
||||
padding: 5px 5px 5px 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<noscript>
|
||||
@@ -303,12 +290,31 @@ var updater_callback = function ( tracked_datasets ) {
|
||||
<%namespace file="history_common.mako" import="render_dataset" />
|
||||
|
||||
%if trans.get_user() is not None:
|
||||
<style>
|
||||
.tag-element {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
</style>
|
||||
${render_individual_tagging_element( user=trans.get_user(), tagged_item=history, elt_context='history.mako' )}
|
||||
<div style="margin: 0px 0px 5px 10px">
|
||||
<a href="#" onclick="$('#tags-and-annotation').toggle('fast')">Edit Tags and Annotation/Notes</a>
|
||||
<div id="tags-and-annotation" style="display: none">
|
||||
## Tagging elt.
|
||||
<div class="form-row">
|
||||
<label>Tags:</label>
|
||||
<div style="float: right"><a id="workflow-tag" title="Tag" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div>
|
||||
<style>
|
||||
.tag-area {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
${render_individual_tagging_element(user=trans.get_user(), tagged_item=history, elt_context="history.mako", use_toggle_link=False, input_size="20", render_add_tag_button=False)}
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
|
||||
## Annotation elt.
|
||||
<div id="history-annotation-area" class="form-row">
|
||||
<label>Annotation / Notes:</label>
|
||||
<div style="float: right"><a id="history-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='history', action='annotate_async' )}"></a></div>
|
||||
<div id="history-annotation">${annotation}</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
|
||||
%if not datasets:
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<div class="indent" style="margin-top: 2em">
|
||||
<h3>Making ${item_class_name} Accessible via Link and Publishing It</h3>
|
||||
|
||||
<div class="indent">
|
||||
<div>
|
||||
%if item.importable:
|
||||
<%
|
||||
item_status = "accessible via link"
|
||||
@@ -75,7 +75,7 @@
|
||||
item_status = item_status + " and published"
|
||||
%>
|
||||
This ${item_class_name_lc} <strong>${item_status}</strong>.
|
||||
<div class="indent">
|
||||
<div>
|
||||
<p>Anyone can view and import this ${item_class_name_lc} by visiting the following URL:
|
||||
<% url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True ) %>
|
||||
<blockquote>
|
||||
@@ -88,7 +88,7 @@
|
||||
</div>
|
||||
|
||||
<p>You can:
|
||||
<div class="indent">
|
||||
<div>
|
||||
<form action="${h.url_for( action='sharing', id=trans.security.encode_id( item.id ) )}"
|
||||
method="POST">
|
||||
%if not item.published:
|
||||
@@ -130,7 +130,7 @@
|
||||
|
||||
<h3>Sharing ${item_class_name} with Specific Users</h3>
|
||||
|
||||
<div class="indent">
|
||||
<div>
|
||||
%if item.users_shared_with:
|
||||
|
||||
<p>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
%endif
|
||||
|
||||
## Render HTML for a list of tags.
|
||||
<%def name="render_tagging_element_html(elt_id=None, tags=None, editable=True, use_toggle_link=True, input_size='15', in_form=False, tag_type='individual')">
|
||||
<%def name="render_tagging_element_html(elt_id=None, tags=None, editable=True, use_toggle_link=True, input_size='15', in_form=False, tag_type='individual', render_add_tag_button=True)">
|
||||
## Useful attributes.
|
||||
<%
|
||||
num_tags = len( tags )
|
||||
@@ -79,7 +79,9 @@
|
||||
<input class="tag-input" type='text' size='${input_size}'/>
|
||||
%endif
|
||||
## Add "add tag" button.
|
||||
<img src='${h.url_for('/static/images/add_icon.png')}' rollover='${h.url_for('/static/images/add_icon_dark.png')}' class="add-tag-button"/>
|
||||
%if render_add_tag_button:
|
||||
<img src='${h.url_for('/static/images/add_icon.png')}' rollover='${h.url_for('/static/images/add_icon_dark.png')}' class="add-tag-button"/>
|
||||
%endif
|
||||
%endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,7 +104,7 @@
|
||||
|
||||
|
||||
## Render individual tagging element.
|
||||
<%def name="render_individual_tagging_element(user=None, tagged_item=None, elt_context=None, use_toggle_link=True, in_form=False, input_size='15', tag_click_fn='default_tag_click_fn', get_toggle_link_text_fn='default_get_toggle_link_text_fn', editable=True)">
|
||||
<%def name="render_individual_tagging_element(user=None, tagged_item=None, elt_context=None, use_toggle_link=True, in_form=False, input_size='15', tag_click_fn='default_tag_click_fn', get_toggle_link_text_fn='default_get_toggle_link_text_fn', editable=True, render_add_tag_button=True)">
|
||||
## Useful attributes.
|
||||
<%
|
||||
# Useful ids.
|
||||
@@ -114,7 +116,7 @@
|
||||
%>
|
||||
|
||||
## Build HTML.
|
||||
${self.render_tagging_element_html(elt_id, item_tags, editable, use_toggle_link, input_size, in_form)}
|
||||
${self.render_tagging_element_html(elt_id=elt_id, tags=item_tags, editable=editable, use_toggle_link=use_toggle_link, input_size=input_size, in_form=in_form, render_add_tag_button=render_add_tag_button)}
|
||||
|
||||
## Build script that augments tags using progressive javascript.
|
||||
<script type="text/javascript">
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<%inherit file="/base.mako"/>
|
||||
<%namespace file="/message.mako" import="render_msg" />
|
||||
|
||||
<%def name="title()">${_('Edit Workflow Attributes')}</%def>
|
||||
|
||||
<%def name="stylesheets()">
|
||||
${h.css( "base", "autocomplete_tagging" )}
|
||||
</%def>
|
||||
|
||||
<%def name="javascripts()">
|
||||
${parent.javascripts()}
|
||||
${h.js( "galaxy.base", "jquery.autocomplete", "autocomplete_tagging" )}
|
||||
</%def>
|
||||
|
||||
%if msg:
|
||||
${render_msg( msg, messagetype )}
|
||||
%endif
|
||||
|
||||
<%def name="body()">
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">${_('Edit Workflow Attributes')}</div>
|
||||
<div class="toolFormBody">
|
||||
<form name="edit_attributes" action="${h.url_for( action='edit_attributes' )}" method="post">
|
||||
<input type="hidden" name="id" value="${trans.security.encode_id( stored.id )}"/>
|
||||
<div class="form-row">
|
||||
<label>
|
||||
Name:
|
||||
</label>
|
||||
<div style="float: left; width: 225px; margin-right: 10px;">
|
||||
<input type="text" name="name" value="${stored.name}" size="30"/>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
<%namespace file="/tagging_common.mako" import="render_individual_tagging_element" />
|
||||
<div class="form-row">
|
||||
<label>
|
||||
Tags:
|
||||
</label>
|
||||
<div style="float: left; width: 265px; margin-right: 10px; border-style: inset; border-width: 1px; margin-left: 2px">
|
||||
<style>
|
||||
.tag-area {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
${render_individual_tagging_element(user=trans.get_user(), tagged_item=stored, elt_context="edit_attributes.mako", use_toggle_link=False, in_form=True, input_size="25")}
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="toolParamHelp">Apply tags to make it easy to search for and find items with the same tag.</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>
|
||||
Annotation / Notes:
|
||||
</label>
|
||||
<div style="float: left; width: 225px; margin-right: 10px;">
|
||||
<textarea name="annotation" cols="30" rows="2">${annotation}</textarea>
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="toolParamHelp">Add an annotation notes to a workflow; annotations are available when a workflow is viewed.</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<input type="submit" name="save" value="${_('Save')}"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</%def>
|
||||
@@ -34,7 +34,9 @@
|
||||
"jquery.jstore-all",
|
||||
"json2",
|
||||
"galaxy.base",
|
||||
"galaxy.workflow_editor.canvas" )}
|
||||
"galaxy.workflow_editor.canvas",
|
||||
"jquery.autocomplete",
|
||||
"autocomplete_tagging")}
|
||||
|
||||
<!--[if lt IE 7]>
|
||||
<script type='text/javascript'>
|
||||
@@ -77,7 +79,7 @@
|
||||
// Load workflow definition
|
||||
$.ajax( {
|
||||
url: "${h.url_for( action='load_workflow' )}",
|
||||
data: { id: "${trans.security.encode_id( workflow_id )}", "_": "true" },
|
||||
data: { id: "${trans.security.encode_id( stored.id )}", "_": "true" },
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
success: function( data ) {
|
||||
@@ -142,6 +144,12 @@
|
||||
canvas_manager.draw_overview();
|
||||
});
|
||||
|
||||
$('#edit-attributes-button').click( function() {
|
||||
workflow.clear_active_node();
|
||||
$('#edit-attributes').show();
|
||||
$('#right-content').hide();
|
||||
});
|
||||
|
||||
$.jStore.ready(function(engine) {
|
||||
engine.ready(function() {
|
||||
// On load, set the size to the pref stored in local storage if it exists
|
||||
@@ -209,6 +217,19 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Rename async.
|
||||
async_save_text("workflow-rename", "workflow-name", "${h.url_for( action="rename_async", id=trans.security.encode_id(stored.id) )}", "new_name");
|
||||
|
||||
// Tag async. Simply have the workflow tag element generate a click on the tag element to activate tagging.
|
||||
$('#workflow-tag').click( function()
|
||||
{
|
||||
$('.tag-area').click();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Annotate async.
|
||||
async_save_text("workflow-annotate", "workflow-annotation", "${h.url_for( action="annotate_async", id=trans.security.encode_id(stored.id) )}", "new_annotation", true, 4);
|
||||
});
|
||||
|
||||
// Global state for the whole workflow
|
||||
@@ -285,7 +306,8 @@
|
||||
};
|
||||
|
||||
function show_form_for_tool( text, node ) {
|
||||
$("#right-content").html( text );
|
||||
$("#edit-attributes").hide();
|
||||
$("#right-content").show().html( text );
|
||||
$("#right-content").find( "form" ).ajaxForm( {
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
@@ -316,6 +338,17 @@
|
||||
$(this).remove();
|
||||
make_popupmenu( b, options );
|
||||
});
|
||||
// Add annotation field to form.
|
||||
// TODO: need to set the annotation for this tool.
|
||||
var annotation_div =
|
||||
$( "<div class='form-row'> \
|
||||
<label>Annotation / Notes:</label> \
|
||||
<div style='margin-right: 10px;'> \
|
||||
<textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \
|
||||
<div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \
|
||||
</div> \
|
||||
</div>");
|
||||
$(this).append( annotation_div );
|
||||
// Implements auto-saving based on whether the inputs change. We consider
|
||||
// "changed" to be when a field is accessed and not necessarily modified
|
||||
// because of an issue where "onchange" is not triggered when activating
|
||||
@@ -366,7 +399,7 @@
|
||||
url: "${h.url_for( action='save_workflow' )}",
|
||||
type: "POST",
|
||||
data: {
|
||||
id: "${trans.security.encode_id( workflow_id )}",
|
||||
id: "${trans.security.encode_id( stored.id )}",
|
||||
workflow_data: function() { return JSON.stringify( workflow.to_simple() ) },
|
||||
"_": "true"
|
||||
},
|
||||
@@ -421,10 +454,10 @@
|
||||
<%def name="stylesheets()">
|
||||
|
||||
## Include "base.css" for styling tool menu and forms (details)
|
||||
<link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" />
|
||||
${h.css( "base", "autocomplete_tagging")}
|
||||
|
||||
## But make sure styles for the layout take precedence
|
||||
${parent.stylesheets()}
|
||||
${parent.stylesheets()}
|
||||
|
||||
<style type="text/css">
|
||||
body { margin: 0; padding: 0; overflow: hidden; }
|
||||
@@ -508,9 +541,8 @@
|
||||
div.toolFormRow {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
#right-content {
|
||||
|
||||
.right-content {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
@@ -575,7 +607,6 @@
|
||||
}
|
||||
|
||||
.form-row {
|
||||
|
||||
}
|
||||
div.toolFormInCanvas div.toolFormBody {
|
||||
padding: 0;
|
||||
@@ -740,9 +771,52 @@
|
||||
<div class="unified-panel-header" unselectable="on">
|
||||
<div class="unified-panel-header-inner">
|
||||
Details
|
||||
<div style="float: right">
|
||||
<a id="edit-attributes-button" class="panel-header-button">Edit Workflow Attributes</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="unified-panel-body" style="overflow: auto;">
|
||||
<div id="right-content"></div>
|
||||
## Div for elements to modify workflow attributes.
|
||||
<div id="edit-attributes" class="toolForm right-content">
|
||||
<div class="toolFormTitle">Edit Workflow Attributes</div>
|
||||
<div class="toolFormBody">
|
||||
## Workflow name.
|
||||
<div id="workflow-name-area" class="form-row">
|
||||
<label>Name:</label>
|
||||
<div style="float: right"><a id="workflow-rename" title="Rename" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='rename_sync' )}"></a></div>
|
||||
<div id="workflow-name">${stored.name}</div>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
## Workflow tags.
|
||||
<%namespace file="/tagging_common.mako" import="render_individual_tagging_element" />
|
||||
<div class="form-row">
|
||||
<label>
|
||||
Tags:
|
||||
</label>
|
||||
<div style="float: right"><a id="workflow-tag" title="Tag" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div>
|
||||
<div style="float: left; width: 225px; margin-right: 10px; border-style: inset; border-width: 1px; margin-left: 2px">
|
||||
<style>
|
||||
.tag-area {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
${render_individual_tagging_element(user=trans.get_user(), tagged_item=stored, elt_context="edit_attributes.mako", use_toggle_link=False, input_size="20", render_add_tag_button=False)}
|
||||
</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="toolParamHelp">Apply tags to make it easy to search for and find items with the same tag.</div>
|
||||
</div>
|
||||
## Workflow annotation.
|
||||
<div id="workflow-annotation-area" class="form-row">
|
||||
<label>Annotation / Notes:</label>
|
||||
<div style="float: right"><a id="workflow-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div>
|
||||
<div id="workflow-annotation">${annotation}</div>
|
||||
<div style="clear: both"></div>
|
||||
<div class="toolParamHelp">Add an annotation or notes to a workflow; annotations are available when a workflow is viewed.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
## Div where tool details are loaded and modified.
|
||||
<div id="right-content" class="right-content"></div>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
Reference in New Issue
Block a user