[hg] galaxy 1678: Enhance the tool panel, now supports following...
details: http://www.bx.psu.edu/hg/galaxy/rev/c0efda325046 changeset: 1678:c0efda325046 user: Greg Von Kuster <greg@bx.psu.edu> date: Thu Dec 18 16:35:26 2008 -0500 description: Enhance the tool panel, now supports following tags: <toolbox> <tool file="data_source/upload.xml"/> # tools outside sections <label text="Basic Tools" id="basic_tools" /> # labels outside sections <workflow id="529fd61ab1c6cc36" /> # workflows outside sections <section name="Get Data" id="getext"> # sections <tool file="data_source/biomart.xml" /> # tools inside sections <label text="In Section" id="in_section" /> # labels inside sections <workflow id="adb5f5c93f827949" /> # workflows inside sections </section> </toolbox> 16 file(s) affected in this change: lib/galaxy/app.py lib/galaxy/config.py lib/galaxy/tools/__init__.py lib/galaxy/web/controllers/workflow.py lib/galaxy/web/framework/__init__.py lib/galaxy/webapps/reports/config.py reports_wsgi.ini.sample static/june_2007_style/blue/tool_menu.css static/june_2007_style/make_style.py static/june_2007_style/tool_menu.css.tmpl templates/admin_main.mako templates/root/tool_menu.mako templates/workflow/editor.mako test/functional/test_toolbox.py tool_conf.xml.sample universe_wsgi.ini.sample diffs (891 lines): diff -r d86bacb600db -r c0efda325046 lib/galaxy/app.py --- a/lib/galaxy/app.py Thu Dec 18 09:32:43 2008 -0500 +++ b/lib/galaxy/app.py Thu Dec 18 16:35:26 2008 -0500 @@ -1,6 +1,7 @@ import sys, os, atexit from galaxy import config, jobs, util, tools, web +from galaxy.web import security import galaxy.model import galaxy.model.mapping import galaxy.datatypes.registry @@ -26,6 +27,8 @@ db_url, self.config.database_engine_options, create_tables = True ) + # Security helper + self.security = security.SecurityHelper( id_secret=self.config.id_secret ) # Initialize the tools self.toolbox = tools.ToolBox( self.config.tool_config, self.config.tool_path, self ) #Load datatype converters diff -r d86bacb600db -r c0efda325046 lib/galaxy/config.py --- a/lib/galaxy/config.py Thu Dec 18 09:32:43 2008 -0500 +++ b/lib/galaxy/config.py Thu Dec 18 16:35:26 2008 -0500 @@ -35,9 +35,6 @@ self.test_conf = resolve_path( kwargs.get( "test_conf", "" ), self.root ) self.tool_config = resolve_path( kwargs.get( 'tool_config_file', 'tool_conf.xml' ), self.root ) self.tool_secret = kwargs.get( "tool_secret", "" ) - # CRITICAL: the value of id_secret MUST be the same in universe_wsgi.ini and reports_wsgi.ini - # or the framework's __ensure_valid_session method will throw exceptions when switching between - # Galaxy and the reports in the same browser. self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" ) self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) ) self.remote_user_maildomain = kwargs.get( "remote_user_maildomain", None ) diff -r d86bacb600db -r c0efda325046 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py Thu Dec 18 09:32:43 2008 -0500 +++ b/lib/galaxy/tools/__init__.py Thu Dec 18 16:35:26 2008 -0500 @@ -42,8 +42,8 @@ individual tool config files. """ self.tools_by_id = {} - self.tools_and_sections_by_id = {} - self.sections = [] + self.workflows_by_id = {} + self.tool_panel = odict() self.tool_root_dir = tool_root_dir self.app = app try: @@ -54,24 +54,68 @@ def init_tools( self, config_filename ): """ Read the configuration file and load each tool. + The following tags are currently supported: + <toolbox> + <tool file="data_source/upload.xml"/> # tools outside sections + <label text="Basic Tools" id="basic_tools" /> # labels outside sections + <workflow id="529fd61ab1c6cc36" /> # workflows outside sections + <section name="Get Data" id="getext"> # sections + <tool file="data_source/biomart.xml" /> # tools inside sections + <label text="In Section" id="in_section" /> # labels inside sections + <workflow id="adb5f5c93f827949" /> # workflows inside sections + </section> + </toolbox> """ + def load_tool( elem, panel_dict ): + try: + path = elem.get( "file" ) + tool = self.load_tool( os.path.join( self.tool_root_dir, path ) ) + self.tools_by_id[ tool.id ] = tool + key = 'tool_' + tool.id + panel_dict[ key ] = tool + log.debug( "Loaded tool: %s %s" % ( tool.id, tool.version ) ) + except: + log.exception( "error reading tool from path: %s" % path ) + def load_workflow( elem, panel_dict ): + try: + # TODO: should id be encoded? + workflow_id = elem.get( 'id' ) + workflow = self.load_workflow( workflow_id ) + self.workflows_by_id[ workflow_id ] = workflow + key = 'workflow_' + workflow_id + panel_dict[ key ] = workflow + log.debug( "Loaded workflow: %s %s" % ( workflow_id, workflow.name ) ) + except: + log.exception( "error loading workflow: %s" % workflow_id ) + def load_label( elem, panel_dict ): + label = ToolSectionLabel( elem ) + key = 'label_' + label.id + panel_dict[ key ] = label + def load_section( elem, panel_dict ): + section = ToolSection( elem ) + log.debug( "Loading section: %s" % section.name ) + for section_elem in elem: + if section_elem.tag == 'tool': + load_tool( section_elem, section.elems ) + elif section_elem.tag == 'workflow': + load_workflow( section_elem, section.elems ) + elif section_elem.tag == 'label': + load_label( section_elem, section.elems ) + key = 'section_' + section.id + panel_dict[ key ] = section + log.info("parsing the tool configuration") tree = util.parse_xml( config_filename ) root = tree.getroot() - for elem in root.findall("section"): - section = ToolSection(elem) - log.debug( "Loading tools in section: %s" % section.name ) - for tool in elem.findall("tool"): - try: - path = tool.get("file") - tool = self.load_tool( os.path.join( self.tool_root_dir, path ) ) - log.debug( "Loaded tool: %s %s" %( tool.id, tool.version ) ) - self.tools_by_id[tool.id] = tool - self.tools_and_sections_by_id[tool.id] = tool, section - section.tools.append(tool) - except Exception, exc: - log.exception( "error reading tool from path: %s" % path ) - self.sections.append(section) + for elem in root: + if elem.tag == 'tool': + load_tool( elem, self.tool_panel ) + elif elem.tag == 'workflow': + load_workflow( elem, self.tool_panel ) + elif elem.tag == 'section' : + load_section( elem, self.tool_panel ) + elif elem.tag == 'label': + load_label( elem, self.tool_panel ) def load_tool( self, config_file ): """ @@ -94,28 +138,36 @@ def reload( self, tool_id ): """ - Attempt to reload the tool identified by 'tool_id', if successfull + Attempt to reload the tool identified by 'tool_id', if successful replace the old tool. """ - if tool_id not in self.tools_and_sections_by_id: + if tool_id not in self.tools_by_id: raise ToolNotFoundException( "No tool with id %s" % tool_id ) - old_tool, section = self.tools_and_sections_by_id[ tool_id ] + old_tool = self.tools_by_id[ tool_id ] new_tool = self.load_tool( old_tool.config_file ) + # Replace old_tool with new_tool in self.tool_panel + tool_key = 'tool_' + tool_id + for key, val in self.tool_panel.items(): + if key == tool_key: + self.tool_panel[ key ] = new_tool + break + elif key.startswith( 'section' ): + section = val + for section_key, section_val in section.elems.items(): + if section_key == tool_key: + self.tool_panel[ key ].elems[ section_key ] = new_tool + break + self.tools_by_id[ tool_id ] = new_tool log.debug( "Reloaded tool %s %s" %( old_tool.id, old_tool.version ) ) - # Is there a potential sync problem here? This should be roughly - # atomic. Too many indexes for tools... - section.tools[ section.tools.index( old_tool ) ] = new_tool - self.tools_by_id[ tool_id ] = new_tool - self.tools_and_sections_by_id[ tool_id ] = new_tool, section - - def itertools( self ): + + def load_workflow( self, workflow_id ): """ - Iterate over all the tools in the toolbox (ordered by section but - without grouping). + Return an instance of 'Workflow' identified by `id`, + which is encoded in the tool panel. """ - for section in self.sections: - for tool in section.tools: - yield tool + id = self.app.security.decode_id( workflow_id ) + stored = self.app.model.StoredWorkflow.get( id ) + return stored.latest_workflow class ToolSection( object ): """ @@ -126,7 +178,17 @@ self.name = elem.get( "name" ) self.id = elem.get( "id" ) self.version = elem.get( "version" ) - self.tools = [] + self.elems = odict() + +class ToolSectionLabel( object ): + """ + A label for a set of tools that can be displayed above groups of tools + and sections in the user interface + """ + def __init__( self, elem ): + self.text = elem.get( "text" ) + self.id = elem.get( "id" ) + self.version = elem.get( "version" ) class DefaultToolState( object ): """ diff -r d86bacb600db -r c0efda325046 lib/galaxy/web/controllers/workflow.py --- a/lib/galaxy/web/controllers/workflow.py Thu Dec 18 09:32:43 2008 -0500 +++ b/lib/galaxy/web/controllers/workflow.py Thu Dec 18 16:35:26 2008 -0500 @@ -439,13 +439,14 @@ ## % ( workflow_name, web.url_for( action='editor', id=trans.security.encode_id(stored.id) ) ) ) @web.expose - def run( self, trans, id, **kwargs ): + def run( self, trans, id, check_user=True, **kwargs ): stored = get_stored_workflow( trans, id, check_ownership=False ) - user = trans.get_user() - if stored.user != user: - if trans.sa_session.query( model.StoredWorkflowUserShareAssociation ) \ - .filter_by( user=user, stored_workflow=stored ).count() == 0: - error( "Workflow is not owned by or shared with current user" ) + if check_user: + user = trans.get_user() + if stored.user != user: + if trans.sa_session.query( model.StoredWorkflowUserShareAssociation ) \ + .filter_by( user=user, stored_workflow=stored ).count() == 0: + error( "Workflow is not owned by or shared with current user" ) # Get the latest revision workflow = stored.latest_workflow # It is possible for a workflow to have 0 steps diff -r d86bacb600db -r c0efda325046 lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py Thu Dec 18 09:32:43 2008 -0500 +++ b/lib/galaxy/web/framework/__init__.py Thu Dec 18 16:35:26 2008 -0500 @@ -86,8 +86,7 @@ module_directory = galaxy_app.config.template_cache, collection_size = 500 ) # Security helper - from galaxy.web import security - self.security = security.SecurityHelper( id_secret = galaxy_app.config.id_secret ) + self.security = galaxy_app.security def handle_controller_exception( self, e, trans, **kwargs ): if isinstance( e, MessageException ): return trans.show_message( e.message, e.type ) diff -r d86bacb600db -r c0efda325046 lib/galaxy/webapps/reports/config.py --- a/lib/galaxy/webapps/reports/config.py Thu Dec 18 09:32:43 2008 -0500 +++ b/lib/galaxy/webapps/reports/config.py Thu Dec 18 16:35:26 2008 -0500 @@ -25,9 +25,6 @@ # Where dataset files are stored self.file_path = resolve_path( kwargs.get( "file_path", "database/files" ), self.root ) self.new_file_path = resolve_path( kwargs.get( "new_file_path", "database/tmp" ), self.root ) - # CRITICAL: the value of id_secret MUST be the same in universe_wsgi.ini and reports_wsgi.ini - # or the framework's __ensure_valid_session method will throw exceptions when switching between - # Galaxy and the reports in the same browser. self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" ) self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) ) self.template_path = resolve_path( kwargs.get( "template_path", "templates" ), self.root ) diff -r d86bacb600db -r c0efda325046 reports_wsgi.ini.sample --- a/reports_wsgi.ini.sample Thu Dec 18 09:32:43 2008 -0500 +++ b/reports_wsgi.ini.sample Thu Dec 18 16:35:26 2008 -0500 @@ -37,7 +37,6 @@ session_secret = changethisinproduction # Galaxy session security -# The value of id_secret MUST be the same as the value of id_secret in universe_wsgi.ini id_secret = changethisinproductiontoo # Configuration for debugging middleware diff -r d86bacb600db -r c0efda325046 static/june_2007_style/blue/tool_menu.css --- a/static/june_2007_style/blue/tool_menu.css Thu Dec 18 09:32:43 2008 -0500 +++ b/static/june_2007_style/blue/tool_menu.css Thu Dec 18 16:35:26 2008 -0500 @@ -35,6 +35,13 @@ font-weight: bold; } +div.toolPanelLabel +{ + padding-top: 5px; + padding-bottom: 5px; + font-weight: bold; +} + div.toolTitle { padding-top: 5px; @@ -44,3 +51,10 @@ display: list-item; list-style: square outside; } + + +div.toolTitleNoSection +{ + padding-bottom: 0px; + font-weight: bold; +} diff -r d86bacb600db -r c0efda325046 static/june_2007_style/make_style.py --- a/static/june_2007_style/make_style.py Thu Dec 18 09:32:43 2008 -0500 +++ b/static/june_2007_style/make_style.py Thu Dec 18 16:35:26 2008 -0500 @@ -1,12 +1,17 @@ #!/usr/bin/env python -import sys +import sys, string, os.path +from galaxy import eggs +import pkg_resources +pkg_resources.require( "Cheetah" ) + from Cheetah.Template import Template -import string from subprocess import Popen, PIPE -import os.path assert sys.version_info[:2] >= ( 2, 4 ) + +# To create a new style ( this is an example ): +# python make_style.py blue_colors.ini blue def run( cmd ): return Popen( cmd, stdout=PIPE).communicate()[0] diff -r d86bacb600db -r c0efda325046 static/june_2007_style/tool_menu.css.tmpl --- a/static/june_2007_style/tool_menu.css.tmpl Thu Dec 18 09:32:43 2008 -0500 +++ b/static/june_2007_style/tool_menu.css.tmpl Thu Dec 18 16:35:26 2008 -0500 @@ -35,6 +35,13 @@ font-weight: bold; } +div.toolPanelLabel +{ + padding-top: 5px; + padding-bottom: 5px; + font-weight: bold; +} + div.toolTitle { padding-top: 5px; @@ -44,3 +51,10 @@ display: list-item; list-style: square outside; } + + +div.toolTitleNoSection +{ + padding-bottom: 0px; + font-weight: bold; +} diff -r d86bacb600db -r c0efda325046 templates/admin_main.mako --- a/templates/admin_main.mako Thu Dec 18 09:32:43 2008 -0500 +++ b/templates/admin_main.mako Thu Dec 18 16:35:26 2008 -0500 @@ -2,32 +2,38 @@ <%def name="title()">Galaxy Administration</%def> <table align="center" width="70%" class="border" cellpadding="5" cellspacing="5"> - <tr> - <td> - <h3 align="center">Galaxy Administration</h3> - %if msg: - <p class="ok_bgr">${msg}</p> - %endif - </td> - </tr> - <tr> - <td> - <form method="post" action="admin"> - <p>Admin password: <input type="password" name="passwd" size="8"></p> - <p> - Reload tool: - <select name="tool_id"> - %for i, section in enumerate( toolbox.sections ): - <optgroup label="${section.name}"> - %for t in section.tools: - <option value="${t.id}">${t.name}</option> - %endfor - %endfor - </select> - <button name="action" value="tool_reload">Reload</button> - </p> - </form> - </td> - </tr> + <tr> + <td> + <h3 align="center">Galaxy Administration</h3> + %if msg: + <p class="ok_bgr">${msg}</p> + %endif + </td> + </tr> + <tr> + <td> + <form method="post" action="admin"> + <p>Admin password: <input type="password" name="passwd" size="8"></p> + <p> + Reload tool: + <select name="tool_id"> + %for key, val in toolbox.tool_panel.items(): + %if key.startswith( 'tool' ): + <option value="${val.id}">${val.name}</option> + %elif key.startswith( 'section' ): + <optgroup label="${val.name}"> + <% section = val %> + %for section_key, section_val in section.elems.items(): + %if section_key.startswith( 'tool' ): + <option value="${section_val.id}">${section_val.name}</option> + %endif + %endfor + %endif + %endfor + </select> + <button name="action" value="tool_reload">Reload</button> + </p> + </form> + </td> + </tr> </table> - diff -r d86bacb600db -r c0efda325046 templates/root/tool_menu.mako --- a/templates/root/tool_menu.mako Thu Dec 18 09:32:43 2008 -0500 +++ b/templates/root/tool_menu.mako Thu Dec 18 16:35:26 2008 -0500 @@ -1,113 +1,148 @@ +## Render a tool +<%def name="render_tool( tool, section )"> + %if not tool.hidden: + %if section: + <div class="toolTitle"> + %else: + <div class="toolTitleNoSection"> + %endif + <% + if tool.input_required: + link = h.url_for( controller='tool_runner', tool_id=tool.id ) + else: + link = h.url_for( tool.action, ** tool.get_static_param_values( t ) ) + %> + ## FIXME: This doesn't look right + ## %if "[[" in tool.description and "]]" in tool.description: + ## ${tool.description.replace( '[[', '<a href="link" target="galaxy_main">' % $tool.id ).replace( "]]", "</a>" ) + %if tool.name: + <a id="link-${tool.id}" href="${link}" target="galaxy_main" minsizehint="${tool.uihints.get( 'minwidth', -1 )}">${tool.name}</a> ${tool.description} + %else: + <a id="link-${tool.id}" href="${link}" target="galaxy_main" minsizehint="${tool.uihints.get( 'minwidth', -1 )}">${tool.description}</a> + %endif + </div> + %endif +</%def> + +## Render a workflow +<%def name="render_workflow( key, workflow, section )"> + %if section: + <div class="toolTitle"> + %else: + <div class="toolTitleNoSection"> + %endif + <% encoded_id = key.lstrip( 'workflow_' ) %> + <a id="link-${workflow.id}" href="${ h.url_for( controller='workflow', action='run', id=encoded_id, check_user=False )}" target="galaxy_main"}">${workflow.name}</a> + </div> +</%def> + +## Render a label +<%def name="render_label( label )"> + <div class="toolSectionPad"></div> + <div class="toolPanelLabel" id="title_${label.id}"> + <span>${label.text}</span> + </div> + <div class="toolSectionPad"></div> +</%def> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> + <head> + <title>Galaxy Tools</title> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> + <link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" /> + <link href="${h.url_for('/static/style/tool_menu.css')}" rel="stylesheet" type="text/css" /> -<head> -<title>Galaxy Tools</title> -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> -<link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" /> -<link href="${h.url_for('/static/style/tool_menu.css')}" rel="stylesheet" type="text/css" /> + <script type="text/javascript" src="${h.url_for('/static/scripts/jquery.js')}"></script> -<script type="text/javascript" src="${h.url_for('/static/scripts/jquery.js')}"></script> + <script type="text/javascript"> + var q = jQuery.noConflict(); + q(document).ready(function() { + q( "div.toolSectionBody" ).hide(); + q( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" ) + var last_expanded = null; + q( "div.toolSectionTitle" ).each( function() { + var body = q(this).next( "div.toolSectionBody" ); + q(this).click( function() { + if ( body.is( ":hidden" ) ) { + if ( last_expanded ) last_expanded.slideUp( "fast" ); + last_expanded = body; + body.slideDown( "fast" ); + } + else { + body.slideUp( "fast" ); + last_expanded = null; + } + return false; + }); + }); + q( "a[@minsizehint]" ).click( function() { + if ( parent.handle_minwidth_hint ) { + parent.handle_minwidth_hint( q(this).attr( "minsizehint" ) ); + } + }); + }); + </script> + </head> -<script type="text/javascript"> - var q = jQuery.noConflict(); - q(document).ready(function() { - q( "div.toolSectionBody" ).hide(); - q( "div.toolSectionTitle > span" ).wrap( "<a href='#'></a>" ) - var last_expanded = null; - q( "div.toolSectionTitle" ).each( function() { - var body = q(this).next( "div.toolSectionBody" ); - q(this).click( function() { - if ( body.is( ":hidden" ) ) { - if ( last_expanded ) last_expanded.slideUp( "fast" ); - last_expanded = body; - body.slideDown( "fast" ); - } - else { - body.slideUp( "fast" ); - last_expanded = null; - } - return false; - }); - }); - q( "a[@minsizehint]" ).click( function() { - if ( parent.handle_minwidth_hint ) { - parent.handle_minwidth_hint( q(this).attr( "minsizehint" ) ); - } - }); - }); -</script> + <body class="toolMenuPage"> + <div class="toolMenu"> + <div class="toolSectionList"> + %for key, val in toolbox.tool_panel.items(): + %if key.startswith( 'tool' ): + ${render_tool( val, False )} + <div class="toolSectionPad"></div> + %elif key.startswith( 'workflow' ): + ${render_workflow( key, val, False )} + %elif key.startswith( 'section' ): + <% section = val %> + <div class="toolSectionTitle" id="title_${section.id}"> + <span>${section.name}</span> + </div> + <div id="${section.id}" class="toolSectionBody"> + <div class="toolSectionBg"> + %for section_key, section_val in section.elems.items(): + %if section_key.startswith( 'tool' ): + ${render_tool( section_val, True )} + %elif section_key.startswith( 'workflow' ): + ${render_workflow( section_key, section_val, True )} + %elif section_key.startswith( 'label' ): + ${render_label( section_val )} + %endif + %endfor + </div> + </div> + <div class="toolSectionPad"></div> + %elif key.startswith( 'label' ): + ${render_label( val )} + %endif + %endfor -</head> + ## Link to workflow management. The location of this may change, but eventually + ## at least some workflows will appear here (the user should be able to + ## configure which of their stored workflows appear in the tools menu). -<body class="toolMenuPage"> - -<div class="toolMenu"> - -<div class="toolSectionList"> -%for i, section in enumerate( toolbox.sections ): - %if i > 0: - <div class="toolSectionPad"></div> - %endif - <div class="toolSectionTitle" id="title_${section.id}"> - <span>${section.name}</span> - </div> - <div id="${section.id}" class="toolSectionBody"> - <div class="toolSectionBg"> - %for tool in section.tools: - %if not tool.hidden: - <div class="toolTitle"> - <% - if tool.input_required: - link = h.url_for( controller='tool_runner', tool_id=tool.id ) - else: - link = h.url_for( tool.action, ** tool.get_static_param_values( t ) ) - %> - ## FIXME: This doesn't look right - ## %if "[[" in tool.description and "]]" in tool.description: - ## ${tool.description.replace( '[[', '<a href="link" target="galaxy_main">' % $tool.id ).replace( "]]", "</a>" ) - %if tool.name: - <a id="link-${tool.id}" href="${link}" target="galaxy_main" minsizehint="${tool.uihints.get( 'minwidth', -1 )}">${tool.name}</a> ${tool.description} - %else: - <a id="link-${tool.id}" href="${link}" target="galaxy_main" minsizehint="${tool.uihints.get( 'minwidth', -1 )}">${tool.description}</a> - %endif + <div class="toolSectionPad"></div> + <div class="toolSectionPad"></div> + <div class="toolSectionTitle" id="title_XXinternalXXworkflow"> + <span>Workflow <i>(beta)</i></span> + </div> + <div id="XXinternalXXworkflow" class="toolSectionBody"> + <div class="toolSectionBg"> + <div class="toolTitle"> + <a href="${h.url_for( controller='workflow', action='index' )}" target="galaxy_main">Manage</a> workflows + </div> + %if t.user: + %for m in t.user.stored_workflow_menu_entries: + <div class="toolTitle"> + <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> + </div> + %endfor + %endif + </div> + </div> </div> - %endif - %endfor - </div> - </div> -%endfor - -## Link to workflow management. The location of this may change, but eventually -## at least some workflows will appear here (the user should be able to -## configure which of their stored workflows appear in the tools menu). - -<div class="toolSectionPad"></div> -<div class="toolSectionPad"></div> -<div class="toolSectionTitle" id="title_XXinternalXXworkflow"> - <span>Workflow <i>(beta)</i></span> -</div> -<div id="XXinternalXXworkflow" class="toolSectionBody"> - <div class="toolSectionBg"> - <div class="toolTitle"> - <a href="${h.url_for( controller='workflow', action='index' )}" target="galaxy_main">Manage</a> workflows </div> - %if t.user: - %for m in t.user.stored_workflow_menu_entries: - <div class="toolTitle"> - <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> - </div> - %endfor - %endif - </div> -</div> - -</div> - -</div> - -<div style="height: 20px"></div> - -</body> - -</html> \ No newline at end of file + <div style="height: 20px"></div> + </body> +</html> diff -r d86bacb600db -r c0efda325046 templates/workflow/editor.mako --- a/templates/workflow/editor.mako Thu Dec 18 09:32:43 2008 -0500 +++ b/templates/workflow/editor.mako Thu Dec 18 16:35:26 2008 -0500 @@ -344,6 +344,11 @@ padding-bottom: 0px; font-weight: bold; } + div.toolPanelLabel { + padding-top: 5px; + padding-bottom: 5px; + font-weight: bold; + } div.toolMenuGroupHeader { font-weight: bold; padding-top: 0.5em; @@ -353,7 +358,6 @@ border-bottom: dotted #333 1px; margin-bottom: 0.5em; } - div.toolTitle { padding-top: 5px; padding-bottom: 5px; @@ -361,6 +365,10 @@ margin-right: 10px; display: list-item; list-style: square outside; + } + div.toolTitleNoSection { + padding-bottom: 0px; + font-weight: bold; } div.toolTitleDisabled { padding-top: 5px; @@ -371,6 +379,11 @@ list-style: square outside; font-style: italic; color: gray; + } + div.toolTitleNoSectionDisabled { + padding-bottom: 0px; + font-style: italic; + color: gray; } div.toolFormRow { position: relative; @@ -467,6 +480,50 @@ </style> </%def> +## Render a tool in the tool panel +<%def name="render_tool( tool, section )"> + %if not tool.hidden: + %if tool.is_workflow_compatible: + %if section: + <div class="toolTitle"> + %else: + <div class="toolTitleNoSection"> + %endif + %if "[[" in tool.description and "]]" in tool.description: + ${tool.description.replace( '[[', '<a id="link-${tool.id}" href="javascript:add_node_for_tool( ${tool.id} )">' % tool.id ).replace( "]]", "</a>" )} + %elif tool.name: + <a id="link-${tool.id}" href="#" onclick="add_node_for_tool( '${tool.id}', '${tool.name}' )">${tool.name}</a> ${tool.description} + %else: + <a id="link-${tool.id}" href="#" onclick="add_node_for_tool( '${tool.id}', '${tool.name}' )">${tool.description}</a> + %endif + </div> + %else: + %if section: + <div class="toolTitleDisabled"> + %else: + <div class="toolTitleNoSectionDisabled"> + %endif + %if "[[" in tool.description and "]]" in tool.description: + ${tool.description.replace( '[[', '' % tool.id ).replace( "]]", "" )} + %elif tool.name: + ${tool.name} ${tool.description} + %else: + ${tool.description} + %endif + </div> + %endif + %endif +</%def> + +## Render a label in the tool panel +<%def name="render_label( label )"> + <div class="toolSectionPad"></div> + <div class="toolPanelLabel" id="title_${label.id}"> + <span>${label.text}</span> + </div> + <div class="toolSectionPad"></div> +</%def> + <div id="overlay"> ## Need a table here for centering in IE6 <table class="dialog-box-container" border="0" cellpadding="0" cellspacing="0"><tr><td> @@ -501,43 +558,30 @@ <div class="unified-panel-body" style="overflow: auto;"> <div class="toolMenu"> <div class="toolSectionList"> - %for i, section in enumerate( app.toolbox.sections ): - %if i > 0: - <div class="toolSectionPad"></div> - %endif - <div class="toolSectionTitle" id="title_${section.id}"> - <span>${section.name}</span> - </div> - <div id="${section.id}" class="toolSectionBody"> - <div class="toolSectionBg"> - %for tool in section.tools: - %if not tool.hidden: - %if tool.is_workflow_compatible: - <div class="toolTitle "> - %if "[[" in tool.description and "]]" in tool.description: - ${tool.description.replace( '[[', '<a id="link-${tool.id}" href="javascript:add_node_for_tool( ${tool.id} )">' % tool.id ).replace( "]]", "</a>" )} - %elif tool.name: - <a id="link-${tool.id}" href="#" onclick="add_node_for_tool( '${tool.id}', '${tool.name}' )">${tool.name}</a> ${tool.description} - %else: - <a id="link-${tool.id}" href="#" onclick="add_node_for_tool( '${tool.id}', '${tool.name}' )">${tool.description}</a> + %for key, val in app.toolbox.tool_panel.items(): + %if key.startswith( 'tool' ): + ${render_tool( val, False )} + %elif key.startswith( 'section' ): + <% section = val %> + <div class="toolSectionTitle" id="title_${section.id}"> + <span>${section.name}</span> + </div> + <div id="${section.id}" class="toolSectionBody"> + <div class="toolSectionBg"> + %for section_key, section_val in section.elems.items(): + %if section_key.startswith( 'tool' ): + ${render_tool( section_val, True )} + %elif section_key.startswith( 'label' ): + ${render_label( section_val )} %endif - </div> - %else: - <div class="toolTitleDisabled"> - %if "[[" in tool.description and "]]" in tool.description: - ${tool.description.replace( '[[', '' % tool.id ).replace( "]]", "" )} - %elif tool.name: - ${tool.name} ${tool.description} - %else: - ${tool.description} - %endif - </div> - %endif - %endif - %endfor - </div> - </div> - %endfor + %endfor + </div> + </div> + <div class="toolSectionPad"></div> + %elif key.startswith( 'label' ): + ${render_label( val )} + %endif + %endfor </div> <div> </div> <div class="toolMenuGroupHeader">Workflow control</div> diff -r d86bacb600db -r c0efda325046 test/functional/test_toolbox.py --- a/test/functional/test_toolbox.py Thu Dec 18 09:32:43 2008 -0500 +++ b/test/functional/test_toolbox.py Thu Dec 18 16:35:26 2008 -0500 @@ -1,5 +1,4 @@ -import sys -import new +import sys, new from galaxy.tools.parameters import grouping from galaxy.tools.parameters import basic from base.twilltestcase import TwillTestCase @@ -9,6 +8,7 @@ class ToolTestCase( TwillTestCase ): """Abstract test case that runs tests based on a `galaxy.tools.test.ToolTest`""" def do_it( self ): + print "###self.testdef: ", self.testdef # If the test generation had an error, raise if self.testdef.error: if self.testdef.exception: @@ -126,10 +126,10 @@ return # Push all the toolbox tests to module level G = globals() - for i, section in enumerate( toolbox.sections ): - for j, tool in enumerate( section.tools ): - if tool.tests: - for k, testdef in enumerate( tool.tests ): - name = "%s > %s > %s" % ( section.name, tool.name, testdef.name ) - testcase = get_testcase( testdef, name ) - G[ 'testcase_%d_%d_%d' % ( i, j, k ) ] = testcase + for i, tool_id in enumerate( toolbox.tools_by_id ): + tool = toolbox.tools_by_id[ tool_id ] + if tool.tests: + for j, testdef in enumerate( tool.tests ): + name = "%s ( %s ) > %s" % ( tool.name, tool.id, testdef.name ) + testcase = get_testcase( testdef, name ) + G[ 'testcase_%d_%d' % ( i, j ) ] = testcase diff -r d86bacb600db -r c0efda325046 tool_conf.xml.sample --- a/tool_conf.xml.sample Thu Dec 18 09:32:43 2008 -0500 +++ b/tool_conf.xml.sample Thu Dec 18 16:35:26 2008 -0500 @@ -2,7 +2,6 @@ <toolbox> <section name="Get Data" id="getext"> <tool file="data_source/upload.xml"/> - <tool file="data_source/access_libraries.xml" /> <tool file="data_source/ucsc_tablebrowser.xml" /> <tool file="data_source/ucsc_tablebrowser_test.xml" /> <tool file="data_source/ucsc_tablebrowser_archaea.xml" /> diff -r d86bacb600db -r c0efda325046 universe_wsgi.ini.sample --- a/universe_wsgi.ini.sample Thu Dec 18 09:32:43 2008 -0500 +++ b/universe_wsgi.ini.sample Thu Dec 18 16:35:26 2008 -0500 @@ -73,7 +73,6 @@ session_secret = changethisinproduction # Galaxy session security -# The value of id_secret MUST be the same as the value of id_secret in reports_wsgi.ini id_secret = changethisinproductiontoo # Use user provided in an upstream server's $REMOTE_USER variable
participants (1)
-
Greg Von Kuster