root/galaxy-central/templates/workflow/editor.mako @ 2

リビジョン 2, 41.4 KB (コミッタ: hatakeyama, 14 年 前)

import galaxy-central

行番号 
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 + '">&#9660;</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>&nbsp;</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>
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。