1 | <%inherit file="/webapps/galaxy/base_panels.mako"/> |
---|
2 | |
---|
3 | <%def name="init()"> |
---|
4 | <% |
---|
5 | self.active_view="workflow" |
---|
6 | self.overlay_visible=True |
---|
7 | %> |
---|
8 | </%def> |
---|
9 | |
---|
10 | <%def name="late_javascripts()"> |
---|
11 | <script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.panels.js')}"> </script> |
---|
12 | <script type="text/javascript"> |
---|
13 | ensure_dd_helper(); |
---|
14 | make_left_panel( $("#left"), $("#center"), $("#left-border" ) ); |
---|
15 | make_right_panel( $("#right"), $("#center"), $("#right-border" ) ); |
---|
16 | ensure_popup_helper(); |
---|
17 | ## handle_minwidth_hint = rp.handle_minwidth_hint; |
---|
18 | </script> |
---|
19 | </%def> |
---|
20 | |
---|
21 | <%def name="javascripts()"> |
---|
22 | |
---|
23 | ${parent.javascripts()} |
---|
24 | |
---|
25 | <!--[if IE]> |
---|
26 | <script type='text/javascript' src="${h.url_for('/static/scripts/excanvas.js')}"> </script> |
---|
27 | <![endif]--> |
---|
28 | |
---|
29 | ${h.js( "jquery", |
---|
30 | "jquery.tipsy", |
---|
31 | "jquery.event.drag", |
---|
32 | "jquery.event.drop", |
---|
33 | "jquery.event.hover", |
---|
34 | "jquery.form", |
---|
35 | "class", |
---|
36 | "json2", |
---|
37 | "jquery.jstore", |
---|
38 | "galaxy.base", |
---|
39 | "galaxy.workflow_editor.canvas", |
---|
40 | "jquery.autocomplete", |
---|
41 | "autocomplete_tagging")} |
---|
42 | |
---|
43 | <!--[if lt IE 7]> |
---|
44 | <script type='text/javascript'> |
---|
45 | window.lt_ie_7 = true; |
---|
46 | </script> |
---|
47 | <![endif]--> |
---|
48 | |
---|
49 | <script type='text/javascript'> |
---|
50 | // Globals |
---|
51 | workflow = null; |
---|
52 | canvas_manager = null; |
---|
53 | active_ajax_call = false; |
---|
54 | var galaxy_async = new GalaxyAsync(); |
---|
55 | galaxy_async.set_func_url(galaxy_async.set_user_pref, "${h.url_for( controller='user', action='set_user_pref_async' )}"); |
---|
56 | |
---|
57 | // jQuery onReady |
---|
58 | $( function() { |
---|
59 | |
---|
60 | if ( window.lt_ie_7 ) { |
---|
61 | show_modal( |
---|
62 | "Browser not supported", |
---|
63 | "Sorry, the workflow editor is not supported for IE6 and below." |
---|
64 | ); |
---|
65 | return; |
---|
66 | } |
---|
67 | |
---|
68 | // Init tool options. |
---|
69 | %if trans.app.toolbox_search.enabled: |
---|
70 | make_popupmenu( $("#tools-options-button"), { |
---|
71 | ## Search tools menu item. |
---|
72 | <% |
---|
73 | show_tool_search = False |
---|
74 | if trans.user: |
---|
75 | show_tool_search = trans.user.preferences.get( "workflow.show_tool_search", "True" ) |
---|
76 | |
---|
77 | if show_tool_search == "True": |
---|
78 | initial_text = "Hide Search" |
---|
79 | else: |
---|
80 | initial_text = "Search Tools" |
---|
81 | %> |
---|
82 | "${initial_text}": function() { |
---|
83 | // Show/hide menu and update vars, user preferences. |
---|
84 | var menu = $('#tool-search'); |
---|
85 | if (menu.is(":visible")) |
---|
86 | { |
---|
87 | // Hide menu. |
---|
88 | pref_value = "False"; |
---|
89 | menu_option_text = "Search Tools"; |
---|
90 | menu.toggle(); |
---|
91 | |
---|
92 | // Reset search. |
---|
93 | reset_tool_search(true); |
---|
94 | } |
---|
95 | else |
---|
96 | { |
---|
97 | // Show menu. |
---|
98 | pref_value = "True"; |
---|
99 | menu_option_text = "Hide Search"; |
---|
100 | menu.toggle(); |
---|
101 | } |
---|
102 | |
---|
103 | // Update menu option. |
---|
104 | $("#tools-options-button-menu").find("li").eq(0).text(menu_option_text); |
---|
105 | |
---|
106 | galaxy_async.set_user_pref("workflow.show_tool_search", pref_value); |
---|
107 | } |
---|
108 | }); |
---|
109 | |
---|
110 | // Init searching. |
---|
111 | $("#tool-search-query").click( function (){ |
---|
112 | $(this).focus(); |
---|
113 | $(this).select(); |
---|
114 | }) |
---|
115 | .keyup( function () { |
---|
116 | // Remove italics. |
---|
117 | $(this).css("font-style", "normal"); |
---|
118 | |
---|
119 | // Don't update if same value as last time |
---|
120 | if ( this.value.length < 3 ) { |
---|
121 | reset_tool_search(false); |
---|
122 | } else if ( this.value != this.lastValue ) { |
---|
123 | // Add class to denote that searching is active. |
---|
124 | $(this).addClass("search_active"); |
---|
125 | // input.addClass(config.loadingClass); |
---|
126 | // Add '*' to facilitate partial matching. |
---|
127 | var q = this.value + '*'; |
---|
128 | // Stop previous ajax-request |
---|
129 | if (this.timer) { |
---|
130 | clearTimeout(this.timer); |
---|
131 | } |
---|
132 | // Start a new ajax-request in X ms |
---|
133 | $("#search-spinner").show(); |
---|
134 | this.timer = setTimeout(function () { |
---|
135 | |
---|
136 | $.get("${h.url_for( controller='root', action='tool_search' )}", { query: q }, function (data) { |
---|
137 | // input.removeClass(config.loadingClass); |
---|
138 | // Show live-search if results and search-term aren't empty |
---|
139 | $("#search-no-results").hide(); |
---|
140 | // Hide all tool sections. |
---|
141 | $(".toolSectionWrapper").hide(); |
---|
142 | // This hides all tools but not workflows link (which is in a .toolTitle div). |
---|
143 | $(".toolSectionWrapper").find(".toolTitle").hide(); |
---|
144 | if ( data.length != 0 ) { |
---|
145 | // Map tool ids to element ids and join them. |
---|
146 | var s = $.map( data, function( n, i ) { return "#link-" + n; } ).join( ", " ); |
---|
147 | |
---|
148 | // First pass to show matching tools and their parents. |
---|
149 | $(s).each( function() { |
---|
150 | // Add class to denote match. |
---|
151 | $(this).parent().addClass("search_match"); |
---|
152 | $(this).parent().show().parent().parent().show().parent().show(); |
---|
153 | }); |
---|
154 | |
---|
155 | // Hide labels that have no visible children. |
---|
156 | $(".toolPanelLabel").each( function() { |
---|
157 | var this_label = $(this); |
---|
158 | var next = this_label.next(); |
---|
159 | var no_visible_tools = true; |
---|
160 | // Look through tools following label and, if none are visible, hide label. |
---|
161 | while (next.length != 0 && next.hasClass("toolTitle")) |
---|
162 | { |
---|
163 | if (next.is(":visible")) |
---|
164 | { |
---|
165 | no_visible_tools = false; |
---|
166 | break; |
---|
167 | } |
---|
168 | else |
---|
169 | next = next.next(); |
---|
170 | } |
---|
171 | if (no_visible_tools) |
---|
172 | this_label.hide(); |
---|
173 | }); |
---|
174 | } else { |
---|
175 | $("#search-no-results").show(); |
---|
176 | } |
---|
177 | $("#search-spinner").hide(); |
---|
178 | }, "json" ); |
---|
179 | }, 200 ); |
---|
180 | } |
---|
181 | this.lastValue = this.value; |
---|
182 | }); |
---|
183 | %endif |
---|
184 | |
---|
185 | // Load jStore for local storage |
---|
186 | $.jStore.init("galaxy"); // Auto-select best storage |
---|
187 | |
---|
188 | // Canvas overview management |
---|
189 | canvas_manager = new CanvasManager( $("#canvas-viewport"), $("#overview") ); |
---|
190 | |
---|
191 | // Initialize workflow state |
---|
192 | reset(); |
---|
193 | // Load the datatype info |
---|
194 | $.ajax( { |
---|
195 | url: "${h.url_for( action='get_datatypes' )}", |
---|
196 | dataType: "json", |
---|
197 | cache: false, |
---|
198 | success: function( data ) { |
---|
199 | populate_datatype_info( data ); |
---|
200 | // Load workflow definition |
---|
201 | $.ajax( { |
---|
202 | url: "${h.url_for( action='load_workflow' )}", |
---|
203 | data: { id: "${trans.security.encode_id( stored.id )}", "_": "true" }, |
---|
204 | dataType: 'json', |
---|
205 | cache: false, |
---|
206 | success: function( data ) { |
---|
207 | reset(); |
---|
208 | workflow.from_simple( data ); |
---|
209 | workflow.has_changes = false; |
---|
210 | workflow.fit_canvas_to_nodes(); |
---|
211 | scroll_to_nodes(); |
---|
212 | canvas_manager.draw_overview(); |
---|
213 | // Determine if any parameters were 'upgraded' and provide message |
---|
214 | upgrade_message = "" |
---|
215 | $.each( data['upgrade_messages'], function( k, v ) { |
---|
216 | upgrade_message += ( "<li>Step " + ( parseInt(k) + 1 ) + ": " + workflow.nodes[k].name + "<ul>"); |
---|
217 | $.each( v, function( i, vv ) { |
---|
218 | upgrade_message += "<li>" + vv +"</li>"; |
---|
219 | }); |
---|
220 | upgrade_message += "</ul></li>"; |
---|
221 | }); |
---|
222 | if ( upgrade_message ) { |
---|
223 | show_modal( "Workflow loaded with changes", |
---|
224 | "Problems were encountered loading this workflow (possibly a result of tool upgrades). Please review the following parameters and then save.<ul>" + upgrade_message + "</ul>", |
---|
225 | { "Continue" : hide_modal } ); |
---|
226 | } else { |
---|
227 | hide_modal(); |
---|
228 | } |
---|
229 | }, |
---|
230 | beforeSubmit: function( data ) { |
---|
231 | show_modal( "Loading workflow", "progress" ); |
---|
232 | } |
---|
233 | }); |
---|
234 | } |
---|
235 | }); |
---|
236 | |
---|
237 | // For autosave purposes |
---|
238 | $(document).ajaxStart( function() { |
---|
239 | active_ajax_call = true; |
---|
240 | $(document).bind( "ajaxStop.global", function() { |
---|
241 | active_ajax_call = false; |
---|
242 | }); |
---|
243 | }); |
---|
244 | |
---|
245 | $(document).ajaxError( function ( e, x ) { |
---|
246 | // console.log( e, x ); |
---|
247 | var message = x.responseText || x.statusText || "Could not connect to server"; |
---|
248 | show_modal( "Server error", message, { "Ignore error" : hide_modal } ); |
---|
249 | return false; |
---|
250 | }); |
---|
251 | |
---|
252 | make_popupmenu( $("#workflow-options-button"), { |
---|
253 | ##"Create New" : create_new_workflow_dialog, |
---|
254 | "Edit Attributes" : edit_workflow_attributes, |
---|
255 | ##"Edit Workflow Outputs": edit_workflow_outputs, |
---|
256 | "Layout": layout_editor, |
---|
257 | "Save" : save_current_workflow, |
---|
258 | ##"Load a Workflow" : load_workflow, |
---|
259 | "Close": close_editor, |
---|
260 | }); |
---|
261 | |
---|
262 | function edit_workflow_outputs(){ |
---|
263 | workflow.clear_active_node(); |
---|
264 | $('.right-content').hide(); |
---|
265 | var new_content = ""; |
---|
266 | for (var node_key in workflow.nodes){ |
---|
267 | var node = workflow.nodes[node_key]; |
---|
268 | if(node.type == 'tool'){ |
---|
269 | new_content += "<div class='toolForm' style='margin-bottom:5px;'><div class='toolFormTitle'>Step " + node.id + " - " + node.name + "</div>"; |
---|
270 | for (var ot_key in node.output_terminals){ |
---|
271 | var output = node.output_terminals[ot_key]; |
---|
272 | // if (node.workflow_outputs[node.id + "|" + output.name]){ |
---|
273 | if ($.inArray(output.name, node.workflow_outputs) != -1){ |
---|
274 | new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' checked /></p>"; |
---|
275 | } |
---|
276 | else{ |
---|
277 | new_content += "<p>"+output.name +"<input type='checkbox' name='"+ node.id + "|" + output.name +"' /></p>"; |
---|
278 | } |
---|
279 | } |
---|
280 | new_content += "</div>"; |
---|
281 | } |
---|
282 | } |
---|
283 | $("#output-fill-area").html(new_content); |
---|
284 | $("#output-fill-area input").bind('click', function(){ |
---|
285 | var node_id = this.name.split('|')[0]; |
---|
286 | var output_name = this.name.split('|')[1]; |
---|
287 | if (this.checked){ |
---|
288 | if($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) == -1){ |
---|
289 | workflow.nodes[node_id].workflow_outputs.push(output_name); |
---|
290 | }//else it's already in the array. Shouldn't happen, but forget it. |
---|
291 | }else{ |
---|
292 | while ($.inArray(output_name, workflow.nodes[node_id].workflow_outputs) != -1){ |
---|
293 | var ia = $.inArray(output_name, workflow.nodes[node_id].workflow_outputs); |
---|
294 | workflow.nodes[node_id].workflow_outputs = workflow.nodes[node_id].workflow_outputs.slice(0,ia).concat( workflow.nodes[node_id].workflow_outputs.slice(ia+1) ); |
---|
295 | } |
---|
296 | } |
---|
297 | workflow.has_changes = true; |
---|
298 | }); |
---|
299 | $('#workflow-output-area').show(); |
---|
300 | }; |
---|
301 | |
---|
302 | function layout_editor() { |
---|
303 | workflow.layout(); |
---|
304 | workflow.fit_canvas_to_nodes(); |
---|
305 | scroll_to_nodes(); |
---|
306 | canvas_manager.draw_overview(); |
---|
307 | }; |
---|
308 | |
---|
309 | function edit_workflow_attributes() { |
---|
310 | workflow.clear_active_node(); |
---|
311 | $('.right-content').hide(); |
---|
312 | $('#edit-attributes').show(); |
---|
313 | |
---|
314 | }; |
---|
315 | |
---|
316 | $.jStore.engineReady(function() { |
---|
317 | // On load, set the size to the pref stored in local storage if it exists |
---|
318 | overview_size = $.jStore.store("overview-size"); |
---|
319 | if (overview_size !== undefined) { |
---|
320 | $("#overview-border").css( { |
---|
321 | width: overview_size, |
---|
322 | height: overview_size |
---|
323 | }); |
---|
324 | } |
---|
325 | |
---|
326 | // Show viewport on load unless pref says it's off |
---|
327 | if ($.jStore.store("overview-off")) { |
---|
328 | hide_overview(); |
---|
329 | } else { |
---|
330 | show_overview(); |
---|
331 | } |
---|
332 | }); |
---|
333 | |
---|
334 | // Stores the size of the overview into local storage when it's resized |
---|
335 | $("#overview-border").bind( "dragend", function( e ) { |
---|
336 | var op = $(this).offsetParent(); |
---|
337 | var opo = op.offset(); |
---|
338 | var new_size = Math.max( op.width() - ( e.offsetX - opo.left ), |
---|
339 | op.height() - ( e.offsetY - opo.top ) ); |
---|
340 | $.jStore.store("overview-size", new_size + "px"); |
---|
341 | }); |
---|
342 | |
---|
343 | function show_overview() { |
---|
344 | $.jStore.remove("overview-off"); |
---|
345 | $("#overview-border").css("right", "0px"); |
---|
346 | $("#close-viewport").css("background-position", "0px 0px"); |
---|
347 | } |
---|
348 | |
---|
349 | function hide_overview() { |
---|
350 | $.jStore.store("overview-off", true); |
---|
351 | $("#overview-border").css("right", "20000px"); |
---|
352 | $("#close-viewport").css("background-position", "12px 0px"); |
---|
353 | } |
---|
354 | |
---|
355 | // Lets the overview be toggled visible and invisible, adjusting the arrows accordingly |
---|
356 | $("#close-viewport").click( function() { |
---|
357 | $("#overview-border").css("right") == "0px" ? hide_overview() : show_overview(); |
---|
358 | }); |
---|
359 | |
---|
360 | // Unload handler |
---|
361 | window.onbeforeunload = function() { |
---|
362 | if ( workflow && workflow.has_changes ) { |
---|
363 | return "There are unsaved changes to your workflow which will be lost."; |
---|
364 | } |
---|
365 | }; |
---|
366 | |
---|
367 | // Tool menu |
---|
368 | $( "div.toolSectionBody" ).hide(); |
---|
369 | $( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" ); |
---|
370 | var last_expanded = null; |
---|
371 | $( "div.toolSectionTitle" ).each( function() { |
---|
372 | var body = $(this).next( "div.toolSectionBody" ); |
---|
373 | $(this).click( function() { |
---|
374 | if ( body.is( ":hidden" ) ) { |
---|
375 | if ( last_expanded ) last_expanded.slideUp( "fast" ); |
---|
376 | last_expanded = body; |
---|
377 | body.slideDown( "fast" ); |
---|
378 | } |
---|
379 | else { |
---|
380 | body.slideUp( "fast" ); |
---|
381 | last_expanded = null; |
---|
382 | } |
---|
383 | }); |
---|
384 | }); |
---|
385 | |
---|
386 | // Rename async. |
---|
387 | async_save_text("workflow-name", "workflow-name", "${h.url_for( action='rename_async', id=trans.security.encode_id(stored.id) )}", "new_name"); |
---|
388 | |
---|
389 | // Tag async. Simply have the workflow edit element generate a click on the tag element to activate tagging. |
---|
390 | $('#workflow-tag').click( function() { |
---|
391 | $('.tag-area').click(); |
---|
392 | return false; |
---|
393 | }); |
---|
394 | // Annotate async. |
---|
395 | async_save_text("workflow-annotation", "workflow-annotation", "${h.url_for( action='annotate_async', id=trans.security.encode_id(stored.id) )}", "new_annotation", 25, true, 4); |
---|
396 | }); |
---|
397 | |
---|
398 | // Global state for the whole workflow |
---|
399 | function reset() { |
---|
400 | if ( workflow ) { |
---|
401 | workflow.remove_all(); |
---|
402 | } |
---|
403 | workflow = new Workflow( $("#canvas-container") ); |
---|
404 | } |
---|
405 | |
---|
406 | function scroll_to_nodes() { |
---|
407 | var cv = $("#canvas-viewport"); |
---|
408 | var cc = $("#canvas-container") |
---|
409 | var top, left; |
---|
410 | if ( cc.width() < cv.width() ) { |
---|
411 | left = ( cv.width() - cc.width() ) / 2; |
---|
412 | } else { |
---|
413 | left = 0; |
---|
414 | } |
---|
415 | if ( cc.height() < cv.height() ) { |
---|
416 | top = ( cv.height() - cc.height() ) / 2; |
---|
417 | } else { |
---|
418 | top = 0; |
---|
419 | } |
---|
420 | cc.css( { left: left, top: top } ); |
---|
421 | } |
---|
422 | |
---|
423 | // Add a new step to the workflow by tool id |
---|
424 | function add_node_for_tool( id, title ) { |
---|
425 | var node = prebuild_node( 'tool', title, id ); |
---|
426 | workflow.add_node( node ); |
---|
427 | workflow.fit_canvas_to_nodes(); |
---|
428 | canvas_manager.draw_overview(); |
---|
429 | workflow.activate_node( node ); |
---|
430 | $.ajax( { |
---|
431 | url: "${h.url_for( action='get_new_module_info' )}", |
---|
432 | data: { type: "tool", tool_id: id, "_": "true" }, |
---|
433 | global: false, |
---|
434 | dataType: "json", |
---|
435 | success: function( data ) { |
---|
436 | node.init_field_data( data ); |
---|
437 | }, |
---|
438 | error: function( x, e ) { |
---|
439 | var m = "error loading field data" |
---|
440 | if ( x.status == 0 ) { |
---|
441 | m += ", server unavailable" |
---|
442 | } |
---|
443 | node.error( m ); |
---|
444 | } |
---|
445 | }); |
---|
446 | }; |
---|
447 | |
---|
448 | function add_node_for_module( type, title ) { |
---|
449 | node = prebuild_node( type, title ); |
---|
450 | workflow.add_node( node ); |
---|
451 | workflow.fit_canvas_to_nodes(); |
---|
452 | canvas_manager.draw_overview(); |
---|
453 | workflow.activate_node( node ); |
---|
454 | $.ajax( { |
---|
455 | url: "${h.url_for( action='get_new_module_info' )}", |
---|
456 | data: { type: type, "_": "true" }, |
---|
457 | dataType: "json", |
---|
458 | success: function( data ) { |
---|
459 | node.init_field_data( data ); |
---|
460 | }, |
---|
461 | error: function( x, e ) { |
---|
462 | var m = "error loading field data" |
---|
463 | if ( x.status == 0 ) { |
---|
464 | m += ", server unavailable" |
---|
465 | } |
---|
466 | node.error( m ); |
---|
467 | } |
---|
468 | }); |
---|
469 | }; |
---|
470 | |
---|
471 | <% |
---|
472 | from galaxy.jobs.actions.post import ActionBox |
---|
473 | %> |
---|
474 | |
---|
475 | // This function preloads how to display known pja's. |
---|
476 | function display_pja(pja, node){ |
---|
477 | // DBTODO SANITIZE INPUTS. |
---|
478 | p_str = ''; |
---|
479 | ${ActionBox.get_forms(trans)} |
---|
480 | $("#pja_container").append(p_str); |
---|
481 | $("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function (){ |
---|
482 | action_to_rem = $(this).closest(".toolForm", ".action_tag").children(".action_tag:first").text(); |
---|
483 | $(this).closest(".toolForm").remove(); |
---|
484 | delete workflow.active_node.post_job_actions[action_to_rem]; |
---|
485 | workflow.active_form_has_changes = true; |
---|
486 | }); |
---|
487 | } |
---|
488 | |
---|
489 | function display_pja_list(){ |
---|
490 | return "${ActionBox.get_add_list()}"; |
---|
491 | } |
---|
492 | |
---|
493 | function display_file_list(node){ |
---|
494 | addlist = "<select id='node_data_list' name='node_data_list'>"; |
---|
495 | for (var out_terminal in node.output_terminals){ |
---|
496 | addlist += "<option value='" + out_terminal + "'>"+ out_terminal +"</option>"; |
---|
497 | } |
---|
498 | addlist += "</select>"; |
---|
499 | return addlist; |
---|
500 | } |
---|
501 | |
---|
502 | function new_pja(action_type, target, node){ |
---|
503 | if (node.post_job_actions == undefined){ |
---|
504 | //New tool node, set up dict. |
---|
505 | node.post_job_actions = {}; |
---|
506 | } |
---|
507 | if (node.post_job_actions[action_type+target] == undefined){ |
---|
508 | var new_pja = new Object(); |
---|
509 | new_pja.action_type = action_type; |
---|
510 | new_pja.output_name = target; |
---|
511 | node.post_job_actions[action_type+target] = null; |
---|
512 | node.post_job_actions[action_type+target] = new_pja; |
---|
513 | display_pja(new_pja, node); |
---|
514 | workflow.active_form_has_changes = true; |
---|
515 | return true; |
---|
516 | }else{ |
---|
517 | return false; |
---|
518 | } |
---|
519 | } |
---|
520 | |
---|
521 | function show_form_for_tool( text, node ) { |
---|
522 | $('.right-content').hide(); |
---|
523 | $("#right-content").show().html( text ); |
---|
524 | // Add metadata form to tool. |
---|
525 | if (node) { |
---|
526 | $("#right-content").find(".toolForm:first").after( "<p><div class='metadataForm'> \ |
---|
527 | <div class='metadataFormTitle'>Edit Step Attributes</div> \ |
---|
528 | <div class='form-row'> \ |
---|
529 | <label>Annotation / Notes:</label> \ |
---|
530 | <div style='margin-right: 10px;'> \ |
---|
531 | <textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \ |
---|
532 | <div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \ |
---|
533 | </div> \ |
---|
534 | </div> \ |
---|
535 | </div>" ); |
---|
536 | } |
---|
537 | // Add step actions. |
---|
538 | if (node && node.type=='tool'){ |
---|
539 | pjastr = "<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> \ |
---|
540 | " + display_pja_list() + " <br/> "+ display_file_list(node) + " <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div>\ |
---|
541 | </div><div class='form-row'>\ |
---|
542 | <div style='margin-right: 10px;'><span id='pja_container'></span>"; |
---|
543 | pjastr += "<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>"; |
---|
544 | $("#right-content").find(".toolForm").after( pjastr ); |
---|
545 | for (var key in node.post_job_actions){ |
---|
546 | if (key != "undefined"){ //To make sure we haven't just deleted it. |
---|
547 | display_pja(node.post_job_actions[key], node); |
---|
548 | } |
---|
549 | } |
---|
550 | $("#add_pja").click(function (){ |
---|
551 | new_pja($("#new_pja_list").val(),$("#node_data_list").val(), node); |
---|
552 | }); |
---|
553 | } |
---|
554 | $("#right-content").find( "form" ).ajaxForm( { |
---|
555 | type: 'POST', |
---|
556 | dataType: 'json', |
---|
557 | success: function( data ) { |
---|
558 | workflow.active_form_has_changes = false; |
---|
559 | node.update_field_data( data ); |
---|
560 | }, |
---|
561 | beforeSubmit: function( data ) { |
---|
562 | data.push( { name: 'tool_state', value: node.tool_state } ); |
---|
563 | data.push( { name: '_', value: "true" } ); |
---|
564 | } |
---|
565 | }).each( function() { |
---|
566 | form = this; |
---|
567 | $(this).find( "select[refresh_on_change='true']").change( function() { |
---|
568 | $(form).submit(); |
---|
569 | }); |
---|
570 | $(this).find( ".popupmenu" ).each( function() { |
---|
571 | var id = $(this).parents( "div.form-row" ).attr( 'id' ); |
---|
572 | var b = $('<a class="popup-arrow" id="popup-arrow-for-' + id + '">▼</a>'); |
---|
573 | var options = {}; |
---|
574 | $(this).find( "button" ).each( function() { |
---|
575 | var name = $(this).attr( 'name' ); |
---|
576 | var value = $(this).attr( 'value' ); |
---|
577 | options[ $(this).text() ] = function() { |
---|
578 | $(form).append( "<input type='hidden' name='"+name+"' value='"+value+"' />" ).submit(); |
---|
579 | } |
---|
580 | }); |
---|
581 | b.insertAfter( this ); |
---|
582 | $(this).remove(); |
---|
583 | make_popupmenu( b, options ); |
---|
584 | }); |
---|
585 | // Implements auto-saving based on whether the inputs change. We consider |
---|
586 | // "changed" to be when a field is accessed and not necessarily modified |
---|
587 | // because of an issue where "onchange" is not triggered when activating |
---|
588 | // another node, or saving the workflow. |
---|
589 | $(this).find("input,textarea,select").each( function() { |
---|
590 | $(this).focus( function() { |
---|
591 | workflow.active_form_has_changes = true; |
---|
592 | }); |
---|
593 | }); |
---|
594 | }); |
---|
595 | } |
---|
596 | |
---|
597 | var close_editor = function() { |
---|
598 | <% next_url = h.url_for( controller='workflow', action='index' ) %> |
---|
599 | workflow.check_changes_in_active_form(); |
---|
600 | if ( workflow && workflow.has_changes ) { |
---|
601 | do_close = function() { |
---|
602 | window.onbeforeunload = undefined; |
---|
603 | window.document.location = "${next_url}" |
---|
604 | }; |
---|
605 | show_modal( "Close workflow editor", |
---|
606 | "There are unsaved changes to your workflow which will be lost.", |
---|
607 | { |
---|
608 | "Cancel" : hide_modal, |
---|
609 | "Save Changes" : function() { |
---|
610 | save_current_workflow( null, do_close ); |
---|
611 | } |
---|
612 | }, { |
---|
613 | "Don't Save": do_close |
---|
614 | } ); |
---|
615 | } else { |
---|
616 | window.document.location = "${next_url}" |
---|
617 | } |
---|
618 | } |
---|
619 | |
---|
620 | var save_current_workflow = function ( eventObj, success_callback ) { |
---|
621 | show_modal( "Saving workflow", "progress" ); |
---|
622 | workflow.check_changes_in_active_form(); |
---|
623 | if (!workflow.has_changes) { |
---|
624 | hide_modal(); |
---|
625 | if ( success_callback ) { |
---|
626 | success_callback(); |
---|
627 | } |
---|
628 | return; |
---|
629 | } |
---|
630 | var savefn = function(callback) { |
---|
631 | $.ajax( { |
---|
632 | url: "${h.url_for( action='save_workflow' )}", |
---|
633 | type: "POST", |
---|
634 | data: { |
---|
635 | id: "${trans.security.encode_id( stored.id )}", |
---|
636 | workflow_data: function() { return JSON.stringify( workflow.to_simple() ) }, |
---|
637 | "_": "true" |
---|
638 | }, |
---|
639 | dataType: 'json', |
---|
640 | success: function( data ) { |
---|
641 | var body = $("<div></div>").text( data.message ); |
---|
642 | if ( data.errors ) { |
---|
643 | body.addClass( "warningmark" ) |
---|
644 | var errlist = $( "<ul/>" ); |
---|
645 | $.each( data.errors, function( i, v ) { |
---|
646 | $("<li></li>").text( v ).appendTo( errlist ); |
---|
647 | }); |
---|
648 | body.append( errlist ); |
---|
649 | } else { |
---|
650 | body.addClass( "donemark" ); |
---|
651 | } |
---|
652 | workflow.name = data.name; |
---|
653 | workflow.has_changes = false; |
---|
654 | workflow.stored = true; |
---|
655 | if ( data.errors ) { |
---|
656 | show_modal( "Saving workflow", body, { "Ok" : hide_modal } ); |
---|
657 | } else { |
---|
658 | if (callback) { |
---|
659 | callback(); |
---|
660 | } |
---|
661 | hide_modal(); |
---|
662 | } |
---|
663 | } |
---|
664 | }); |
---|
665 | } |
---|
666 | |
---|
667 | // We bind to ajaxStop because of auto-saving, since the form submission ajax |
---|
668 | // call needs to be completed so that the new data is saved |
---|
669 | if (active_ajax_call) { |
---|
670 | $(document).bind('ajaxStop.save_workflow', function() { |
---|
671 | $(document).unbind('ajaxStop.save_workflow'); |
---|
672 | savefn(); |
---|
673 | $(document).unbind('ajaxStop.save_workflow'); // IE7 needs it here |
---|
674 | active_ajax_call = false; |
---|
675 | }); |
---|
676 | } else { |
---|
677 | savefn(success_callback); |
---|
678 | } |
---|
679 | } |
---|
680 | |
---|
681 | </script> |
---|
682 | </%def> |
---|
683 | |
---|
684 | <%def name="stylesheets()"> |
---|
685 | |
---|
686 | ## Include "base.css" for styling tool menu and forms (details) |
---|
687 | ${h.css( "base", "autocomplete_tagging", "tool_menu" )} |
---|
688 | |
---|
689 | ## But make sure styles for the layout take precedence |
---|
690 | ${parent.stylesheets()} |
---|
691 | |
---|
692 | <style type="text/css"> |
---|
693 | body { margin: 0; padding: 0; overflow: hidden; } |
---|
694 | |
---|
695 | /* Wider right panel */ |
---|
696 | #center { right: 309px; } |
---|
697 | #right-border { right: 300px; } |
---|
698 | #right { width: 300px; } |
---|
699 | ## /* Relative masthead size */ |
---|
700 | ## #masthead { height: 2.5em; } |
---|
701 | ## #masthead div.title { font-size: 1.8em; } |
---|
702 | ## #left, #left-border, #center, #right-border, #right { |
---|
703 | ## top: 2.5em; |
---|
704 | ## margin-top: 7px; |
---|
705 | ## } |
---|
706 | |
---|
707 | #left { |
---|
708 | background: #C1C9E5 url(${h.url_for('/static/style/menu_bg.png')}) top repeat-x; |
---|
709 | } |
---|
710 | |
---|
711 | div.toolMenu { |
---|
712 | margin: 5px; |
---|
713 | margin-left: 10px; |
---|
714 | margin-right: 10px; |
---|
715 | } |
---|
716 | div.toolMenuGroupHeader { |
---|
717 | font-weight: bold; |
---|
718 | padding-top: 0.5em; |
---|
719 | padding-bottom: 0.5em; |
---|
720 | color: #333; |
---|
721 | font-style: italic; |
---|
722 | border-bottom: dotted #333 1px; |
---|
723 | margin-bottom: 0.5em; |
---|
724 | } |
---|
725 | div.toolTitleDisabled { |
---|
726 | padding-top: 5px; |
---|
727 | padding-bottom: 5px; |
---|
728 | margin-left: 16px; |
---|
729 | margin-right: 10px; |
---|
730 | display: list-item; |
---|
731 | list-style: square outside; |
---|
732 | font-style: italic; |
---|
733 | color: gray; |
---|
734 | } |
---|
735 | div.toolTitleNoSectionDisabled { |
---|
736 | padding-bottom: 0px; |
---|
737 | font-style: italic; |
---|
738 | color: gray; |
---|
739 | } |
---|
740 | div.toolFormRow { |
---|
741 | position: relative; |
---|
742 | } |
---|
743 | |
---|
744 | .right-content { |
---|
745 | margin: 5px; |
---|
746 | } |
---|
747 | |
---|
748 | canvas { position: absolute; z-index: 10; } |
---|
749 | canvas.dragging { position: absolute; z-index: 1000; } |
---|
750 | .input-terminal { width: 12px; height: 12px; background: url(${h.url_for('/static/style/workflow_circle_open.png')}); position: absolute; top: 50%; margin-top: -6px; left: -6px; z-index: 1500; } |
---|
751 | .output-terminal { width: 12px; height: 12px; background: url(${h.url_for('/static/style/workflow_circle_open.png')}); position: absolute; top: 50%; margin-top: -6px; right: -6px; z-index: 1500; } |
---|
752 | .drag-terminal { width: 12px; height: 12px; background: url(${h.url_for('/static/style/workflow_circle_drag.png')}); position: absolute; z-index: 1500; } |
---|
753 | .input-terminal-active { background: url(${h.url_for('/static/style/workflow_circle_green.png')}); } |
---|
754 | ## .input-terminal-hover { background: yellow; border: solid black 1px; } |
---|
755 | .unselectable { -moz-user-select: none; -khtml-user-select: none; user-select: none; } |
---|
756 | img { border: 0; } |
---|
757 | |
---|
758 | div.buttons img { |
---|
759 | width: 16px; height: 16px; |
---|
760 | cursor: pointer; |
---|
761 | } |
---|
762 | |
---|
763 | ## Extra styles for the representation of a tool on the canvas (looks like |
---|
764 | ## a tiny tool form) |
---|
765 | div.toolFormInCanvas { |
---|
766 | z-index: 100; |
---|
767 | position: absolute; |
---|
768 | ## min-width: 130px; |
---|
769 | margin: 6px; |
---|
770 | } |
---|
771 | |
---|
772 | div.toolForm-active { |
---|
773 | z-index: 1001; |
---|
774 | border: solid #8080FF 4px; |
---|
775 | margin: 3px; |
---|
776 | } |
---|
777 | |
---|
778 | div.toolFormTitle { |
---|
779 | cursor: move; |
---|
780 | min-height: 16px; |
---|
781 | } |
---|
782 | |
---|
783 | div.titleRow { |
---|
784 | font-weight: bold; |
---|
785 | border-bottom: dotted gray 1px; |
---|
786 | margin-bottom: 0.5em; |
---|
787 | padding-bottom: 0.25em; |
---|
788 | } |
---|
789 | div.form-row { |
---|
790 | position: relative; |
---|
791 | } |
---|
792 | |
---|
793 | div.tool-node-error div.toolFormTitle { |
---|
794 | background: #FFCCCC; |
---|
795 | border-color: #AA6666; |
---|
796 | } |
---|
797 | div.tool-node-error { |
---|
798 | border-color: #AA6666; |
---|
799 | } |
---|
800 | |
---|
801 | #canvas-area { |
---|
802 | position: absolute; |
---|
803 | top: 0; left: 305px; bottom: 0; right: 0; |
---|
804 | border: solid red 1px; |
---|
805 | overflow: none; |
---|
806 | } |
---|
807 | |
---|
808 | .form-row { |
---|
809 | } |
---|
810 | |
---|
811 | div.toolFormInCanvas div.toolFormBody { |
---|
812 | padding: 0; |
---|
813 | } |
---|
814 | .form-row-clear { |
---|
815 | clear: both; |
---|
816 | } |
---|
817 | |
---|
818 | div.rule { |
---|
819 | height: 0; |
---|
820 | border: none; |
---|
821 | border-bottom: dotted black 1px; |
---|
822 | margin: 0 5px; |
---|
823 | } |
---|
824 | |
---|
825 | .callout { |
---|
826 | position: absolute; |
---|
827 | z-index: 10000; |
---|
828 | } |
---|
829 | |
---|
830 | .pjaForm { |
---|
831 | margin-bottom:10px; |
---|
832 | } |
---|
833 | |
---|
834 | .pjaForm .toolFormBody{ |
---|
835 | padding:10px; |
---|
836 | } |
---|
837 | |
---|
838 | .pjaForm .toolParamHelp{ |
---|
839 | padding:5px; |
---|
840 | } |
---|
841 | |
---|
842 | .panel-header-button-group { |
---|
843 | margin-right: 5px; |
---|
844 | padding-right: 5px; |
---|
845 | border-right: solid gray 1px; |
---|
846 | } |
---|
847 | |
---|
848 | </style> |
---|
849 | </%def> |
---|
850 | |
---|
851 | ## Render a tool in the tool panel |
---|
852 | <%def name="render_tool( tool, section )"> |
---|
853 | %if not tool.hidden: |
---|
854 | %if tool.is_workflow_compatible: |
---|
855 | %if section: |
---|
856 | <div class="toolTitle"> |
---|
857 | %else: |
---|
858 | <div class="toolTitleNoSection"> |
---|
859 | %endif |
---|
860 | %if "[[" in tool.description and "]]" in tool.description: |
---|
861 | ${tool.description.replace( '[[', '<a id="link-${tool.id}" href="javascript:add_node_for_tool( ${tool.id} )">' % tool.id ).replace( "]]", "</a>" )} |
---|
862 | %elif tool.name: |
---|
863 | <a id="link-${tool.id}" href="#" onclick="add_node_for_tool( '${tool.id}', '${tool.name}' )">${tool.name}</a> ${tool.description} |
---|
864 | %else: |
---|
865 | <a id="link-${tool.id}" href="#" onclick="add_node_for_tool( '${tool.id}', '${tool.name}' )">${tool.description}</a> |
---|
866 | %endif |
---|
867 | </div> |
---|
868 | %else: |
---|
869 | %if section: |
---|
870 | <div class="toolTitleDisabled"> |
---|
871 | %else: |
---|
872 | <div class="toolTitleNoSectionDisabled"> |
---|
873 | %endif |
---|
874 | %if "[[" in tool.description and "]]" in tool.description: |
---|
875 | ${tool.description.replace( '[[', '' % tool.id ).replace( "]]", "" )} |
---|
876 | %elif tool.name: |
---|
877 | ${tool.name} ${tool.description} |
---|
878 | %else: |
---|
879 | ${tool.description} |
---|
880 | %endif |
---|
881 | </div> |
---|
882 | %endif |
---|
883 | %endif |
---|
884 | </%def> |
---|
885 | |
---|
886 | ## Render a label in the tool panel |
---|
887 | <%def name="render_label( label )"> |
---|
888 | <div class="toolPanelLabel" id="title_${label.id}"> |
---|
889 | <span>${label.text}</span> |
---|
890 | </div> |
---|
891 | </%def> |
---|
892 | |
---|
893 | <%def name="overlay()"> |
---|
894 | ${parent.overlay( "Loading workflow editor...", |
---|
895 | "<img src='" + h.url_for('/static/images/yui/rel_interstitial_loading.gif') + "'/>" )} |
---|
896 | </%def> |
---|
897 | |
---|
898 | <%def name="left_panel()"> |
---|
899 | <div class="unified-panel-header" unselectable="on"> |
---|
900 | <div class='unified-panel-header-inner'> |
---|
901 | <div style="float: right"> |
---|
902 | <a class='panel-header-button popup' id="tools-options-button" href="#">${_('Options')}</a> |
---|
903 | </div> |
---|
904 | ${n_('Tools')} |
---|
905 | </div> |
---|
906 | </div> |
---|
907 | |
---|
908 | <div class="unified-panel-body" style="overflow: auto;"> |
---|
909 | <div class="toolMenu"> |
---|
910 | ## Tool search. |
---|
911 | <% |
---|
912 | show_tool_search = False |
---|
913 | if trans.user: |
---|
914 | show_tool_search = trans.user.preferences.get( "workflow.show_tool_search", "True" ) |
---|
915 | |
---|
916 | if show_tool_search == "True": |
---|
917 | display = "block" |
---|
918 | else: |
---|
919 | display = "none" |
---|
920 | %> |
---|
921 | <div id="tool-search" style="padding-bottom: 5px; position: relative; display: ${display}; width: 100%"> |
---|
922 | <input type="text" name="query" value="search tools" id="tool-search-query" style="width: 100%; font-style:italic; font-size: inherit"/> |
---|
923 | <img src="${h.url_for('/static/images/loading_small_white_bg.gif')}" id="search-spinner" style="display: none; position: absolute; right: 0; top: 5px;"/> |
---|
924 | </div> |
---|
925 | |
---|
926 | <div class="toolSectionList"> |
---|
927 | %for key, val in app.toolbox.tool_panel.items(): |
---|
928 | <div class="toolSectionWrapper"> |
---|
929 | %if key.startswith( 'tool' ): |
---|
930 | ${render_tool( val, False )} |
---|
931 | %elif key.startswith( 'section' ): |
---|
932 | <% section = val %> |
---|
933 | <div class="toolSectionTitle" id="title_${section.id}"> |
---|
934 | <span>${section.name}</span> |
---|
935 | </div> |
---|
936 | <div id="${section.id}" class="toolSectionBody"> |
---|
937 | <div class="toolSectionBg"> |
---|
938 | %for section_key, section_val in section.elems.items(): |
---|
939 | %if section_key.startswith( 'tool' ): |
---|
940 | ${render_tool( section_val, True )} |
---|
941 | %elif section_key.startswith( 'label' ): |
---|
942 | ${render_label( section_val )} |
---|
943 | %endif |
---|
944 | %endfor |
---|
945 | </div> |
---|
946 | </div> |
---|
947 | %elif key.startswith( 'label' ): |
---|
948 | ${render_label( val )} |
---|
949 | %endif |
---|
950 | <div class="toolSectionPad"></div> |
---|
951 | </div> |
---|
952 | %endfor |
---|
953 | </div> |
---|
954 | ## Feedback when search returns no results. |
---|
955 | <div id="search-no-results" style="display: none; padding-top: 5px"> |
---|
956 | <em><strong>Search did not match any tools.</strong></em> |
---|
957 | </div> |
---|
958 | <div> </div> |
---|
959 | <div class="toolMenuGroupHeader">Workflow control</div> |
---|
960 | <div class="toolSectionTitle" id="title___workflow__input__"> |
---|
961 | <span>Inputs</span> |
---|
962 | </div> |
---|
963 | <div id="__workflow__input__" class="toolSectionBody"> |
---|
964 | <div class="toolSectionBg"> |
---|
965 | <div class="toolTitle"> |
---|
966 | <a href="#" onclick="add_node_for_module( 'data_input', 'Input Dataset' )">Input dataset</a> |
---|
967 | </div> |
---|
968 | </div> |
---|
969 | </div> |
---|
970 | </div> |
---|
971 | </div> |
---|
972 | |
---|
973 | </%def> |
---|
974 | |
---|
975 | <%def name="center_panel()"> |
---|
976 | |
---|
977 | <div class="unified-panel-header" unselectable="on"> |
---|
978 | <div class="unified-panel-header-inner" style="float: right"> |
---|
979 | <a id="workflow-options-button" class="panel-header-button popup" href="#">Options</a> |
---|
980 | </div> |
---|
981 | <div class="unified-panel-header-inner"> |
---|
982 | Workflow Canvas | ${h.to_unicode( stored.name ) | h} |
---|
983 | </div> |
---|
984 | </div> |
---|
985 | |
---|
986 | <div class="unified-panel-body"> |
---|
987 | <div id="canvas-viewport" style="width: 100%; height: 100%; position: absolute; overflow: hidden; background: #EEEEEE; background: white url(${h.url_for('/static/images/light_gray_grid.gif')}) repeat;"> |
---|
988 | <div id="canvas-container" style="position: absolute; width: 100%; height: 100%;"></div> |
---|
989 | </div> |
---|
990 | <div id="overview-border" style="position: absolute; width: 150px; height: 150px; right: 20000px; bottom: 0px; border-top: solid gray 1px; border-left: solid grey 1px; padding: 7px 0 0 7px; background: #EEEEEE no-repeat url(${h.url_for('/static/images/resizable.png')}); z-index: 20000; overflow: hidden; max-width: 300px; max-height: 300px; min-width: 50px; min-height: 50px"> |
---|
991 | <div style="position: relative; overflow: hidden; width: 100%; height: 100%; border-top: solid gray 1px; border-left: solid grey 1px;"> |
---|
992 | <div id="overview" style="position: absolute;"> |
---|
993 | <canvas width="0" height="0" style="background: white; width: 100%; height: 100%;" id="overview-canvas"></canvas> |
---|
994 | <div id="overview-viewport" style="position: absolute; width: 0px; height: 0px; border: solid blue 1px; z-index: 10;"></div> |
---|
995 | </div> |
---|
996 | </div> |
---|
997 | </div> |
---|
998 | <div id="close-viewport" style="border-left: 1px solid #999; border-top: 1px solid #999; background: #ddd url(${h.url_for('/static/images/overview_arrows.png')}) 12px 0px; position: absolute; right: 0px; bottom: 0px; width: 12px; height: 12px; z-index: 25000;"></div> |
---|
999 | </div> |
---|
1000 | |
---|
1001 | </%def> |
---|
1002 | |
---|
1003 | <%def name="right_panel()"> |
---|
1004 | <div class="unified-panel-header" unselectable="on"> |
---|
1005 | <div class="unified-panel-header-inner"> |
---|
1006 | Details |
---|
1007 | </div> |
---|
1008 | </div> |
---|
1009 | <div class="unified-panel-body" style="overflow: auto;"> |
---|
1010 | ## Div for elements to modify workflow attributes. |
---|
1011 | <div id="edit-attributes" class="metadataForm right-content"> |
---|
1012 | <div class="metadataFormTitle">Edit Workflow Attributes</div> |
---|
1013 | <div class="metadataFormBody"> |
---|
1014 | ## Workflow name. |
---|
1015 | <div id="workflow-name-area" class="form-row"> |
---|
1016 | <label>Name:</label> |
---|
1017 | <span id="workflow-name" class="tooltip editable-text" original-title="Click to rename workflow">${h.to_unicode( stored.name ) | h}</span> |
---|
1018 | </div> |
---|
1019 | ## Workflow tags. |
---|
1020 | <%namespace file="/tagging_common.mako" import="render_individual_tagging_element" /> |
---|
1021 | <div class="form-row"> |
---|
1022 | <label> |
---|
1023 | Tags: |
---|
1024 | </label> |
---|
1025 | <div style="float: left; width: 225px; margin-right: 10px; border-style: inset; border-width: 1px; margin-left: 2px"> |
---|
1026 | <style> |
---|
1027 | .tag-area { |
---|
1028 | border: none; |
---|
1029 | } |
---|
1030 | </style> |
---|
1031 | ${render_individual_tagging_element(user=trans.get_user(), tagged_item=stored, elt_context="edit_attributes.mako", use_toggle_link=False, input_size="20")} |
---|
1032 | </div> |
---|
1033 | <div class="toolParamHelp">Apply tags to make it easy to search for and find items with the same tag.</div> |
---|
1034 | </div> |
---|
1035 | ## Workflow annotation. |
---|
1036 | ## Annotation elt. |
---|
1037 | <div id="workflow-annotation-area" class="form-row"> |
---|
1038 | <label>Annotation / Notes:</label> |
---|
1039 | <div id="workflow-annotation" class="tooltip editable-text" original-title="Click to edit annotation"> |
---|
1040 | %if annotation: |
---|
1041 | ${h.to_unicode( annotation ) | h} |
---|
1042 | %else: |
---|
1043 | <em>Describe or add notes to workflow</em> |
---|
1044 | %endif |
---|
1045 | </div> |
---|
1046 | <div class="toolParamHelp">Add an annotation or notes to a workflow; annotations are available when a workflow is viewed.</div> |
---|
1047 | </div> |
---|
1048 | </div> |
---|
1049 | </div> |
---|
1050 | |
---|
1051 | ## Div where tool details are loaded and modified. |
---|
1052 | <div id="right-content" class="right-content"></div> |
---|
1053 | |
---|
1054 | ## Workflow output tagging |
---|
1055 | <div style="display:none;" id="workflow-output-area" class="metadataForm right-content"> |
---|
1056 | <div class="metadataFormTitle">Edit Workflow Outputs</div> |
---|
1057 | <div class="metadataFormBody"><div class="form-row"> |
---|
1058 | <div class="toolParamHelp">Tag step outputs to indicate the final dataset(s) to be generated by running this workflow.</div> |
---|
1059 | <div id="output-fill-area"></div> |
---|
1060 | </div></div> |
---|
1061 | </div> |
---|
1062 | |
---|
1063 | </div> |
---|
1064 | </%def> |
---|