details: http://www.bx.psu.edu/hg/galaxy/rev/db4f8befcd89 changeset: 3722:db4f8befcd89 user: Greg Von Kuster <greg@bx.psu.edu> date: Fri Apr 30 14:08:23 2010 -0400 description: Many fixes and additional features added to the community. diffstat: lib/galaxy/webapps/community/controllers/admin.py | 374 +++++++++++-- lib/galaxy/webapps/community/controllers/common.py | 81 ++- lib/galaxy/webapps/community/controllers/tool.py | 293 ++++++++-- lib/galaxy/webapps/community/model/__init__.py | 7 +- lib/galaxy/webapps/community/model/mapping.py | 5 +- templates/webapps/community/admin/index.mako | 43 +- templates/webapps/community/category/edit_category.mako | 44 + templates/webapps/community/category/rename_category.mako | 44 - templates/webapps/community/index.mako | 62 ++- templates/webapps/community/tool/browse_tool.mako | 37 - templates/webapps/community/tool/edit_tool.mako | 2 +- templates/webapps/community/tool/view_tool.mako | 8 + 12 files changed, 733 insertions(+), 267 deletions(-) diffs (1467 lines): diff -r c642fbb301fc -r db4f8befcd89 lib/galaxy/webapps/community/controllers/admin.py --- a/lib/galaxy/webapps/community/controllers/admin.py Fri Apr 30 13:09:29 2010 -0400 +++ b/lib/galaxy/webapps/community/controllers/admin.py Fri Apr 30 14:08:23 2010 -0400 @@ -2,7 +2,7 @@ from galaxy.webapps.community import model from galaxy.model.orm import * from galaxy.web.framework.helpers import time_ago, iff, grids -from common import get_categories, get_category +from common import get_categories, get_category, get_tools, get_event, get_tool import logging log = logging.getLogger( __name__ ) @@ -200,7 +200,7 @@ return None def build_initial_query( self, session ): return session.query( self.model_class ) - def apply_default_filter( self, trans, query, **kwargs ): + def apply_default_filter( self, trans, query, **kwd ): return query.filter( model.Role.type != model.Role.types.PRIVATE ) class GroupListGrid( grids.Grid ): @@ -280,34 +280,31 @@ def build_initial_query( self, session ): return session.query( self.model_class ) -class CategoryListGrid( grids.Grid ): +class ManageCategoryListGrid( grids.Grid ): class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, category ): return category.name class DescriptionColumn( grids.TextColumn ): def get_value( self, trans, grid, category ): return category.description - class StatusColumn( grids.GridColumn ): - def get_value( self, trans, grid, category ): - if category.deleted: - return "deleted" - return "" # Grid definition webapp = "community" - title = "Categories" + title = "Manage Categories" model_class = model.Category template='/webapps/community/category/grid.mako' default_sort_key = "name" columns = [ NameColumn( "Name", key="name", - link=( lambda item: dict( operation="Edit category", id=item.id, webapp="community" ) ), + link=( lambda item: dict( operation="Edit", id=item.id, webapp="community" ) ), model_class=model.Category, - attach_popup=True, + attach_popup=False, filterable="advanced" ), - DescriptionColumn( "Description", attach_popup=False ), - StatusColumn( "Status", attach_popup=False ), + DescriptionColumn( "Description", + model_class=model.Category, + attach_popup=False, + filterable="advanced" ), # Columns that are valid for filtering but are not visible. grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) ] @@ -318,13 +315,9 @@ filterable="standard" ) ) global_actions = [ grids.GridAction( "Add new category", - dict( controller='admin', action='categories', operation='create', webapp="community" ) ) + dict( controller='admin', action='manage_categories', operation='create', webapp="community" ) ) ] - operations = [ grids.GridOperation( "Rename", - condition=( lambda item: not item.deleted ), - allow_multiple=False, - url_args=dict( webapp="community", action="rename_category" ) ), - grids.GridOperation( "Delete", + operations = [ grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), allow_multiple=True, url_args=dict( webapp="community", action="mark_category_deleted" ) ), @@ -349,16 +342,77 @@ def build_initial_query( self, session ): return session.query( self.model_class ) +class ToolsByCategoryListGrid( grids.Grid ): + class NameColumn( grids.TextColumn ): + def get_value( self, trans, grid, category ): + return category.name + class DescriptionColumn( grids.TextColumn ): + def get_value( self, trans, grid, category ): + return category.description + class ToolsColumn( grids.TextColumn ): + def get_value( self, trans, grid, category ): + if category.tools: + return len( category.tools ) + return 0 + + # Grid definition + webapp = "community" + title = "Tools by Category" + model_class = model.Category + template='/webapps/community/category/grid.mako' + default_sort_key = "name" + columns = [ + NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="Browse Category", id=item.id, webapp="community" ) ), + model_class=model.Category, + attach_popup=True, + filterable="advanced" ), + DescriptionColumn( "Description", + model_class=model.Category, + attach_popup=False, + filterable="advanced" ), + ToolsColumn( "Tools", + model_class=model.Category, + attach_popup=False, + filterable="advanced" ), + # Columns that are valid for filtering but are not visible. + grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) + ] + columns.append( grids.MulticolFilterColumn( "Search", + cols_to_filter=[ columns[0], columns[1], columns[2] ], + key="free-text-search", + visible=False, + filterable="standard" ) ) + standard_filters = [ + grids.GridColumnFilter( "Active", args=dict( deleted=False ) ), + grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ), + grids.GridColumnFilter( "All", args=dict( deleted='All' ) ) + ] + num_rows_per_page = 50 + preserve_state = False + use_paging = True + def get_current_item( self, trans ): + return None + def build_initial_query( self, session ): + return session.query( self.model_class ) + class ToolListGrid( grids.Grid ): class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, tool ): return tool.name + class VersionColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return tool.version + class DescriptionColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return tool.description class CategoryColumn( grids.TextColumn ): def get_value( self, trans, grid, tool ): if tool.categories: rval = '' for tca in tool.categories: - rval = '%s%s<br/>' % ( rval, tca.category.name ) + rval += '<a href="browse_category?id=%s">%s</a><br/>\n' % ( trans.security.encode_id( tca.category.id ), tca.category.name ) return rval return 'not set' class StateColumn( grids.GridColumn ): @@ -389,7 +443,7 @@ return accepted_filters class UserColumn( grids.TextColumn ): def get_value( self, trans, grid, tool ): - return tool.user.email + return '<a href="browse_tools_by_user?operation=browse&id=%s">%s</a>' % ( trans.security.encode_id( tool.user.id ), tool.user.username ) # Grid definition title = "Tools" model_class = model.Tool @@ -402,27 +456,34 @@ link=( lambda item: dict( operation="View Tool", id=item.id, cntrller='admin', webapp="community" ) ), attach_popup=True, filterable="advanced" ), + VersionColumn( "Version", + model_class=model.Tool, + attach_popup=False, + filterable="advanced" ), + DescriptionColumn( "Description", + model_class=model.Tool, + attach_popup=False, + filterable="advanced" ), CategoryColumn( "Category", - key="category", model_class=model.Category, attach_popup=False, filterable="advanced" ), - StateColumn( "State", - key="state", + StateColumn( "Status", model_class=model.Event, - attach_popup=False, - filterable="advanced" ), + attach_popup=False ), + UserColumn( "Uploaded By", + key="username", + model_class=model.User, + attach_popup=False, + filterable="advanced" ), # Columns that are valid for filtering but are not visible. - grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) + grids.DeletedColumn( "Deleted", model_class=model.Tool, key="deleted", visible=False, filterable="advanced" ) ] columns.append( grids.MulticolFilterColumn( "Search", cols_to_filter=[ columns[0], columns[1] ], key="free-text-search", visible=False, filterable="standard" ) ) - global_actions = [ - grids.GridAction( "Upload tool", dict( controller='upload', action='upload', type='tool' ) ) - ] operations = [ grids.GridOperation( "Edit information", condition=( lambda item: not item.deleted ), @@ -443,57 +504,156 @@ use_paging = True def build_initial_query( self, session ): return session.query( self.model_class ) - def apply_default_filter( self, trans, query, **kwargs ): + def apply_default_filter( self, trans, query, **kwd ): + tool_id = kwd.get( 'tool_id', False ) + if tool_id: + if str( tool_id ).lower() in [ '', 'none' ]: + # Return an empty query since the current user cannot view any + # tools (possibly due to state not being approved, etc). + return query.filter( model.Tool.id == None ) + tool_id = util.listify( tool_id ) + query = query.filter( or_( *map( lambda id: self.model_class.id == id, tool_id ) ) ) return query.filter( self.model_class.deleted==False ) -class AdminCommunity( BaseController, Admin ): +class AdminController( BaseController, Admin ): user_list_grid = UserListGrid() role_list_grid = RoleListGrid() group_list_grid = GroupListGrid() - category_list_grid = CategoryListGrid() + manage_category_list_grid = ManageCategoryListGrid() + tools_by_category_list_grid = ToolsByCategoryListGrid() tool_list_grid = ToolListGrid() @web.expose @web.require_admin - def browse_tools( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() + def browse_tools( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "edit tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='edit_tool', + cntrller='admin', + **kwd ) ) + elif operation == "view tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='view_tool', + cntrller='admin', + **kwd ) ) + # Render the list view + return self.tool_list_grid( trans, **kwd ) + @web.expose + @web.require_admin + def browse_tools_by_category( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "browse category": + return self.browse_category( trans, id=kwd['id'] ) + # Render the list view + return self.tools_by_category_list_grid( trans, **kwd ) + @web.expose + @web.require_admin + def browse_tools_by_user( self, trans, **kwd ): + # TODO: move this to the common controller as it is in the tool controller as well... + if 'operation' in kwd: + operation = kwd['operation'].lower() if operation == "browse": - return trans.response.send_redirect( web.url_for( controller='tool', - action='browse_tools', + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_tools_by_user', cntrller='admin', - **kwargs ) ) + **kwd ) ) + elif operation == "browse category": + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_category', + cntrller='admin', + **kwd ) ) + elif operation == "view tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='view_tool', + cntrller='admin', + **kwd ) ) elif operation == "edit tool": return trans.response.send_redirect( web.url_for( controller='common', action='edit_tool', cntrller='admin', - **kwargs ) ) + **kwd ) ) + elif operation == "download tool": + return trans.response.send_redirect( web.url_for( controller='tool', + action='download_tool', + **kwd ) ) + @web.expose + @web.require_admin + def browse_tools_by_user( self, trans, **kwd ): + # TODO: move this to the common controller as it is in the tool controller as well... + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "browse": + return trans.response.send_redirect( web.url_for( controller='admin', + action='browse_tools_by_user', + **kwd ) ) + elif operation == "browse category": + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_category', + cntrller='admin', + **kwd ) ) elif operation == "view tool": return trans.response.send_redirect( web.url_for( controller='common', action='view_tool', cntrller='admin', - **kwargs ) ) - # Render the list view - return self.tool_list_grid( trans, **kwargs ) + **kwd ) ) + elif operation == "edit tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='edit_tool', + cntrller='admin', + **kwd ) ) + elif operation == "download tool": + return trans.response.send_redirect( web.url_for( controller='tool', + action='download_tool', + **kwd ) ) @web.expose @web.require_admin - def categories( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() + def manage_categories( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() if operation == "create": - return self.create_category( trans, **kwargs ) + return self.create_category( trans, **kwd ) if operation == "delete": - return self.mark_category_deleted( trans, **kwargs ) + return self.mark_category_deleted( trans, **kwd ) if operation == "undelete": - return self.undelete_category( trans, **kwargs ) + return self.undelete_category( trans, **kwd ) if operation == "purge": - return self.purge_category( trans, **kwargs ) - if operation == "rename": - return self.rename_category( trans, **kwargs ) + return self.purge_category( trans, **kwd ) + if operation == "edit": + return self.edit_category( trans, **kwd ) # Render the list view - return self.category_list_grid( trans, **kwargs ) - + return self.manage_category_list_grid( trans, **kwd ) + @web.expose + @web.require_admin + def browse_tools_by_state( self, trans, state=None, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + if state is None: + id = params.get( 'id', None ) + if not id: + return trans.response.send_redirect( web.url_for( controller=cntrller, + action='browse_tools', + message='Select a status', + status='error' ) ) + event = get_event( trans, id ) + state = event.state + tool_id = get_tools_by_state( trans, state ) + if not tool_id: + tool_id = 'None' + return trans.response.send_redirect( web.url_for( controller='admin', + action='browse_tools', + tool_id=tool_id ) ) + @web.expose + @web.require_admin + def browse_category( self, trans, **kwd ): + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_category', + cntrller='admin', + **kwd ) ) @web.expose @web.require_admin def create_category( self, trans, **kwd ): @@ -515,7 +675,7 @@ message = "Category '%s' has been created" % category.name trans.sa_session.flush() trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='done' ) ) @@ -530,42 +690,69 @@ status=status ) @web.expose @web.require_admin - def rename_category( self, trans, **kwd ): + def set_tool_state( self, trans, state, **kwd ): params = util.Params( kwd ) webapp = params.get( 'webapp', 'galaxy' ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) id = params.get( 'id', None ) if not id: - message = "No category ids received for renaming" + message = "No tool id received for setting status" + status = 'error' + else: + tool = get_tool( trans, id ) + event = trans.model.Event( state ) + # Flush so we an get an id + trans.sa_session.add( event ) + trans.sa_session.flush() + tea = trans.model.ToolEventAssociation( tool, event ) + trans.sa_session.add( tea ) + trans.sa_session.flush() + message = "State of tool '%s' is now %s" % ( tool.name, state ) + trans.response.send_redirect( web.url_for( controller='admin', + action='browse_tools', + webapp=webapp, + message=message, + status=status ) ) + @web.expose + @web.require_admin + def edit_category( self, trans, **kwd ): + params = util.Params( kwd ) + webapp = params.get( 'webapp', 'galaxy' ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + message = "No category ids received for editing" trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=message, status='error' ) ) category = get_category( trans, id ) - if params.get( 'rename_category_button', False ): + if params.get( 'edit_category_button', False ): old_name = category.name new_name = util.restore_text( params.name ) new_description = util.restore_text( params.description ) - if not new_name: - message = 'Enter a valid name' - status = 'error' - elif trans.sa_session.query( trans.app.model.Category ).filter( trans.app.model.Category.table.c.name==new_name ).first(): - message = 'A category with that name already exists' - status = 'error' + if old_name != new_name: + if not new_name: + message = 'Enter a valid name' + status = 'error' + elif trans.sa_session.query( trans.app.model.Category ).filter( trans.app.model.Category.table.c.name==new_name ).first(): + message = 'A category with that name already exists' + status = 'error' else: category.name = new_name category.description = new_description trans.sa_session.add( category ) trans.sa_session.flush() - message = "Category '%s' has been renamed to '%s'" % ( old_name, new_name ) + message = "The information has been saved for category '%s'" % ( new_name ) return trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='done' ) ) - return trans.fill_template( '/webapps/community/category/rename_category.mako', + return trans.fill_template( '/webapps/community/category/edit_category.mako', category=category, webapp=webapp, message=message, @@ -579,7 +766,7 @@ if not id: message = "No category ids received for deleting" trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=message, status='error' ) ) @@ -592,7 +779,7 @@ trans.sa_session.flush() message += " %s " % category.name trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='done' ) ) @@ -605,7 +792,7 @@ if not id: message = "No category ids received for undeleting" trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=message, status='error' ) ) @@ -617,7 +804,7 @@ if not category.deleted: message = "Category '%s' has not been deleted, so it cannot be undeleted." % category.name trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='error' ) ) @@ -628,7 +815,7 @@ undeleted_categories += " %s" % category.name message = "Undeleted %d categories: %s" % ( count, undeleted_categories ) trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='done' ) ) @@ -644,7 +831,7 @@ if not id: message = "No category ids received for purging" trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='error' ) ) @@ -655,7 +842,7 @@ if not category.deleted: message = "Category '%s' has not been deleted, so it cannot be purged." % category.name trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='error' ) ) @@ -665,7 +852,42 @@ trans.sa_session.flush() message += " %s " % category.name trans.response.send_redirect( web.url_for( controller='admin', - action='categories', + action='manage_categories', webapp=webapp, message=util.sanitize_text( message ), status='done' ) ) + +## ---- Utility methods ------------------------------------------------------- + +def get_tools_by_state( trans, state ): + # TODO: this can be written so that it is much cleaner and faster + tool_id = [] + if state == trans.model.Tool.states.NEW: + for tool in get_tools( trans ): + if tool.is_new(): + tool_id.append( tool.id ) + elif state == trans.model.Tool.states.ERROR: + for tool in get_tools( trans ): + if tool.is_error(): + tool_id.append( tool.id ) + elif state == trans.model.Tool.states.DELETED: + for tool in get_tools( trans ): + if tool.is_deleted(): + tool_id.append( tool.id ) + elif state == trans.model.Tool.states.WAITING: + for tool in get_tools( trans ): + if tool.is_waiting(): + tool_id.append( tool.id ) + elif state == trans.model.Tool.states.APPROVED: + for tool in get_tools( trans ): + if tool.is_approved(): + tool_id.append( tool.id ) + elif state == trans.model.Tool.states.REJECTED: + for tool in get_tools( trans ): + if tool.is_rejected(): + tool_id.append( tool.id ) + elif state == trans.model.Tool.states.ARCHIVED: + for tool in get_tools( trans ): + if tool.is_archived(): + tool_id.append( tool.id ) + return tool_id diff -r c642fbb301fc -r db4f8befcd89 lib/galaxy/webapps/community/controllers/common.py --- a/lib/galaxy/webapps/community/controllers/common.py Fri Apr 30 13:09:29 2010 -0400 +++ b/lib/galaxy/webapps/community/controllers/common.py Fri Apr 30 14:08:23 2010 -0400 @@ -8,7 +8,7 @@ import logging log = logging.getLogger( __name__ ) -class CommunityCommon( BaseController ): +class CommonController( BaseController ): @web.expose def edit_tool( self, trans, cntrller, **kwd ): params = util.Params( kwd ) @@ -108,6 +108,54 @@ action='browse_tools', message='Not yet implemented, sorry...', status='error' ) ) + @web.expose + def browse_category( self, trans, cntrller, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + return trans.response.send_redirect( web.url_for( controller=cntrller, + action='browse_categories', + message='Select a category', + status='error' ) ) + category = get_category( trans, id ) + # If request came from the tool controller, then we need to filter by the state of the + # tool in addition to the category. + if cntrller == 'tool': + tool_id = get_approved_tools( trans, category=category ) + else: + # If request came from the admin controller, we don't filter on tool state. + tool_id = [ tca.tool.id for tca in category.tools ] + if not tool_id: + tool_id = 'None' + return trans.response.send_redirect( web.url_for( controller=cntrller, + action='browse_tools', + tool_id=tool_id ) ) + @web.expose + def browse_tools_by_user( self, trans, cntrller, **kwd ): + params = util.Params( kwd ) + message = util.restore_text( params.get( 'message', '' ) ) + status = params.get( 'status', 'done' ) + id = params.get( 'id', None ) + if not id: + return trans.response.send_redirect( web.url_for( controller=cntrller, + action='browse_tools', + message='Select a user', + status='error' ) ) + user = get_user( trans, id ) + # If request came from the tool controller, then we need to filter by the state of the + # tool if the user is not viewing his own tools + if cntrller == 'tool': + tool_id = get_approved_tools( trans, user=user ) + else: + # If request came from the admin controller, we don't filter on tool state. + tool_id = [ tool.id for tool in user.tools ] + if not tool_id: + tool_id = 'None' + return trans.response.send_redirect( web.url_for( controller=cntrller, + action='browse_tools_by_user', + tool_id=tool_id ) ) ## ---- Utility methods ------------------------------------------------------- @@ -142,4 +190,33 @@ obj.categories.append( trans.model.ToolCategoryAssociation( obj, category ) ) def get_tool( trans, id ): return trans.sa_session.query( trans.model.Tool ).get( trans.app.security.decode_id( id ) ) - +def get_tools( trans ): + return trans.sa_session.query( trans.model.Tool ).order_by( trans.model.Tool.name ) +def get_approved_tools( trans, category=None, user=None ): + tool_id = [] + if category: + # Return only the approved tools in the category + for tca in category.tools: + tool = tca.tool + if tool.is_approved(): + tool_id.append( tool.id ) + elif user: + if trans.user == user: + # If the current user is browsing his own tools, then don't filter on state + tool_id = [ tool.id for tool in user.tools ] + else: + # The current user is viewing all tools uploaded by another user, so show only + # approved tools + for tool in user.active_tools: + if tool.is_approved(): + tool_id.append( tool.id ) + else: + # Return all approved tools + for tool in get_tools( trans ): + if tool.is_approved(): + tool_id.append( tool.id ) + return tool_id +def get_event( trans, id ): + return trans.sa_session.query( trans.model.Event ).get( trans.security.decode_id( id ) ) +def get_user( trans, id ): + return trans.sa_session.query( trans.model.User ).get( trans.security.decode_id( id ) ) diff -r c642fbb301fc -r db4f8befcd89 lib/galaxy/webapps/community/controllers/tool.py --- a/lib/galaxy/webapps/community/controllers/tool.py Fri Apr 30 13:09:29 2010 -0400 +++ b/lib/galaxy/webapps/community/controllers/tool.py Fri Apr 30 14:08:23 2010 -0400 @@ -15,38 +15,111 @@ class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, tool ): return tool.name + class VersionColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return tool.version + class DescriptionColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return tool.description class CategoryColumn( grids.TextColumn ): def get_value( self, trans, grid, tool ): if tool.categories: rval = '' for tca in tool.categories: - rval += '%s<br/>\n' % tca.category.name + rval += '<a href="browse_category?id=%s">%s</a><br/>\n' % ( trans.security.encode_id( tca.category.id ), tca.category.name ) return rval return 'not set' - def filter( self, trans, user, query, column_filter ): - # Category.name conflicts with Tool.name, so we have to make our own filter - def get_single_filter( filter ): - return func.lower( model.Category.name ).like( "%" + filter.lower() + "%" ) - if column_filter == 'All': - pass - elif isinstance( column_filter, list ): - clause_list = [] - for filter in column_filter: - clause_list.append( get_single_filter( filter ) ) - query = query.filter( or_( *clause_list ) ) - else: - query = query.filter( get_single_filter( column_filter ) ) - return query - def get_link( self, trans, grid, tool, filter_params ): + class UserColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return '<a href="browse_tools_by_user?operation=browse&id=%s">%s</a>' % ( trans.security.encode_id( tool.user.id ), tool.user.username ) + # Grid definition + title = "Tools" + model_class = model.Tool + template='/webapps/community/tool/grid.mako' + default_sort_key = "name" + columns = [ + NameColumn( "Name", + key="name", + model_class=model.Tool, + link=( lambda item: dict( operation="View Tool", id=item.id, cntrller='tool', webapp="community" ) ), + attach_popup=True, + filterable="advanced" ), + VersionColumn( "Version", + model_class=model.Tool, + attach_popup=False, + filterable="advanced" ), + DescriptionColumn( "Description", + model_class=model.Tool, + attach_popup=False, + filterable="advanced" ), + CategoryColumn( "Categories", + model_class=model.Category, + attach_popup=False, + filterable="advanced" ), + UserColumn( "Uploaded By", + key="username", + model_class=model.User, + attach_popup=False, + filterable="advanced" ), + # Columns that are valid for filtering but are not visible. + grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) + ] + columns.append( grids.MulticolFilterColumn( "Search", + cols_to_filter=[ columns[0], columns[1] ], + key="free-text-search", + visible=False, + filterable="standard" ) ) + operations = [ + grids.GridOperation( "Download tool", + condition=( lambda item: not item.deleted ), + allow_multiple=False, + url_args=dict( controller="tool", action="download_tool", cntrller="tool", webapp="community" ) ) + ] + standard_filters = [ + grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ), + grids.GridColumnFilter( "All", args=dict( deleted='All' ) ) + ] + default_filter = dict( name="All", deleted="False", username="All" ) + num_rows_per_page = 50 + preserve_state = False + use_paging = True + def build_initial_query( self, session ): + return session.query( self.model_class ) + def apply_default_filter( self, trans, query, **kwd ): + def filter_query( query, tool_id ): + if str( tool_id ).lower() in [ '', 'none' ]: + # Return an empty query since the current user cannot view any + # tools (possibly due to state not being approved, etc). + return query.filter( model.Tool.id == None ) + tool_id = util.listify( tool_id ) + query = query.filter( or_( *map( lambda id: self.model_class.id == id, tool_id ) ) ) + return query.filter( self.model_class.deleted==False ) + tool_id = kwd.get( 'tool_id', False ) + if not tool_id: + # Display only approved tools + tool_id = get_approved_tools( trans ) + if not tool_id: + tool_id = 'None' + return filter_query( query, tool_id ) + +class ToolsByUserListGrid( grids.Grid ): + class NameColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return tool.name + class VersionColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return tool.version + class DescriptionColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): + return tool.description + class CategoryColumn( grids.TextColumn ): + def get_value( self, trans, grid, tool ): if tool.categories: - filter_params['f-category'] = [] + rval = '' for tca in tool.categories: - filter_params['f-category'].append( tca.category.name ) - if len( filter_params['f-category'] ) == 1: - filter_params['f-category'] = filter_params['f-category'][0] - filter_params['advanced-search'] = 'True' - return filter_params - return None + rval += '<a href="browse_category?id=%s">%s</a><br/>\n' % ( trans.security.encode_id( tca.category.id ), tca.category.name ) + return rval + return 'not set' class StateColumn( grids.GridColumn ): def get_value( self, trans, grid, tool ): state = tool.state() @@ -75,13 +148,9 @@ return accepted_filters class UserColumn( grids.TextColumn ): def get_value( self, trans, grid, tool ): - return tool.user.username - def get_link( self, trans, grid, tool, filter_params ): - filter_params['f-username'] = tool.user.username - filter_params['advanced-search'] = 'True' - return filter_params + return '<a href="browse_tools_by_user?operation=browse&id=%s">%s</a>' % ( trans.security.encode_id( tool.user.id ), tool.user.username ) # Grid definition - title = "Tools" + title = "Tools By User" model_class = model.Tool template='/webapps/community/tool/grid.mako' default_sort_key = "name" @@ -92,21 +161,26 @@ link=( lambda item: dict( operation="View Tool", id=item.id, cntrller='tool', webapp="community" ) ), attach_popup=True, filterable="advanced" ), - CategoryColumn( "Categories", - key="category", + VersionColumn( "Version", model_class=model.Tool, attach_popup=False, filterable="advanced" ), + DescriptionColumn( "Description", + model_class=model.Tool, + attach_popup=False, + filterable="advanced" ), + CategoryColumn( "Categories", + model_class=model.Category, + attach_popup=False, + filterable="advanced" ), + StateColumn( "Status", + model_class=model.Event, + attach_popup=False ), UserColumn( "Uploaded By", key="username", model_class=model.User, attach_popup=False, filterable="advanced" ), - StateColumn( "State", - key="state", - model_class=model.Event, - attach_popup=False, - filterable="advanced" ), # Columns that are valid for filtering but are not visible. grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) ] @@ -130,18 +204,44 @@ preserve_state = False use_paging = True def build_initial_query( self, session ): - return session.query( self.model_class ).outerjoin( model.ToolCategoryAssociation ).outerjoin( model.Category ) - def apply_default_filter( self, trans, query, **kwargs ): - return query.filter( self.model_class.deleted==False ) + return session.query( self.model_class ) + def apply_default_filter( self, trans, query, **kwd ): + def filter_query( query, tool_id ): + if str( tool_id ).lower() in [ '', 'none' ]: + # Return an empty query since the current user cannot view any + # tools (possibly due to state not being approved, etc). + return query.filter( model.Tool.id == None ) + tool_id = util.listify( tool_id ) + query = query.filter( or_( *map( lambda id: self.model_class.id == id, tool_id ) ) ) + return query.filter( self.model_class.deleted==False ) + tool_id = kwd.get( 'tool_id', False ) + if not tool_id: + # Display only approved tools + tool_id = get_approved_tools( trans ) + if not tool_id: + tool_id = 'None' + return filter_query( query, tool_id ) -class ToolCategoryListGrid( grids.Grid ): +class CategoryListGrid( grids.Grid ): class NameColumn( grids.TextColumn ): def get_value( self, trans, grid, category ): return category.name class DescriptionColumn( grids.TextColumn ): def get_value( self, trans, grid, category ): return category.description + class ToolsColumn( grids.TextColumn ): + def get_value( self, trans, grid, category ): + if category.tools: + viewable_tools = 0 + for tca in category.tools: + tool = tca.tool + if tool.is_approved(): + viewable_tools += 1 + return viewable_tools + return 0 + # Grid definition + webapp = "community" title = "Tool Categories" model_class = model.Category template='/webapps/community/category/grid.mako' @@ -157,7 +257,13 @@ key="description", model_class=model.Category, attach_popup=False, - filterable="advanced" ) + filterable="advanced" ), + ToolsColumn( "Tools", + model_class=model.Tool, + attach_popup=False, + filterable="advanced" ), + # Columns that are valid for filtering but are not visible. + grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ) ] columns.append( grids.MulticolFilterColumn( "Search", cols_to_filter=[ columns[0], columns[1] ], @@ -165,21 +271,23 @@ visible=False, filterable="standard" ) ) standard_filters = [ + grids.GridColumnFilter( "Active", args=dict( deleted=False ) ), + grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ), grids.GridColumnFilter( "All", args=dict( deleted='All' ) ) ] - default_filter = dict( name="All", deleted="False" ) num_rows_per_page = 50 preserve_state = False use_paging = True def build_initial_query( self, session ): return session.query( self.model_class ) - def apply_default_filter( self, trans, query, **kwargs ): + def apply_default_filter( self, trans, query, **kwd ): return query.filter( self.model_class.deleted==False ) -class ToolBrowserController( BaseController ): - - tool_category_list_grid = ToolCategoryListGrid() +class ToolController( BaseController ): + tool_list_grid = ToolListGrid() + tools_by_user_list_grid = ToolsByUserListGrid() + category_list_grid = CategoryListGrid() @web.expose def index( self, trans, **kwd ): @@ -188,53 +296,84 @@ status = params.get( 'status', 'done' ) return trans.fill_template( '/webapps/community/index.mako', message=message, status=status ) @web.expose - def browse_tool_categories( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() + def browse_categories( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() if operation == "browse category": - category_id = int( trans.app.security.decode_id( kwargs['id'] ) ) - category = trans.sa_session.query( model.Category ).get( category_id ) - del kwargs['id'] - del kwargs['operation'] - kwargs['f-category'] = category.name - return trans.response.send_redirect( web.url_for( controller='tool', - action='browse_tools', - **kwargs ) ) - return self.tool_category_list_grid( trans, **kwargs ) + return self.browse_category( trans, id=kwd['id'] ) + elif operation == "view tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='view_category', + cntrller='tool', + **kwd ) ) + elif operation == "edit tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='edit_category', + cntrller='tool', + **kwd ) ) + # Render the list view + return self.category_list_grid( trans, **kwd ) @web.expose - def browse_tools( self, trans, **kwargs ): - if 'operation' in kwargs: - operation = kwargs['operation'].lower() - if operation == "browse": - return trans.response.send_redirect( web.url_for( controller='tool', - action='browse_tool', + def browse_category( self, trans, **kwd ): + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_category', + cntrller='tool', + **kwd ) ) + @web.expose + def browse_tools( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "browse category": + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_category', cntrller='tool', - **kwargs ) ) + **kwd ) ) elif operation == "view tool": return trans.response.send_redirect( web.url_for( controller='common', action='view_tool', cntrller='tool', - **kwargs ) ) + **kwd ) ) elif operation == "edit tool": return trans.response.send_redirect( web.url_for( controller='common', action='edit_tool', cntrller='tool', - **kwargs ) ) + **kwd ) ) elif operation == "download tool": return trans.response.send_redirect( web.url_for( controller='tool', action='download_tool', - **kwargs ) ) + **kwd ) ) # Render the list view - return self.tool_list_grid( trans, **kwargs ) + return self.tool_list_grid( trans, **kwd ) @web.expose - def browse_tool( self, trans, **kwd ): - params = util.Params( kwd ) - message = util.restore_text( params.get( 'message', '' ) ) - status = params.get( 'status', 'done' ) - return trans.fill_template( '/webapps/community/tool/browse_tool.mako', - tools=tools, - message=message, - status=status ) + def browse_tools_by_user( self, trans, **kwd ): + if 'operation' in kwd: + operation = kwd['operation'].lower() + if operation == "browse": + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_tools_by_user', + cntrller='tool', + **kwd ) ) + elif operation == "browse category": + return trans.response.send_redirect( web.url_for( controller='common', + action='browse_category', + cntrller='tool', + **kwd ) ) + elif operation == "view tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='view_tool', + cntrller='tool', + **kwd ) ) + elif operation == "edit tool": + return trans.response.send_redirect( web.url_for( controller='common', + action='edit_tool', + cntrller='tool', + **kwd ) ) + elif operation == "download tool": + return trans.response.send_redirect( web.url_for( controller='tool', + action='download_tool', + **kwd ) ) + # Render the list view + return self.tools_by_user_list_grid( trans, **kwd ) @web.expose def download_tool( self, trans, **kwd ): params = util.Params( kwd ) diff -r c642fbb301fc -r db4f8befcd89 lib/galaxy/webapps/community/model/__init__.py --- a/lib/galaxy/webapps/community/model/__init__.py Fri Apr 30 13:09:29 2010 -0400 +++ b/lib/galaxy/webapps/community/model/__init__.py Fri Apr 30 14:08:23 2010 -0400 @@ -92,7 +92,8 @@ DELETED = 'deleted', WAITING = 'waiting for approval', APPROVED = 'approved', - REJECTED = 'rejected' ) + REJECTED = 'rejected', + ARCHIVED = 'archived' ) def __init__( self, guid=None, tool_id=None, name=None, description=None, user_description=None, category=None, version=None, user_id=None, external_filename=None ): self.guid = guid self.tool_id = tool_id @@ -153,10 +154,14 @@ return self.state() == self.states.ERROR def is_deleted( self ): return self.state() == self.states.DELETED + def is_waiting( self ): + return self.state() == self.states.WAITING def is_approved( self ): return self.state() == self.states.APPROVED def is_rejected( self ): return self.state() == self.states.REJECTED + def is_archived( self ): + return self.state() == self.states.ARCHIVED @property def extension( self ): # if instantiated via a query, this unmapped property won't exist diff -r c642fbb301fc -r db4f8befcd89 lib/galaxy/webapps/community/model/mapping.py --- a/lib/galaxy/webapps/community/model/mapping.py Fri Apr 30 13:09:29 2010 -0400 +++ b/lib/galaxy/webapps/community/model/mapping.py Fri Apr 30 14:08:23 2010 -0400 @@ -164,8 +164,8 @@ # With the tables defined we can define the mappers and setup the # relationships between the model objects. assign_mapper( context, User, User.table, - properties=dict( tools=relation( Tool, order_by=desc( Tool.table.c.update_time ) ), - active_tools=relation( Tool, primaryjoin=( ( Tool.table.c.user_id == User.table.c.id ) & ( not_( Tool.table.c.deleted ) ) ), order_by=desc( Tool.table.c.update_time ) ), + properties=dict( tools=relation( Tool, primaryjoin=( Tool.table.c.user_id == User.table.c.id ), order_by=( Tool.table.c.name ) ), + active_tools=relation( Tool, primaryjoin=( ( Tool.table.c.user_id == User.table.c.id ) & ( not_( Tool.table.c.deleted ) ) ), order_by=( Tool.table.c.name ) ), galaxy_sessions=relation( GalaxySession, order_by=desc( GalaxySession.table.c.update_time ) ) ) ) assign_mapper( context, Group, Group.table, @@ -238,7 +238,6 @@ ) ) - def guess_dialect_for_url( url ): return (url.split(':', 1))[0] diff -r c642fbb301fc -r db4f8befcd89 templates/webapps/community/admin/index.mako --- a/templates/webapps/community/admin/index.mako Fri Apr 30 13:09:29 2010 -0400 +++ b/templates/webapps/community/admin/index.mako Fri Apr 30 14:08:23 2010 -0400 @@ -54,7 +54,6 @@ </style> </%def> - <%def name="init()"> <% self.has_left_panel=True @@ -71,32 +70,34 @@ <div class="toolMenu"> <div class="toolSectionList"> <div class="toolSectionTitle"> + <span>Tools</span> + </div> + <div class="toolSectionBody"> + <div class="toolSectionBg"> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_tools_by_state', state=trans.model.Tool.states.WAITING, webapp='community' )}">Tools awaiting approval</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_tools_by_category' )}">Browse by category</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='browse_tools', webapp='community' )}">Browse all tools</a></div> + </div> + </div> + <div class="toolSectionPad"></div> + <div class="toolSectionTitle"> + <span>Categories</span> + </div> + <div class="toolSectionBody"> + <div class="toolSectionBg"> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='manage_categories', webapp='community' )}">Manage categories</a></div> + </div> + </div> + <div class="toolSectionTitle"> <span>Security</span> </div> <div class="toolSectionBody"> <div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='users', webapp='community' )}" target="galaxy_main">Manage users</a></div> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='groups', webapp='community' )}" target="galaxy_main">Manage groups</a></div> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='roles', webapp='community' )}" target="galaxy_main">Manage roles</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='users', webapp='community' )}">Manage users</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='groups', webapp='community' )}">Manage groups</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='roles', webapp='community' )}">Manage roles</a></div> </div> </div> - <div class="toolSectionTitle"> - <span>Tools</span> - </div> - <div class="toolSectionBody"> - <div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_tools', webapp='community' )}" target="galaxy_main">Manage tools</a></div> - </div> - </div> - <div class="toolSectionPad"></div> - <div class="toolSectionTitle"> - <span>Community</span> - </div> - <div class="toolSectionBody"> - <div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='admin', action='categories', webapp='community' )}" target="galaxy_main">Manage categories</a></div> - </div> - </div> </div> </div> </div> diff -r c642fbb301fc -r db4f8befcd89 templates/webapps/community/category/edit_category.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/webapps/community/category/edit_category.mako Fri Apr 30 14:08:23 2010 -0400 @@ -0,0 +1,44 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +%if message: + ${render_msg( message, status )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">Change category name and description</div> + <div class="toolFormBody"> + <form name="library" action="${h.url_for( controller='admin', action='edit_category' )}" method="post" > + <div class="form-row"> + <input name="webapp" type="hidden" value="${webapp}" size=40"/> + <label>Name:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="name" value="${category.name}" size="40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Description:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input name="description" type="textfield" value="${category.description}" size=40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="hidden" name="rename" value="submitted"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="hidden" name="id" value="${trans.security.encode_id( category.id )}"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <input type="submit" name="edit_category_button" value="Save"/> + </div> + </form> + </div> +</div> diff -r c642fbb301fc -r db4f8befcd89 templates/webapps/community/category/rename_category.mako --- a/templates/webapps/community/category/rename_category.mako Fri Apr 30 13:09:29 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="/message.mako" import="render_msg" /> - -%if message: - ${render_msg( message, status )} -%endif - -<div class="toolForm"> - <div class="toolFormTitle">Change category name and description</div> - <div class="toolFormBody"> - <form name="library" action="${h.url_for( controller='admin', action='rename_category' )}" method="post" > - <div class="form-row"> - <input name="webapp" type="hidden" value="${webapp}" size=40"/> - <label>Name:</label> - <div style="float: left; width: 250px; margin-right: 10px;"> - <input type="text" name="name" value="${category.name}" size="40"/> - </div> - <div style="clear: both"></div> - </div> - <div class="form-row"> - <label>Description:</label> - <div style="float: left; width: 250px; margin-right: 10px;"> - <input name="description" type="textfield" value="${category.description}" size=40"/> - </div> - <div style="clear: both"></div> - </div> - <div class="form-row"> - <div style="float: left; width: 250px; margin-right: 10px;"> - <input type="hidden" name="rename" value="submitted"/> - </div> - <div style="clear: both"></div> - </div> - <div class="form-row"> - <div style="float: left; width: 250px; margin-right: 10px;"> - <input type="hidden" name="id" value="${trans.security.encode_id( category.id )}"/> - </div> - <div style="clear: both"></div> - </div> - <div class="form-row"> - <input type="submit" name="rename_category_button" value="Save"/> - </div> - </form> - </div> -</div> diff -r c642fbb301fc -r db4f8befcd89 templates/webapps/community/index.mako --- a/templates/webapps/community/index.mako Fri Apr 30 13:09:29 2010 -0400 +++ b/templates/webapps/community/index.mako Fri Apr 30 14:08:23 2010 -0400 @@ -1,6 +1,57 @@ <%inherit file="/webapps/community/base_panels.mako"/> <%namespace file="/message.mako" import="render_msg" /> +<%def name="stylesheets()"> + ${parent.stylesheets()} + ## TODO: Clean up these styles and move into panel_layout.css (they are + ## used here and in the editor). + <style type="text/css"> + #left { + background: #C1C9E5 url(${h.url_for('/static/style/menu_bg.png')}) top repeat-x; + } + div.toolMenu { + margin: 5px; + margin-left: 10px; + margin-right: 10px; + } + div.toolSectionPad { + margin: 0; + padding: 0; + height: 5px; + font-size: 0px; + } + div.toolSectionDetailsInner { + margin-left: 5px; + margin-right: 5px; + } + div.toolSectionTitle { + padding-bottom: 0px; + font-weight: bold; + } + div.toolMenuGroupHeader { + font-weight: bold; + padding-top: 0.5em; + padding-bottom: 0.5em; + color: #333; + font-style: italic; + border-bottom: dotted #333 1px; + margin-bottom: 0.5em; + } + div.toolTitle { + padding-top: 5px; + padding-bottom: 5px; + margin-left: 16px; + margin-right: 10px; + display: list-item; + list-style: square outside; + } + a:link, a:visited, a:active + { + color: #303030; + } + </style> +</%def> + <%def name="init()"> <% self.has_left_panel=True @@ -29,17 +80,18 @@ </div> <div class="toolSectionBody"> <div class="toolSectionBg"> - <div class="toolTitle"><a href="${h.url_for( controller='tool', action='browse_tool_categories' )}" target="galaxy_main">Browse tools by category</a></div> - <div class="toolTitle"><a href="${h.url_for( controller='tool', action='browse_tools' )}" target="galaxy_main">Browse all tools</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='tool', action='browse_categories' )}">Browse by category</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='tool', action='browse_tools' )}">Browse all tools</a></div> + <div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='tool', action='browse_tools_by_user', operation='browse', id=trans.security.encode_id( trans.user.id ) )}">Browse your tools</a></div> </div> </div> <div class="toolSectionBody"> <div class="toolSectionBg"> <div class="toolTitle"> %if trans.user: - <a href="${h.url_for( controller='upload', action='upload', type='tool' )}" target="galaxy_main">Upload a tool</a> + <a target="galaxy_main" href="${h.url_for( controller='upload', action='upload', type='tool' )}">Upload a tool</a> %else: - Login to upload + <a target="galaxy_main" href="${h.url_for( controller='/user', action='login', webapp='community' )}">Login to upload</a> %endif </div> </div> @@ -54,7 +106,7 @@ if trans.app.config.require_login and not trans.user: center_url = h.url_for( controller='user', action='login', message=message, status=status ) else: - center_url = h.url_for( controller='tool', action='browse_tool_categories', message=message, status=status ) + center_url = h.url_for( controller='tool', action='browse_categories', message=message, status=status ) %> <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"> </iframe> </%def> diff -r c642fbb301fc -r db4f8befcd89 templates/webapps/community/tool/browse_tool.mako --- a/templates/webapps/community/tool/browse_tool.mako Fri Apr 30 13:09:29 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -<%namespace file="/message.mako" import="render_msg" /> - -<%! - def inherit(context): - if context.get('use_panels'): - return '/webapps/community/base_panels.mako' - else: - return '/base.mako' -%> -<%inherit file="${inherit(context)}"/> - -<%def name="title()">Browse Tool</%def> - -<h2>Galaxy Tool</h2> - -%if message: - ${render_msg( message, status )} -%endif - -%if not tools: - There are no tools -%else: - <table class="grid"> - <thead> - <tr> - <th>Name</th> - <th>Description</th> - </tr> - </thead> - <tbody> - <tr class="formRow id="toolRow"> - <td><a href="${h.url_for( controller='tool', action='browse', id=trans.security.encode_id( tool.id ) )}">${tool.name}</a></td> - <td>${tool.description}</td> - </tr> - </tbody> - </table> -%endif diff -r c642fbb301fc -r db4f8befcd89 templates/webapps/community/tool/edit_tool.mako --- a/templates/webapps/community/tool/edit_tool.mako Fri Apr 30 13:09:29 2010 -0400 +++ b/templates/webapps/community/tool/edit_tool.mako Fri Apr 30 14:08:23 2010 -0400 @@ -123,7 +123,7 @@ <div class="toolParamHelp" style="clear: both;"> Tools must be approved before they are made available to others in the community. After you have submitted your tool to be published, you will no longer be able to modify it, so make sure the information above is - correct and has been saved before submitting for approval. + correct and and save any changes before submitting for approval. </div> </div> </form> diff -r c642fbb301fc -r db4f8befcd89 templates/webapps/community/tool/view_tool.mako --- a/templates/webapps/community/tool/view_tool.mako Fri Apr 30 13:09:29 2010 -0400 +++ b/templates/webapps/community/tool/view_tool.mako Fri Apr 30 14:08:23 2010 -0400 @@ -49,6 +49,14 @@ <h2>View Tool: ${tool.name} <em>${tool.description}</em></h2> +%if cntrller=='admin' and tool.is_waiting(): + <p> + <ul class="manage-table-actions"> + <li><a class="action-button" href="${h.url_for( controller='admin', action='set_tool_state', state=trans.model.Tool.states.APPROVED, id=trans.security.encode_id( tool.id ), cntrller=cntrller )}"><span>Approve</span></a></li> + </ul> + </p> +%endif + %if message: ${render_msg( message, status )} %endif