PageRenderTime 22ms CodeModel.GetById 13ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/templates/root/tool_menu.mako

https://bitbucket.org/cistrome/cistrome-harvard/
Mako | 425 lines | 378 code | 33 blank | 14 comment | 4 complexity | c3ba02dd6027cbc195087ac8072f0433 MD5 | raw file
  1<%!
  2    import re
  3%>
  4
  5<%namespace file="/tagging_common.mako" import="render_tool_tagging_elements" />
  6
  7## Render a tool
  8<%def name="render_tool( tool, section )">
  9    %if not tool.hidden:
 10        %if section:
 11            <div class="toolTitle">
 12        %else:
 13            <div class="toolTitleNoSection">
 14        %endif
 15            <%
 16                if tool.input_required:
 17                    link = h.url_for( controller='tool_runner', tool_id=tool.id )
 18                else:
 19                    link = h.url_for( tool.action, ** tool.get_static_param_values( t ) )
 20            %>
 21            ## FIXME: This doesn't look right
 22            ## %if "[[" in tool.description and "]]" in tool.description:
 23            ##   ${tool.description.replace( '[[', '<a href="link" target="galaxy_main">' % $tool.id ).replace( "]]", "</a>" )
 24            <% tool_id = re.sub( '[^a-z0-9_]', '_', tool.id.lower() ) %>
 25            %if tool.name:
 26                <a class="link-${tool_id} tool-link" href="${link}" target=${tool.target} minsizehint="${tool.uihints.get( 'minwidth', -1 )}">${_(tool.name)}</a> ${tool.description} 
 27            %else:
 28                <a class="link-${tool_id} tool-link" href="${link}" target=${tool.target} minsizehint="${tool.uihints.get( 'minwidth', -1 )}">${tool.description}</a>
 29            %endif
 30        </div>
 31    %endif
 32</%def>
 33
 34## Render a workflow
 35<%def name="render_workflow( key, workflow, section )">
 36    %if section:
 37        <div class="toolTitle">
 38    %else:
 39        <div class="toolTitleNoSection">
 40    %endif
 41        <% encoded_id = key.lstrip( 'workflow_' ) %>
 42        <a id="link-${workflow.id}" href="${ h.url_for( controller='workflow', action='run', id=encoded_id )}" target="_parent">${_(workflow.name)}</a>
 43    </div>
 44</%def>
 45
 46## Render a label
 47<%def name="render_label( label )">
 48    <div class="toolPanelLabel" id="title_${label.id}">
 49        <span>${label.text}</span>
 50    </div>
 51</%def>
 52
 53<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 54<html>
 55    <head>
 56        <title>${_('Galaxy Tools')}</title>
 57        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 58        <link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" />
 59        <link href="${h.url_for('/static/style/tool_menu.css')}" rel="stylesheet" type="text/css" />
 60        <link href="${h.url_for('/static/style/autocomplete_tagging.css')}" rel="stylesheet" type="text/css" />
 61
 62        ##<script type="text/javascript" src="${h.url_for('/static/scripts/jquery.js')}"></script>
 63        ${h.js( "jquery", "galaxy.base", "json2", "autocomplete_tagging" )}
 64
 65        <script type="text/javascript">
 66            // Set up GalaxyAsync object.
 67            var galaxy_async = new GalaxyAsync(${str(trans.app.config.log_actions).lower()});
 68            galaxy_async.set_func_url(galaxy_async.log_user_action, "${h.url_for( controller='user', action='log_user_action_async' )}");
 69        
 70            $(document).ready(function() { 
 71                // Init showing/hiding of tool sections.
 72                $( "div.toolSectionBody" ).hide();
 73                $( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" )
 74                var last_expanded = null;
 75                $( "div.toolSectionTitle" ).each( function() { 
 76                    var body = $(this).next( "div.toolSectionBody" );
 77                    $(this).click( function() {
 78                        if ( body.is( ":hidden" ) ) {
 79                            if ( last_expanded ) {
 80                                last_expanded.slideUp( "fast" );
 81                            }
 82                            last_expanded = body;
 83                            body.slideDown( "fast" );
 84                        } else {
 85                            body.slideUp( "fast" );
 86                            last_expanded = null;
 87                        }
 88                        return false;
 89                    });
 90                });
 91                
 92                // Log clicks on tools.
 93                $("div.toolTitle > a").click( function() {
 94                    var tool_title = $(this).attr('id').split("-")[1];
 95                    var section_title = $.trim( $(this).parents("div.toolSectionWrapper").find("div.toolSectionTitle").text() );
 96                    var search_active = $(this).parents("div.toolTitle").hasClass("search_match");
 97                    
 98                    // Log action.
 99                    galaxy_async.log_user_action("tool_menu_click." + tool_title, section_title, 
100                                                    JSON.stringify({"search_active" : search_active}));
101                });
102                
103                $( "a[minsizehint]" ).click( function() {
104                    if ( parent.handle_minwidth_hint ) {
105                        parent.handle_minwidth_hint( $(this).attr( "minsizehint" ) );
106                    }
107                });
108                
109                // Init searching.
110                $("#tool-search-query").click( function () {
111                    $(this).focus();
112                    $(this).select();
113                }).keyup( function () {
114                    // Remove italics.
115                    $(this).css("font-style", "normal");
116                    
117                    // Don't search if the search value is < 3 chars, but clear the search if there was a previous query
118                    if ( this.value.length < 3 && this.lastValue && this.lastValue.length >= 3 ) {
119                        reset_tool_search(false);
120                        // Re-apply tags
121                        if ( current_tags.length > 0 ) {
122                            $.get("${h.url_for( controller='root', action='tool_search' )}", { query: "", tags: current_tags }, function (data) {
123                                apply_search_results(data);
124                            }, "json" );
125                        }
126                    // Don't update if same value as last time
127                    } else if ( this.value !== this.lastValue ) {
128                        // Add class to denote that searching is active.
129                        $(this).addClass("search_active");
130                        // input.addClass(config.loadingClass);
131                        // Add '*' to facilitate partial matching.
132                        var q = this.value + '*';
133                        // Stop previous ajax-request
134                        if (this.timer) {
135                            clearTimeout(this.timer);
136                        }
137                        // Start a new ajax-request in X ms
138                        $("#search-spinner").show();
139                        this.timer = setTimeout(function () {
140                            $.get("${h.url_for( controller='root', action='tool_search' )}", { query: q, tags: current_tags }, function (data) {
141                                apply_search_results(data);
142                                $("#search-spinner").hide();
143                            }, "json" );
144                        }, 200 );
145                    }
146                    this.lastValue = this.value;
147                });                
148
149                // Apply stored tags
150                %if trans.user and trans.user.preferences.get( 'selected_tool_tags', '' ):
151                    current_tags = "${trans.user.preferences['selected_tool_tags']}".split(",")
152                    $.get("${h.url_for( controller='root', action='tool_search' )}", { query: "", tags: current_tags }, function (data) {
153                        apply_search_results(data);
154                    }, "json" );
155                    $("span.tag-name").each( function() {
156                        for ( var i in current_tags ) {
157                            if ( $(this).text() == current_tags[i] ) {
158                                $(this).addClass("active-tag-name");
159                                $(this).append("<img class='delete-tag-img' src='${h.url_for('/static/images/delete_tag_icon_gray.png')}'/>")
160                            }
161                        }
162                    });
163                %endif
164            });            
165
166            var apply_search_results = function (data) {
167                // input.removeClass(config.loadingClass);
168                // Show live-search if results and search-term aren't empty
169                $("#search-no-results").hide();
170                // Hide all tool sections.
171                $(".toolSectionWrapper").hide();
172                // This hides all tools but not workflows link (which is in a .toolTitle div).
173                $(".toolSectionWrapper").find(".toolTitle").hide();
174                if ( data.length !== 0 ) {
175                    // Map tool ids to element ids and join them.
176                    var s = $.map( data, function( n, i ) { return ".link-" + n.toLowerCase().replace(/[^a-z0-9_]/g,'_'); } ).join( ", " );
177
178                    // First pass to show matching tools and their parents.
179                    $(s).each( function() {
180                        // Add class to denote match.
181                        $(this).parent().addClass("search_match");
182                        if ($(this).parents("#recently_used_wrapper").length === 0) {
183                            // Default behavior.
184                            $(this).parent().show().parent().parent().show().parent().show();
185                        } else if ($(this).parents(".user_pref_visible").length !== 0) {
186                            // RU menu is visible, so filter it as normal.
187                            $(this).parent().show().parent().parent().show().parent().show();
188                        } else  {
189                            // RU menu is not visible, so set up classes and visibility so that if menu shown matching is 
190                            // aleady in place.
191                            $(this).parent().show();
192                        }
193                    });
194                    
195                    // Hide labels that have no visible children.
196                    $(".toolPanelLabel").each( function() {
197                        var this_label = $(this);                                   
198                        var next = this_label.next();
199                        var no_visible_tools = true;
200                        // Look through tools following label and, if none are visible, hide label.
201                        while (next.length !== 0 && next.hasClass("toolTitle")) {
202                            if (next.is(":visible")) {
203                                no_visible_tools = false;
204                                break;
205                            } else {
206                                next = next.next();
207                            }
208                        }
209                        if (no_visible_tools) {
210                            this_label.hide();
211                        }
212                    });
213                } else {
214                    $("#search-no-results").show();
215                }
216            }
217
218            // Update recently used tools menu. Function inserts a new item and removes the last item.
219            function update_recently_used() {
220                $.ajax({
221                    url: "${h.url_for( controller='/user', action='get_most_recently_used_tool_async' )}",
222                    dataType: 'json',
223                    error: function() { 
224                        // console.log( "Failed to update recently used list." );
225                    },
226                    success: function(new_tool_info) {
227                        var recently_used_elts = $("#recently_used").find(".toolTitle");
228                        var first_elt = $(recently_used_elts.first());
229                        var found_in_list = false;
230            
231                        // Look for new tool in current list. If found, rearrange list to move tool to top.
232                        var new_tool_info_id = new_tool_info.id.toLowerCase().replace(/[^a-z0-9_]/, "_")
233                        recently_used_elts.each( function(index) {
234                            var anchor = $(this).find("a");
235                            if (anchor.hasClass("link-" + new_tool_info_id)) {
236                                found_in_list = true;
237                    
238                                // If tool is first, do nothing.
239                                if (index === 0) {
240                                    return;
241                                } else {
242                                    // Tool not first; reorder.
243                                    $(this).remove();
244                                    first_elt.before($(this));
245                                }
246                            }
247                        });
248            
249                        // If tool not in list, create new element, remove last element, and put new element first in list.
250                        if (!found_in_list) {
251                            new_tool_elt = $("<div class='toolTitle'> \
252                                                <a class='link-" + new_tool_info.id + "' href='" + new_tool_info.link + "' target='" + 
253                                                new_tool_info.target + "' minsizehint='" + new_tool_info.minsizehint + "'>" +
254                                                new_tool_info.name + "</a> " + new_tool_info.description + " \
255                                              </div>");
256                            recently_used_elts.last().remove();
257                            recently_used_elts.first().before(new_tool_elt);                            
258                        }
259                    }
260                });                
261
262            }
263
264            var current_tags = new Array();
265            function tool_tag_click(tag_name, tag_value) {
266                var add = true;
267                for ( var i = 0 ; i < current_tags.length ; i++ ) {
268                    if ( current_tags[i] == tag_name ) {
269                        current_tags.splice( i, 1 );
270                        add = false;
271                    }
272                }
273                if ( add ) {
274                    current_tags.push( tag_name );
275                    $("span.tag-name").each( function() {
276                        if ( $(this).text() == tag_name ) {
277                            $(this).addClass("active-tag-name");
278                            $(this).append("<img class='delete-tag-img' src='${h.url_for('/static/images/delete_tag_icon_gray.png')}'/>")
279                        }
280                    });
281                } else {
282                    $("span.tag-name").each( function() {
283                        if ( $(this).text() == tag_name ) {
284                            $(this).removeClass("active-tag-name");
285                            $(this).text(tag_name);
286                        }
287                    });
288                }
289                if ( current_tags.length == 0 ) {
290                    $("#search-no-results").hide();
291                    $(".tool-link").each( function() {
292                        reset_tool_search(false);
293                    });
294                    return;
295                }
296                var q = $("input#tool-search-query").val();
297                if ( q == "search tools" ) {
298                    q = "";
299                } else if ( q.length > 0 ) {
300                    q = q + '*';
301                }
302                $.get("${h.url_for( controller='root', action='tool_search' )}", { query: q, tags: current_tags }, function (data) {
303                    apply_search_results(data);
304                }, "json" );
305            }
306
307        </script>
308    </head>
309
310    <body class="toolMenuPage">
311        <div class="toolMenu">
312            
313                ## Tool search.
314                <%
315                    show_tool_search = True
316                    if trans.user:
317                        show_tool_search = trans.user.preferences.get( "show_tool_search", "False" ) == "True"
318                    
319                    if show_tool_search:
320                        display = "block"
321                    else:
322                        display = "none"
323                %>
324                <div id="tool-search" style="padding-bottom: 5px; position: relative; display: ${display}; width: 100%">
325                    %if trans.app.config.get_bool( 'enable_tool_tags', False ):
326                        <b>Tags:</b>
327                        ${render_tool_tagging_elements()}
328                    %endif
329                    <input type="text" name="query" value="search tools" id="tool-search-query" autocomplete="off" style="width: 100%; font-style:italic; font-size: inherit"/>
330                    <img src="${h.url_for('/static/images/loading_small_white_bg.gif')}" id="search-spinner" style="display: none; position: absolute; right: 0; top: 5px;"/>
331                </div>
332                
333                ## Recently used tools.
334                %if trans.user:
335                    <%
336                    if trans.user.preferences.get( 'show_recently_used_menu', 'False' ) == 'True':
337                        display = "block"
338                        pref_class = "user_pref_visible"
339                    else:
340                        display = "none"
341                        pref_class = "user_pref_hidden"
342                    %>
343                    <div class="toolSectionWrapper ${pref_class}" id="recently_used_wrapper" 
344                            style="display: ${display}; padding-bottom: 5px">
345                        <div class="toolSectionTitle">
346                            <span>Recently Used</span>
347                        </div>
348                        <div id="recently_used" class="toolSectionBody">
349                            <div class="toolSectionBg">
350                                %for tool in recent_tools:
351                                    ${render_tool( tool, True )}
352                                %endfor
353                            </div>
354                        </div>
355                        <div class="toolSectionPad"></div>
356                    </div>
357                %endif
358                
359                ## Tools.
360                %for key, val in toolbox.tool_panel.items():
361                    <div class="toolSectionWrapper">
362                    %if key.startswith( 'tool' ):
363                        ${render_tool( val, False )}
364                    %elif key.startswith( 'workflow' ):
365                        ${render_workflow( key, val, False )}
366                    %elif key.startswith( 'section' ):
367                        <% section = val %>
368                        <div class="toolSectionTitle" id="title_${section.id}">
369                            <span>${section.name}</span>
370                        </div>
371                        <div id="${section.id}" class="toolSectionBody">
372                            <div class="toolSectionBg">
373                                %for section_key, section_val in section.elems.items():
374                                    %if section_key.startswith( 'tool' ):
375                                        ${render_tool( section_val, True )}
376                                    %elif section_key.startswith( 'workflow' ):
377                                        ${render_workflow( section_key, section_val, True )}
378                                    %elif section_key.startswith( 'label' ):
379                                        ${render_label( section_val )}
380                                    %endif
381                                %endfor
382                            </div>
383                        </div>
384                    %elif key.startswith( 'label' ):
385                        ${render_label( val )}
386                    %endif
387                    <div class="toolSectionPad"></div>
388                    </div>
389                %endfor
390                
391                ## Feedback when search returns no results.
392                <div id="search-no-results" style="display: none; padding-top: 5px">
393                    <em><strong>Search did not match any tools.</strong></em>
394                </div>
395                
396                ## Link to workflow management. The location of this may change, but eventually
397                ## at least some workflows will appear here (the user should be able to
398                ## configure which of their stored workflows appear in the tools menu). 
399                
400                %if t.user:
401                    <div class="toolSectionPad"></div>
402                    <div class="toolSectionPad"></div>
403                    <div class="toolSectionTitle" id="title_XXinternalXXworkflow">
404                      <span>Workflows</span>
405                    </div>
406                    <div id="XXinternalXXworkflow" class="toolSectionBody">
407                        <div class="toolSectionBg">
408                            %if t.user.stored_workflow_menu_entries:
409                                %for m in t.user.stored_workflow_menu_entries:
410                                    <div class="toolTitle">
411                                        <a href="${h.url_for( controller='workflow', action='run', id=trans.security.encode_id(m.stored_workflow_id) )}" target="galaxy_main">${m.stored_workflow.name}</a>
412                                    </div>
413                                %endfor
414                            %endif
415                            <div class="toolTitle">
416                                <a href="${h.url_for( controller='workflow', action='list_for_run')}" target="galaxy_main">All workflows</a>
417                            </div>
418                        </div>
419                    </div>
420                %endif
421                
422            </div>
423        </div>
424    </body>
425</html>