details: http://www.bx.psu.edu/hg/galaxy/rev/63201eefad88 changeset: 3319:63201eefad88 user: jeremy goecks <jeremy.goecks@emory.edu> date: Wed Feb 03 11:27:21 2010 -0500 description: Added functionality to insert links to pages, datasets, and workflows into pages; button images are not done yet, however. Also refactored grid code to use shared columns defined in controller.py, replaced tabs with spaces in mako files, and made change to show right panel for all shared items regardless of whether they are published. diffstat: lib/galaxy/web/base/controller.py | 24 +- lib/galaxy/web/buildapp.py | 1 + lib/galaxy/web/controllers/admin.py | 27 -- lib/galaxy/web/controllers/dataset.py | 57 ++++- lib/galaxy/web/controllers/forms.py | 9 - lib/galaxy/web/controllers/history.py | 23 +- lib/galaxy/web/controllers/library_admin.py | 9 - lib/galaxy/web/controllers/page.py | 224 +++++++++++++++--- lib/galaxy/web/controllers/requests.py | 9 - lib/galaxy/web/controllers/requests_admin.py | 18 - lib/galaxy/web/controllers/root.py | 1 - lib/galaxy/web/controllers/workflow.py | 29 ++ static/wymeditor/lang/en.js | 2 + templates/dataset/display.mako | 103 ++++++++ templates/display_base.mako | 71 ++--- templates/display_common.mako | 2 + templates/grid_base.mako | 30 +- templates/page/editor.mako | 124 +++++++-- templates/page/select_histories_grid.mako | 13 - templates/page/select_histories_grid_async.mako | 8 - templates/page/select_items_grid.mako | 13 + templates/page/select_items_grid_async.mako | 8 + templates/root/history.mako | 24 +- templates/root/history_common.mako | 74 +++--- templates/sharing_base.mako | 290 ++++++++++++------------ templates/workflow/edit_attributes.mako | 40 +- templates/workflow/editor.mako | 101 ++++---- 27 files changed, 826 insertions(+), 508 deletions(-) diffs (1881 lines): diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/base/controller.py Wed Feb 03 11:27:21 2010 -0500 @@ -17,13 +17,13 @@ # Useful columns in many grids used by controllers. -# Item's user/owner. class OwnerColumn( grids.TextColumn ): + """ Column that lists item's owner. """ def get_value( self, trans, grid, item ): return item.user.username -# Item's public URL based on username and slug. class PublicURLColumn( grids.TextColumn ): + """ Column displays item's public URL based on username and slug. """ def get_link( self, trans, grid, item ): if item.user.username and item.slug: return dict( action='display_by_username_and_slug', username=item.user.username, slug=item.slug ) @@ -33,7 +33,18 @@ elif not item.user.slug: # TODO: provide link to set slg return None - + +class DeletedColumn( grids.GridColumn ): + """ Column that tracks and filters for items with deleted attribute. """ + def get_accepted_filters( self ): + """ Returns a list of accepted filters for this column. """ + accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } + accepted_filters = [] + for label, val in accepted_filter_labels_and_vals.items(): + args = { self.key: val } + accepted_filters.append( grids.GridColumnFilter( label, args) ) + return accepted_filters + class BaseController( object ): """ Base class for Galaxy web application controllers. @@ -205,6 +216,13 @@ """ Display item by username and slug. """ pass + @web.expose + @web.json + @web.require_login( "get item name and link" ) + def get_name_and_link_async( self, trans, id=None ): + """ Returns item's name and link. """ + pass + # Helper methods. def _make_item_accessible( self, sa_session, item ): diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/buildapp.py --- a/lib/galaxy/web/buildapp.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/buildapp.py Wed Feb 03 11:27:21 2010 -0500 @@ -74,6 +74,7 @@ webapp.add_route( '/:controller/:action', action='index' ) webapp.add_route( '/:action', controller='root', action='index' ) webapp.add_route( '/datasets/:dataset_id/:action/:filename', controller='dataset', action='index', dataset_id=None, filename=None) + webapp.add_route( '/u/:username/d/:slug', controller='dataset', action='display_by_username_and_slug' ) webapp.add_route( '/u/:username/p/:slug', controller='page', action='display_by_username_and_slug' ) webapp.add_route( '/u/:username/h/:slug', controller='history', action='display_by_username_and_slug' ) webapp.add_route( '/u/:username/w/:slug', controller='workflow', action='display_by_username_and_slug' ) diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/admin.py --- a/lib/galaxy/web/controllers/admin.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/admin.py Wed Feb 03 11:27:21 2010 -0500 @@ -47,15 +47,6 @@ if user.galaxy_sessions: return self.format( user.galaxy_sessions[ 0 ].update_time ) return 'never' - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters # Grid definition title = "Users" @@ -131,15 +122,6 @@ if role.deleted: return "deleted" return "" - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters class GroupsColumn( grids.GridColumn ): def get_value( self, trans, grid, role ): if role.groups: @@ -216,15 +198,6 @@ if group.deleted: return "deleted" return "" - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters class RolesColumn( grids.GridColumn ): def get_value( self, trans, grid, group ): if group.roles: diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/dataset.py --- a/lib/galaxy/web/controllers/dataset.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/dataset.py Wed Feb 03 11:27:21 2010 -0500 @@ -105,9 +105,8 @@ use_paging = True num_rows_per_page = 50 def apply_default_filter( self, trans, query, **kwargs ): - # This is a somewhat obtuse way to join the History and HDA tables. However, it's necessary - # because the initial query in build_initial_query is specificied on the HDA table (this is reasonable) - # and there's no simple property in the HDA to do the join. + # To filter HDAs by user, need to join HDA and History table and then filter histories by user. This is necessary because HDAs do not have + # a user relation. return query.select_from( model.HistoryDatasetAssociation.table.join( model.History.table ) ).filter( model.History.user == trans.user ) class DatasetInterface( BaseController ): @@ -287,6 +286,39 @@ # Render the list view return self.stored_list_grid( trans, status=status, message=message, **kwargs ) + + @web.expose + @web.json + @web.require_login( "use Galaxy datasets" ) + def get_name_and_link_async( self, trans, id=None ): + """ Returns dataset's name and link. """ + dataset = self.get_data( trans, id ) + return_dict = { "name" : dataset.name, "link" : url_for( action="display_by_username_and_slug", username=dataset.history.user.username, slug=trans.security.encode_id( dataset.id ) ) } + return return_dict + + @web.expose + @web.require_login( "use Galaxy datasets" ) + def set_accessible_async( self, trans, id=None, accessible=False ): + """ Does nothing because datasets do not have an importable/accessible attribute. This method could potentially set another attribute. """ + return + + @web.expose + def display_by_username_and_slug( self, trans, username, slug, preview=True ): + """ Display dataset by username and slug; because datasets do not yet have slugs, the slug is the dataset's id. """ + data = self.get_data( trans, slug ) + if data: + # Get data from file, truncating if necessary. + if os.path.exists( data.file_name ): + max_peek_size = 1000000 # 1 MB + if preview and os.stat( data.file_name ).st_size > max_peek_size: + dataset_data = open( data.file_name ).read(max_peek_size) + truncated = True + else: + dataset_data = open( data.file_name ).read(max_peek_size) + truncated = False + return trans.fill_template_mako( "dataset/display.mako", item=data, item_data=dataset_data, truncated=truncated ) + else: + raise web.httpexceptions.HTTPNotFound() @web.expose def display_at( self, trans, dataset_id, filename=None, **kwd ): @@ -413,3 +445,22 @@ done_msg = done_msg, error_msg = error_msg, refresh_frames = refresh_frames ) + + def get_data( self, trans, dataset_id, check_user_can_access=True ): + """ Get an HDA from the database by id, verifying that user can access dataset.""" + # DEPRECATION: We still support unencoded ids for backward compatibility + try: + dataset_id = int( dataset_id ) + except ValueError: + dataset_id = trans.security.decode_id( dataset_id ) + data = trans.sa_session.query( model.HistoryDatasetAssociation ).get( dataset_id ) + if not data: + raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid dataset id: %s." % str( dataset_id ) ) + if check_user_can_access: + current_user_roles = trans.get_current_user_roles() + if trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): + if data.state == trans.model.Dataset.states.UPLOAD: + return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." ) + else: + error( "You are not allowed to access this dataset" ) + return data \ No newline at end of file diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/forms.py --- a/lib/galaxy/web/controllers/forms.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/forms.py Wed Feb 03 11:27:21 2010 -0500 @@ -23,15 +23,6 @@ class TypeColumn( grids.TextColumn ): def get_value(self, trans, grid, form): return form.latest_form.type - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters # Grid definition title = "Forms" template = "admin/forms/grid.mako" diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/history.py Wed Feb 03 11:27:21 2010 -0500 @@ -31,16 +31,6 @@ else: rval.append( '' ) return rval - - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters # Grid definition title = "Saved Histories" @@ -384,18 +374,15 @@ """ Returns history's name and link. """ history = self.get_history( trans, id, False ) - # To get info: user must own history. - if history.user == trans.get_user(): - if self.set_item_slug( trans.sa_session, history ): - trans.sa_session.flush() - return_dict = { "name" : history.name, "link" : "/u/%s/h/%s" % ( history.user.username, history.slug ) } - return return_dict - return + if self.set_item_slug( trans.sa_session, history ): + trans.sa_session.flush() + return_dict = { "name" : history.name, "link" : url_for( action="display_by_username_and_slug", username=history.user.username, slug=history.slug ) } + return return_dict @web.expose @web.require_login( "set history's accessible flag" ) def set_accessible_async( self, trans, id=None, accessible=False ): - """ Set history's importable attribute and sets history's slug. """ + """ Set history's importable attribute and slug. """ history = self.get_history( trans, id, True ) # Only set if importable value would change; this prevents a change in the update_time unless attribute really changed. diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/library_admin.py --- a/lib/galaxy/web/controllers/library_admin.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/library_admin.py Wed Feb 03 11:27:21 2010 -0500 @@ -31,15 +31,6 @@ elif library.deleted: return "deleted" return "" - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters # Grid definition title = "Data Libraries" model_class = model.Library diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/page.py --- a/lib/galaxy/web/controllers/page.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/page.py Wed Feb 03 11:27:21 2010 -0500 @@ -84,44 +84,7 @@ class NameColumn( grids.TextColumn ): def get_value(self, trans, grid, history): return history.get_display_name() - - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters - - class SharingColumn( grids.GridColumn ): - def filter( self, db_session, user, query, column_filter ): - """ Modify query to filter histories by sharing status. """ - if column_filter == "All": - pass - elif column_filter: - if column_filter == "private": - query = query.filter( model.History.users_shared_with == None ) - query = query.filter( model.History.importable == False ) - elif column_filter == "shared": - query = query.filter( model.History.users_shared_with != None ) - elif column_filter == "importable": - query = query.filter( model.History.importable == True ) - return query - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = odict() - accepted_filter_labels_and_vals["private"] = "private" - accepted_filter_labels_and_vals["shared"] = "shared" - accepted_filter_labels_and_vals["importable"] = "importable" - accepted_filter_labels_and_vals["all"] = "All" - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters - + # Grid definition. title = "Saved Histories" template = "/page/select_histories_grid.mako" @@ -138,9 +101,9 @@ grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), # Columns that are valid for filtering but are not visible. DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ), - SharingColumn( "Shared", key="shared", visible=False, filterable="advanced" ), + SharingStatusColumn( "Sharing", key="sharing", model_class=model.History, filterable="advanced", sortable=False, visible=False ), ] - columns.append( + columns.append( grids.MulticolFilterColumn( "Search", cols_to_filter=[ columns[0], columns[1] ], @@ -148,12 +111,125 @@ ) def apply_default_filter( self, trans, query, **kwargs ): return query.filter_by( user=trans.user, purged=False ) + +class ItemSelectionGrid( grids.Grid ): + """ Base class for pages' item selection grids. """ + # Custom columns. + class NameColumn( grids.TextColumn ): + def get_value(self, trans, grid, item): + if hasattr( item, "get_display_name" ): + return item.get_display_name() + else: + return item.name + # Grid definition. + template = "/page/select_items_grid.mako" + async_template = "/page/select_items_grid_async.mako" + default_filter = { "deleted" : "False" , "sharing" : "All" } + default_sort_key = "-update_time" + use_async = True + use_paging = True + num_rows_per_page = 10 + + def apply_default_filter( self, trans, query, **kwargs ): + return query.filter_by( user=trans.user ) + +class HistorySelectionGrid( ItemSelectionGrid ): + """ Grid for selecting histories. """ + # Grid definition. + title = "Saved Histories" + model_class = model.History + columns = [ + ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.History, filterable="advanced" ), + grids.IndividualTagsColumn( "Tags", "tags", model.History, model.HistoryTagAssociation, filterable="advanced"), + grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), + # Columns that are valid for filtering but are not visible. + DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ), + SharingStatusColumn( "Sharing", key="sharing", model_class=model.History, filterable="advanced", sortable=False, visible=False ), + ] + columns.append( + grids.MulticolFilterColumn( + "Search", + cols_to_filter=[ columns[0], columns[1] ], + key="free-text-search", visible=False, filterable="standard" ) + ) + + def apply_default_filter( self, trans, query, **kwargs ): + return query.filter_by( user=trans.user, purged=False ) + +class HistoryDatasetAssociationSelectionGrid( ItemSelectionGrid ): + """ Grid for selecting HDAs. """ + # Grid definition. + title = "Saved Datasets" + model_class = model.HistoryDatasetAssociation + columns = [ + ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.HistoryDatasetAssociation, filterable="advanced" ), + grids.IndividualTagsColumn( "Tags", "tags", model.StoredWorkflow, model.HistoryDatasetAssociationTagAssociation, filterable="advanced"), + grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), + # Columns that are valid for filtering but are not visible. + DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ), + SharingStatusColumn( "Sharing", key="sharing", model_class=model.HistoryDatasetAssociation, filterable="advanced", sortable=False, visible=False ), + ] + columns.append( + grids.MulticolFilterColumn( + "Search", + cols_to_filter=[ columns[0], columns[1] ], + key="free-text-search", visible=False, filterable="standard" ) + ) + def apply_default_filter( self, trans, query, **kwargs ): + # To filter HDAs by user, need to join HDA and History table and then filter histories by user. This is necessary because HDAs do not have + # a user relation. + return query.select_from( model.HistoryDatasetAssociation.table.join( model.History.table ) ).filter( model.History.user == trans.user ) + + +class WorkflowSelectionGrid( ItemSelectionGrid ): + """ Grid for selecting workflows. """ + # Grid definition. + title = "Saved Workflows" + model_class = model.StoredWorkflow + columns = [ + ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.StoredWorkflow, filterable="advanced" ), + grids.IndividualTagsColumn( "Tags", "tags", model.StoredWorkflow, model.StoredWorkflowTagAssociation, filterable="advanced"), + grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), + # Columns that are valid for filtering but are not visible. + DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ), + SharingStatusColumn( "Sharing", key="sharing", model_class=model.StoredWorkflow, filterable="advanced", sortable=False, visible=False ), + ] + columns.append( + grids.MulticolFilterColumn( + "Search", + cols_to_filter=[ columns[0], columns[1] ], + key="free-text-search", visible=False, filterable="standard" ) + ) + +class PageSelectionGrid( ItemSelectionGrid ): + """ Grid for selecting pages. """ + # Grid definition. + title = "Saved Pages" + model_class = model.Page + columns = [ + grids.TextColumn( "Title", key="title", model_class=model.Page, filterable="advanced" ), + grids.IndividualTagsColumn( "Tags", "tags", model.Page, model.PageTagAssociation, filterable="advanced"), + grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), + # Columns that are valid for filtering but are not visible. + DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ), + SharingStatusColumn( "Sharing", key="sharing", model_class=model.Page, filterable="advanced", sortable=False, visible=False ), + ] + columns.append( + grids.MulticolFilterColumn( + "Search", + cols_to_filter=[ columns[0], columns[1] ], + key="free-text-search", visible=False, filterable="standard" ) + ) + class PageController( BaseController, Sharable ): _page_list = PageListGrid() _all_published_list = PageAllPublishedGrid() _history_selection_grid = HistorySelectionGrid() + _workflow_selection_grid = WorkflowSelectionGrid() + _datasets_selection_grid = HistoryDatasetAssociationSelectionGrid() + _page_selection_grid = PageSelectionGrid() @web.expose @web.require_login() @@ -447,7 +523,34 @@ raise web.httpexceptions.HTTPNotFound() return trans.fill_template_mako( "page/display.mako", item=page) - + + @web.expose + @web.require_login( "use Galaxy pages" ) + def set_accessible_async( self, trans, id=None, accessible=False ): + """ Set page's importable attribute and slug. """ + page = self.get_page( trans, id ) + + # Only set if importable value would change; this prevents a change in the update_time unless attribute really changed. + importable = accessible in ['True', 'true', 't', 'T']; + if page.importable != importable: + if importable: + self._make_item_accessible( trans.sa_session, page ) + else: + page.importable = importable + trans.sa_session.flush() + return + + @web.expose + @web.json + @web.require_login( "use Galaxy pages" ) + def get_name_and_link_async( self, trans, id=None ): + """ Returns page's name and link. """ + page = self.get_page( trans, id ) + + if self.set_item_slug( trans.sa_session, page ): + trans.sa_session.flush() + return_dict = { "name" : page.title, "link" : url_for( action="display_by_username_and_slug", username=page.user.username, slug=page.slug ) } + return return_dict @web.expose @web.require_login("select a history from saved histories") @@ -457,6 +560,27 @@ return self._history_selection_grid( trans, **kwargs ) @web.expose + @web.require_login("select a workflow from saved workflows") + def list_workflows_for_selection( self, trans, **kwargs ): + """ Returns HTML that enables a user to select one or more workflows. """ + # Render the list view + return self._workflow_selection_grid( trans, **kwargs ) + + @web.expose + @web.require_login("select a page from saved pages") + def list_pages_for_selection( self, trans, **kwargs ): + """ Returns HTML that enables a user to select one or more pages. """ + # Render the list view + return self._page_selection_grid( trans, **kwargs ) + + @web.expose + @web.require_login("select a dataset from saved datasets") + def list_datasets_for_selection( self, trans, **kwargs ): + """ Returns HTML that enables a user to select one or more datasets. """ + # Render the list view + return self._datasets_selection_grid( trans, **kwargs ) + + @web.expose @web.require_login("get annotation table for history") def get_history_annotation_table( self, trans, id ): """ Returns HTML for an annotation table for a history. """ @@ -483,4 +607,20 @@ @web.expose def get_editor_iframe( self, trans ): """ Returns the document for the page editor's iframe. """ - return trans.fill_template( "page/wymiframe.mako" ) \ No newline at end of file + return trans.fill_template( "page/wymiframe.mako" ) + + def get_page( self, trans, id, check_ownership=True ): + """Get a page from the database by id, verifying ownership.""" + # Load history from database + id = trans.security.decode_id( id ) + page = trans.sa_session.query( model.Page ).get( id ) + if not page: + err+msg( "History not found" ) + if check_ownership: + # Verify ownership + user = trans.get_user() + if not user: + error( "Must be logged in to work with Pages" ) + if page.user != user: + error( "History is not owned by current user" ) + return page \ No newline at end of file diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/requests.py --- a/lib/galaxy/web/controllers/requests.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/requests.py Wed Feb 03 11:27:21 2010 -0500 @@ -71,15 +71,6 @@ args = { self.key: val } accepted_filters.append( grids.GridColumnFilter( label, args) ) return accepted_filters - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters # Grid definition title = "Sequencing Requests" template = 'requests/grid.mako' diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/requests_admin.py --- a/lib/galaxy/web/controllers/requests_admin.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/requests_admin.py Wed Feb 03 11:27:21 2010 -0500 @@ -80,15 +80,6 @@ class UserColumn( grids.TextColumn ): def get_value(self, trans, grid, request): return request.user.email - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters # Grid definition title = "Sequencing Requests" template = "admin/requests/grid.mako" @@ -167,15 +158,6 @@ class SampleFormColumn( grids.TextColumn ): def get_value(self, trans, grid, request_type): return request_type.sample_form.name - class DeletedColumn( grids.GridColumn ): - def get_accepted_filters( self ): - """ Returns a list of accepted filters for this column. """ - accepted_filter_labels_and_vals = { "active" : "False", "deleted" : "True", "all": "All" } - accepted_filters = [] - for label, val in accepted_filter_labels_and_vals.items(): - args = { self.key: val } - accepted_filters.append( grids.GridColumnFilter( label, args) ) - return accepted_filters # Grid definition title = "Requests Types" template = "admin/requests/manage_request_types.mako" diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/root.py --- a/lib/galaxy/web/controllers/root.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/root.py Wed Feb 03 11:27:21 2010 -0500 @@ -306,7 +306,6 @@ setattr( data.metadata, name, spec.unwrap( params.get (name, None) ) ) data.datatype.after_setting_metadata( data ) self.add_item_annotation( trans, data, params.annotation ) - else: msg = ' (Metadata could not be changed because this dataset is currently being used as input or output. You must cancel or wait for these jobs to complete before changing metadata.)' trans.sa_session.flush() diff -r 1a3339f017e9 -r 63201eefad88 lib/galaxy/web/controllers/workflow.py --- a/lib/galaxy/web/controllers/workflow.py Wed Feb 03 10:31:26 2010 -0500 +++ b/lib/galaxy/web/controllers/workflow.py Wed Feb 03 11:27:21 2010 -0500 @@ -367,6 +367,35 @@ @web.expose @web.require_login( "use Galaxy workflows" ) + def set_accessible_async( self, trans, id=None, accessible=False ): + """ Set workflow's importable attribute and slug. """ + stored = get_stored_workflow( trans, id ) + + # Only set if importable value would change; this prevents a change in the update_time unless attribute really changed. + importable = accessible in ['True', 'true', 't', 'T']; + if stored and stored.importable != importable: + if importable: + self._make_item_accessible( trans.sa_session, stored ) + else: + stored.importable = importable + trans.sa_session.flush() + + return + + @web.expose + @web.json + @web.require_login( "use Galaxy workflows" ) + def get_name_and_link_async( self, trans, id=None ): + """ Returns workflow's name and link. """ + stored = get_stored_workflow( trans, id ) + + if self.set_item_slug( trans.sa_session, stored ): + trans.sa_session.flush() + return_dict = { "name" : stored.name, "link" : url_for( action="display_by_username_and_slug", username=stored.user.username, slug=stored.slug ) } + return return_dict + + @web.expose + @web.require_login( "use Galaxy workflows" ) def clone( self, trans, id ): stored = get_stored_workflow( trans, id, check_ownership=False ) user = trans.get_user() diff -r 1a3339f017e9 -r 63201eefad88 static/wymeditor/lang/en.js --- a/static/wymeditor/lang/en.js Wed Feb 03 10:31:26 2010 -0500 +++ b/static/wymeditor/lang/en.js Wed Feb 03 11:27:21 2010 -0500 @@ -45,6 +45,8 @@ // Galaxy replacements. Galaxy_History_Link: 'Insert Link to History', Galaxy_Dataset_Link: 'Insert Link to Dataset', + Galaxy_Workflow_Link: 'Insert Link to Workflow', + Galaxy_Page_Link: 'Insert Link to Page', Annotate_Galaxy_History: 'Annotate History', }; diff -r 1a3339f017e9 -r 63201eefad88 templates/dataset/display.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/dataset/display.mako Wed Feb 03 11:27:21 2010 -0500 @@ -0,0 +1,103 @@ +## Because HDAs do not have many of the properties that other sharable items have, we need to override most of the default code for display. +<%inherit file="/display_base.mako"/> +<%namespace file="/display_common.mako" import="*" /> +<%namespace file="/tagging_common.mako" import="render_individual_tagging_element, render_community_tagging_element" /> + +<%def name="javascripts()"> + ${parent.javascripts()} +</%def> + +<%def name="init()"> +<% + self.has_left_panel=False + self.has_right_panel=True + self.message_box_visible=False + self.active_view="user" + self.overlay_visible=False +%> +</%def> + +<%def name="title()"> + Galaxy | ${get_class_display_name( item.__class__ )} | ${get_item_name( item )} +</%def> + +<%def name="render_item_links( data )"> + ## Provide links to save data and TODO: import dataset. + <a href="${h.url_for( controller='dataset', action='display', dataset_id=trans.security.encode_id( data.id ), to_ext=data.ext )}">save</a> +</%def> + +<%def name="render_item( data, data_to_render )"> + <hr/> + %if truncated: + <div class="warningmessagelarge"> + This dataset is large and only the first megabyte is shown below. | + <a href="${h.url_for( controller='dataset', action='display_by_username_and_slug', username=data.history.user.username, slug=trans.security.encode_id( data.id ), preview=False )}">Show all</a> + </div> + %endif + ## TODO: why is the default font size so small? + <pre style="font-size: 135%">${ data_to_render | h }</pre> +</%def> + + +<%def name="center_panel()"> + <div class="unified-panel-header" unselectable="on"> + <div class="unified-panel-header-inner"> + ${get_class_display_name( item.__class__ )} + | ${get_item_name( item )} + </div> + </div> + + <div class="unified-panel-body"> + <div style="overflow: auto; height: 100%;"> + <div class="page-body"> + <div style="padding: 0px 0px 5px 0px"> + ${self.render_item_links( item )} + </div> + + ${self.render_item( item, item_data )} + </div> + </div> + </div> +</%def> + +<%def name="right_panel()"> + <div class="unified-panel-header" unselectable="on"> + <div class="unified-panel-header-inner"> + About this ${get_class_display_name( item.__class__ )} + </div> + </div> + + <div class="unified-panel-body"> + <div style="overflow: auto; height: 100%;"> + <div style="padding: 10px;"> + <h4>Author</h4> + + <p>${item.history.user.username}</p> + + <div><img src="http://www.gravatar.com/avatar/${h.md5(item.history.user.email)}?s=150"></div> + + ## Page meta. No page meta for datasets for now. + + ## Tags. + <p> + <h4>Tags</strong></h4> + <p> + ## Community tags. + <div> + Community: + ${render_community_tagging_element( tagged_item=item, tag_click_fn='community_tag_click', use_toggle_link=False )} + %if len ( item.tags ) == 0: + none + %endif + </div> + ## Individual tags. + <p> + <div> + Yours: + ${render_individual_tagging_element( user=trans.get_user(), tagged_item=item, elt_context='view.mako', use_toggle_link=False, tag_click_fn='community_tag_click' )} + </div> + </div> + </div> + </div> + +</%def> \ No newline at end of file diff -r 1a3339f017e9 -r 63201eefad88 templates/display_base.mako --- a/templates/display_base.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/display_base.mako Wed Feb 03 11:27:21 2010 -0500 @@ -148,45 +148,40 @@ </div> <div class="unified-panel-body"> - <div style="overflow: auto; height: 100%;"> - - %if item.published: - <div style="padding: 10px;"> - <h4>Author</h4> - - <p>${item.user.username}</p> - - <div><img src="http://www.gravatar.com/avatar/${h.md5(item.user.email)}?s=150"></div> - - - - ## Page meta. - <h4>Related ${item_plural}</h4> - <p> - <a href="${href_to_all_items}">All published ${item_plural.lower()}</a><br> - <a href="${href_to_user_items}">${item_plural} owned by ${item.user.username}</a> - - ## Tags. - <h4>Tags</strong></h4> - <p> - ## Community tags. - <div> - Community: - ${render_community_tagging_element( tagged_item=item, tag_click_fn='community_tag_click', use_toggle_link=False )} - %if len ( item.tags ) == 0: - none - %endif - </div> - ## Individual tags. - <p> - <div> - Yours: - ${render_individual_tagging_element( user=trans.get_user(), tagged_item=item, elt_context='view.mako', use_toggle_link=False, tag_click_fn='community_tag_click' )} - </div> + <div style="overflow: auto; height: 100%;"> + <div style="padding: 10px;"> + <h4>Author</h4> + + <p>${item.user.username}</p> + + <div><img src="http://www.gravatar.com/avatar/${h.md5(item.user.email)}?s=150"></div> + + + + ## Page meta. + <h4>Related ${item_plural}</h4> + <p> + <a href="${href_to_all_items}">All published ${item_plural.lower()}</a><br> + <a href="${href_to_user_items}">${item_plural} owned by ${item.user.username}</a> + + ## Tags. + <h4>Tags</strong></h4> + <p> + ## Community tags. + <div> + Community: + ${render_community_tagging_element( tagged_item=item, tag_click_fn='community_tag_click', use_toggle_link=False )} + %if len ( item.tags ) == 0: + none + %endif </div> - %endif - - + ## Individual tags. + <p> + <div> + Yours: + ${render_individual_tagging_element( user=trans.get_user(), tagged_item=item, elt_context='view.mako', use_toggle_link=False, tag_click_fn='community_tag_click' )} + </div> + </div> </div> </div> diff -r 1a3339f017e9 -r 63201eefad88 templates/display_common.mako --- a/templates/display_common.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/display_common.mako Wed Feb 03 11:27:21 2010 -0500 @@ -39,6 +39,8 @@ ## Start with exceptions, end with default. if a_class is model.StoredWorkflow: return "Workflow" + elif a_class is model.HistoryDatasetAssociation: + return "Dataset" else: return a_class.__name__ %> diff -r 1a3339f017e9 -r 63201eefad88 templates/grid_base.mako --- a/templates/grid_base.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/grid_base.mako Wed Feb 03 11:27:21 2010 -0500 @@ -15,12 +15,12 @@ ## <%def name="center_panel()"> - ${make_grid( grid )} + ${make_grid( grid )} </%def> ## Render the grid's basic elements. Each of these elements can be subclassed. <%def name="body()"> - ${make_grid( grid )} + ${make_grid( grid )} </%def> <%def name="title()">${grid.title}</%def> @@ -718,15 +718,15 @@ <%namespace file="./grid_common.mako" import="*" /> <%def name="make_grid( grid )"> - <table> - <tr> - <td width="75%">${self.render_grid_header( grid )}</td> - <td></td> - <td width="25%" id="grid-message" valign="top">${self.render_grid_message( grid )}</td> - </tr> - </table> + <table> + <tr> + <td width="75%">${self.render_grid_header( grid )}</td> + <td></td> + <td width="25%" id="grid-message" valign="top">${self.render_grid_message( grid )}</td> + </tr> + </table> - ${self.render_grid_table( grid )} + ${self.render_grid_table( grid )} </%def> ## Render grid message. @@ -920,13 +920,13 @@ ## Render grid table footer contents. <%def name="render_grid_table_footer_contents(grid, show_item_checkboxes=False)"> ## Row for navigating among pages. - <%namespace file="/display_common.mako" import="get_class_plural" /> - <% items_plural = get_class_plural( grid.model_class ).lower() %> + <%namespace file="/display_common.mako" import="get_class_plural" /> + <% items_plural = get_class_plural( grid.model_class ).lower() %> %if grid.use_paging and num_pages > 1: <tr id="page-links-row"> - %if show_item_checkboxes: - <td></td> - %endif + %if show_item_checkboxes: + <td></td> + %endif <td colspan="100"> <span id='page-link-container'> ## Page links. diff -r 1a3339f017e9 -r 63201eefad88 templates/page/editor.mako --- a/templates/page/editor.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/page/editor.mako Wed Feb 03 11:27:21 2010 -0500 @@ -30,6 +30,9 @@ var Galaxy = { DIALOG_HISTORY_LINK : "history_link", + DIALOG_DATASET_LINK : "dataset_link", + DIALOG_WORKFLOW_LINK : "workflow_link", + DIALOG_PAGE_LINK : "page_link", DIALOG_HISTORY_ANNOTATE : "history_annotate", }; @@ -199,25 +202,59 @@ ); } - // INSERT HISTORY LINK DIALOG - if ( dialogType == Galaxy.DIALOG_HISTORY_LINK ) { + // INSERT "GALAXY ITEM" (HISTORY, DATASET, WORKFLOW, PAGE) LINK DIALOG + if ( dialogType == Galaxy.DIALOG_HISTORY_LINK || dialogType == Galaxy.DIALOG_DATASET_LINK || + dialogType == Galaxy.DIALOG_WORKFLOW_LINK || dialogType == Galaxy.DIALOG_PAGE_LINK ) { + // Based on item type, set useful vars. + var + item_singular, + item_plural, + item_controller, + item_list_action; + switch( dialogType ) { + case( Galaxy.DIALOG_HISTORY_LINK ): + item_singular = "History"; + item_plural = "Histories"; + item_controller = "history" + break; + case( Galaxy.DIALOG_DATASET_LINK ): + item_singular = "Dataset"; + item_plural = "Datasets"; + item_controller = "dataset" + break; + case( Galaxy.DIALOG_WORKFLOW_LINK ): + item_singular = "Workflow"; + item_plural = "Workflows"; + item_controller = "workflow" + break; + case( Galaxy.DIALOG_PAGE_LINK ): + item_singular = "Page"; + item_plural = "Pages"; + item_controller = "page" + break; + } + item_list_action = "list_" + item_plural.toLowerCase() + "_for_selection"; + + // Show grid that enables user to select items. + var url_template = "${h.url_for( action='LIST_ACTION' )}"; + var ajax_url = url_template.replace( "LIST_ACTION", item_list_action ); $.ajax( { - url: "${h.url_for( action='list_histories_for_selection' )}", + url: ajax_url, data: {}, - error: function() { alert( "Grid refresh failed" ) }, + error: function() { alert( "Failed to list " + item_plural.toLowerCase() + " for selection"); }, success: function(table_html) { show_modal( - "Insert Link to History", + "Insert Link to " + item_singular, table_html + "<div><input id='make-importable' type='checkbox' checked/>" + - "Make the selected histories accessible so that they can viewed by everyone.</div>" + "Make the selected " + item_plural.toLowerCase() + " accessible so that they can viewed by everyone.</div>" , { "Insert": function() { - // Make histories public/importable? + // Make items accessible (importable) ? var make_importable = false; if ( $('#make-importable:checked').val() !== null ) make_importable = true; @@ -229,15 +266,21 @@ // Make history importable? if (make_importable) + { + url_template = "${h.url_for( controller='ITEM_CONTROLLER', action='set_accessible_async' )}"; + ajax_url = url_template.replace( "ITEM_CONTROLLER", item_controller); $.ajax({ type: "POST", - url: '${h.url_for( controller='history', action='set_accessible_async' )}', + url: ajax_url, data: { id: item_id, accessible: 'True' }, - error: function() { alert('Make history accessible failed; id=' + item_id) } + error: function() { alert("Making " + item_plural.toLowerCase() + " accessible failed"); } }); - - // Insert link. This is done by getting history info and then manipulating wym. - $.getJSON( '${h.url_for( controller='history', action='get_name_and_link_async' )}?id=' + item_id, function( history_info ) { + } + + // Insert link(s) to item(s). This is done by getting item info and then manipulating wym. + url_template = "${h.url_for( controller='ITEM_CONTROLLER', action='get_name_and_link_async' )}?id=" + item_id; + ajax_url = url_template.replace( "ITEM_CONTROLLER", item_controller); + $.getJSON( ajax_url, function( item_info ) { // Get link text. wym._exec(WYMeditor.CREATE_LINK, sStamp); var link_text = $("a[href=" + sStamp + "]", wym._doc.body).text(); @@ -250,12 +293,12 @@ ) { // User selected no text; create link from scratch and use default text. - wym.insert("<a href='" + history_info.link + "'>History '" + history_info.name + "'</a>"); + wym.insert("<a href='" + item_info.link + "'> '" + item_singular + " " + item_info.name + "'</a>"); } else { // Link created from selected text; add href and title. - $("a[href=" + sStamp + "]", wym._doc.body).attr(WYMeditor.HREF, history_info.link).attr(WYMeditor.TITLE, "History" + item_id); + $("a[href=" + sStamp + "]", wym._doc.body).attr(WYMeditor.HREF, item_info.link).attr(WYMeditor.TITLE, item_singular + item_id); } }); }); @@ -365,6 +408,9 @@ {'name': 'InsertImage', 'title': 'Image', 'css': 'wym_tools_image'}, {'name': 'InsertTable', 'title': 'Table', 'css': 'wym_tools_table'}, {'name': 'Insert Galaxy History Link', 'title' : 'Galaxy_History_Link', 'css' : 'galaxy_tools_insert_history_link'}, + {'name': 'Insert Galaxy Dataset Link', 'title' : 'Galaxy_Dataset_Link', 'css' : 'galaxy_tools_insert_dataset_link'}, + {'name': 'Insert Galaxy Workflow Link', 'title' : 'Galaxy_Workflow_Link', 'css' : 'galaxy_tools_insert_workflow_link'}, + {'name': 'Insert Galaxy Page Link', 'title' : 'Galaxy_Page_Link', 'css' : 'galaxy_tools_insert_page_link'}, {'name': 'Annonate Galaxy History', 'title' : 'Annotate_Galaxy_History', 'css' : 'galaxy_tools_annotate_history'}, ] }); @@ -372,29 +418,29 @@ var editor = $.wymeditors(0); var save = function ( callback ) { show_modal( "Saving page", "progress" ); - // Gather annotations. - var annotations = new Array(); - - $('.annotation', editor._doc.body).each( function() { - var item_class = $(this).attr( 'item_class' ); - var item_id = $(this).attr( 'item_id' ); - var text = $(this).text(); - annotation = { - "item_class" : item_class, - "item_id" : item_id, - "text" : text - }; - annotations[ annotations.length ] = annotation; - }); - - // Do save. - $.ajax( { + // Gather annotations. + var annotations = new Array(); + + $('.annotation', editor._doc.body).each( function() { + var item_class = $(this).attr( 'item_class' ); + var item_id = $(this).attr( 'item_id' ); + var text = $(this).text(); + annotation = { + "item_class" : item_class, + "item_id" : item_id, + "text" : text + }; + annotations[ annotations.length ] = annotation; + }); + + // Do save. + $.ajax( { url: "${h.url_for( action='save' )}", type: "POST", data: { id: "${trans.security.encode_id(page.id)}", content: editor.xhtml(), - annotations: JSON.stringify(annotations), + annotations: JSON.stringify(annotations), "_": "true" }, success: function() { @@ -436,9 +482,21 @@ $('.galaxy_tools_insert_history_link').children().click( function() { editor.dialog(Galaxy.DIALOG_HISTORY_LINK); }); + // Initialize 'Insert dataset link' button. + $('.galaxy_tools_insert_dataset_link').children().click( function() { + editor.dialog(Galaxy.DIALOG_DATASET_LINK); + }); + // Initialize 'Insert workflow link' button. + $('.galaxy_tools_insert_workflow_link').children().click( function() { + editor.dialog(Galaxy.DIALOG_WORKFLOW_LINK); + }); + // Initialize 'Insert page link' button. + $('.galaxy_tools_insert_page_link').children().click( function() { + editor.dialog(Galaxy.DIALOG_PAGE_LINK); + }); // Initialize 'Annotate history' button. $('.galaxy_tools_annotate_history').children().click( function() { - editor.dialog(Galaxy.ANNOTATE_HISTORY); + editor.dialog(Galaxy.DIALOG_ANNOTATE_HISTORY); }); // Initialize galaxy elements. //init_galaxy_elts(editor); diff -r 1a3339f017e9 -r 63201eefad88 templates/page/select_histories_grid.mako --- a/templates/page/select_histories_grid.mako Wed Feb 03 10:31:26 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -## Template generates a grid that enables user to select histories. -<%namespace file="../grid_base.mako" import="*" /> - -${javascripts()} -${stylesheets()} -${render_grid_header( grid, False )} -${render_grid_table( grid, show_item_checkboxes=True )} - -## Initialize the grid. -<script type="text/javascript"> - init_grid_elements(); - init_grid_controls(); -</script> diff -r 1a3339f017e9 -r 63201eefad88 templates/page/select_histories_grid_async.mako --- a/templates/page/select_histories_grid_async.mako Wed Feb 03 10:31:26 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -<%namespace file="../grid_base.mako" import="*" /> - -## Always show item checkboxes so that users can select histories. -${render_grid_table_body_contents( grid, show_item_checkboxes=True )} -***** -${num_pages} -***** -${render_grid_message( grid )} \ No newline at end of file diff -r 1a3339f017e9 -r 63201eefad88 templates/page/select_items_grid.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/page/select_items_grid.mako Wed Feb 03 11:27:21 2010 -0500 @@ -0,0 +1,13 @@ +## Template generates a grid that enables user to select items. +<%namespace file="../grid_base.mako" import="*" /> + +${javascripts()} +${stylesheets()} +${render_grid_header( grid, False )} +${render_grid_table( grid, show_item_checkboxes=True )} + +## Initialize the grid. +<script type="text/javascript"> + init_grid_elements(); + init_grid_controls(); +</script> diff -r 1a3339f017e9 -r 63201eefad88 templates/page/select_items_grid_async.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/page/select_items_grid_async.mako Wed Feb 03 11:27:21 2010 -0500 @@ -0,0 +1,8 @@ +<%namespace file="../grid_base.mako" import="*" /> + +## Always show item checkboxes so that users can select histories. +${render_grid_table_body_contents( grid, show_item_checkboxes=True )} +***** +${num_pages} +***** +${render_grid_message( grid )} \ No newline at end of file diff -r 1a3339f017e9 -r 63201eefad88 templates/root/history.mako --- a/templates/root/history.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/root/history.mako Wed Feb 03 11:27:21 2010 -0500 @@ -47,14 +47,14 @@ // Annotation async. // Tag async. Simply have the workflow tag element generate a click on the tag element to activate tagging. - $('#workflow-tag').click( function() - { - $('.tag-area').click(); - return false; - }); - - // Annotate async. - async_save_text("history-annotate", "history-annotation", "${h.url_for( controller="/history", action="annotate_async", id=trans.security.encode_id(history.id) )}", "new_annotation", true, 4); + $('#workflow-tag').click( function() + { + $('.tag-area').click(); + return false; + }); + + // Annotate async. + async_save_text("history-annotate", "history-annotation", "${h.url_for( controller="/history", action="annotate_async", id=trans.security.encode_id(history.id) )}", "new_annotation", true, 4); // Updater updater({ @@ -308,6 +308,11 @@ ## Annotation elt. <div id="history-annotation-area" class="form-row"> +<<<<<<< local + <label>Annotation / Notes:</label> + <div style="float: right"><a id="history-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='history', action='annotate_async' )}"></a></div> + <div id="history-annotation">${annotation}</div> +======= <label>Annotation / Notes:</label> <div style="float: right"><a id="history-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='history', action='annotate_async' )}"></a></div> %if annotation: @@ -315,8 +320,9 @@ %else: <div id="history-annotation"></div> %endif +>>>>>>> other <div style="clear: both"></div> - </div> + </div> </div> </div> %endif diff -r 1a3339f017e9 -r 63201eefad88 templates/root/history_common.mako --- a/templates/root/history_common.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/root/history_common.mako Wed Feb 03 11:27:21 2010 -0500 @@ -3,11 +3,11 @@ <%def name="render_dataset( data, hid, show_deleted_on_refresh = False, user_owns_dataset = True )"> <a name="${trans.security.encode_id( data.id )}"></a> <% - if data.state in ['no state','',None]: - data_state = "queued" - else: - data_state = data.state - current_user_roles = trans.get_current_user_roles() + if data.state in ['no state','',None]: + data_state = "queued" + else: + data_state = data.state + current_user_roles = trans.get_current_user_roles() %> %if not trans.user_is_admin() and not trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ): <div class="historyItemWrapper historyItem historyItem-${data_state} historyItem-noPermission" id="historyItem-${data.id}"> @@ -22,29 +22,29 @@ %endif ## Header row for history items (name, state, action buttons) - <div style="overflow: hidden;" class="historyItemTitleBar"> - <div class="historyItemButtons"> + <div style="overflow: hidden;" class="historyItemTitleBar"> + <div class="historyItemButtons"> %if data_state == "upload": - ## TODO: Make these CSS, just adding a "disabled" class to the normal - ## links should be enough. However the number of datasets being uploaded - ## at a time is usually small so the impact of these images is also small. - <img src="${h.url_for('/static/images/eye_icon_grey.png')}" width='16' height='16' alt='display data' title='display data' class='button display' border='0'> + ## TODO: Make these CSS, just adding a "disabled" class to the normal + ## links should be enough. However the number of datasets being uploaded + ## at a time is usually small so the impact of these images is also small. + <img src="${h.url_for('/static/images/eye_icon_grey.png')}" width='16' height='16' alt='display data' title='display data' class='button display' border='0'> %if user_owns_dataset: - <img src="${h.url_for('/static/images/pencil_icon_grey.png')}" width='16' height='16' alt='edit attributes' title='edit attributes' class='button edit' border='0'> - %endif + <img src="${h.url_for('/static/images/pencil_icon_grey.png')}" width='16' height='16' alt='edit attributes' title='edit attributes' class='button edit' border='0'> + %endif %else: - <a class="icon-button display" title="display data" href="${h.url_for( controller='dataset', action='display', dataset_id=trans.security.encode_id( data.id ), preview=True, filename='' )}" target="galaxy_main"></a> + <a class="icon-button display" title="display data" href="${h.url_for( controller='dataset', action='display', dataset_id=trans.security.encode_id( data.id ), preview=True, filename='' )}" target="galaxy_main"></a> %if user_owns_dataset: - <a class="icon-button edit" title="edit attributes" href="${h.url_for( controller='root', action='edit', id=data.id )}" target="galaxy_main"></a> - %endif + <a class="icon-button edit" title="edit attributes" href="${h.url_for( controller='root', action='edit', id=data.id )}" target="galaxy_main"></a> + %endif %endif %if user_owns_dataset: - <a class="icon-button delete" title="delete" href="${h.url_for( action='delete', id=data.id, show_deleted_on_refresh=show_deleted_on_refresh )}" id="historyItemDeleter-${data.id}"></a> - %endif - </div> - <span class="state-icon"></span> - <span class="historyItemTitle">${hid}: ${data.display_name()}</span> - </div> + <a class="icon-button delete" title="delete" href="${h.url_for( action='delete', id=data.id, show_deleted_on_refresh=show_deleted_on_refresh )}" id="historyItemDeleter-${data.id}"></a> + %endif + </div> + <span class="state-icon"></span> + <span class="historyItemTitle">${hid}: ${data.display_name()}</span> + </div> ## Body for history items, extra info and actions, data "peek" @@ -61,10 +61,10 @@ <div> An error occurred running this job: <i>${data.display_info().strip()}</i> </div> - <div> - <a href="${h.url_for( controller='dataset', action='errors', id=data.id )}" target="galaxy_main">report this error</a> - | <a href="${h.url_for( controller='tool_runner', action='rerun', id=data.id )}" target="galaxy_main">rerun</a> - </div> + <div> + <a href="${h.url_for( controller='dataset', action='errors', id=data.id )}" target="galaxy_main">report this error</a> + | <a href="${h.url_for( controller='tool_runner', action='rerun', id=data.id )}" target="galaxy_main">rerun</a> + </div> %elif data_state == "discarded": <div> The job creating this dataset was cancelled before completion. @@ -88,16 +88,16 @@ <div> %if data.has_data: <a href="${h.url_for( controller='dataset', action='display', dataset_id=trans.security.encode_id( data.id ), to_ext=data.ext )}">save</a> - %if user_owns_dataset: - | <a href="${h.url_for( controller='tool_runner', action='rerun', id=data.id )}" target="galaxy_main">rerun</a> - %endif + %if user_owns_dataset: + | <a href="${h.url_for( controller='tool_runner', action='rerun', id=data.id )}" target="galaxy_main">rerun</a> + %endif %for display_app in data.datatype.get_display_types(): <% target_frame, display_links = data.datatype.get_display_links( data, display_app, app, request.base ) %> %if len( display_links ) > 0: | ${data.datatype.get_display_label(display_app)} - %for display_name, display_link in display_links: - <a target="${target_frame}" href="${display_link}">${_(display_name)}</a> - %endfor + %for display_name, display_link in display_links: + <a target="${target_frame}" href="${display_link}">${_(display_name)}</a> + %endfor %endif %endfor %endif @@ -105,17 +105,17 @@ %if data.peek != "no peek": <div><pre id="peek${data.id}" class="peek">${_(data.display_peek())}</pre></div> %endif - %else: - <div>${_('Error: unknown dataset state "%s".') % data_state}</div> + %else: + <div>${_('Error: unknown dataset state "%s".') % data_state}</div> %endif ## Recurse for child datasets %if len( data.children ) > 0: - ## FIXME: This should not be in the template, there should - ## be a 'visible_children' method on dataset. + ## FIXME: This should not be in the template, there should + ## be a 'visible_children' method on dataset. <% - children = [] + children = [] for child in data.children: if child.visible: children.append( child ) diff -r 1a3339f017e9 -r 63201eefad88 templates/sharing_base.mako --- a/templates/sharing_base.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/sharing_base.mako Wed Feb 03 11:27:21 2010 -0500 @@ -12,172 +12,172 @@ ## <%def name="title()"> - Sharing and Publishing ${get_class_display_name( item.__class__ )} '${get_item_name( item )}' + Sharing and Publishing ${get_class_display_name( item.__class__ )} '${get_item_name( item )}' </%def> <%def name="stylesheets()"> ${parent.stylesheets()} - <style> - div.indent - { - margin-left: 1em; - } - input.action-button - { - margin-left: 0; - } - </style> + <style> + div.indent + { + margin-left: 1em; + } + input.action-button + { + margin-left: 0; + } + </style> </%def> <%def name="body()"> - <% - # - # Setup and variables needed for page. - # - - # Get class name strings. - item_class_name = get_class_display_name( item.__class__ ) - item_class_name_lc = item_class_name.lower() - item_class_plural_name = get_class_plural_display_name( item.__class__ ) - item_class_plural_name_lc = item_class_plural_name.lower() - %> - <% item_name = get_item_name(item) %> + <% + # + # Setup and variables needed for page. + # + + # Get class name strings. + item_class_name = get_class_display_name( item.__class__ ) + item_class_name_lc = item_class_name.lower() + item_class_plural_name = get_class_plural_display_name( item.__class__ ) + item_class_plural_name_lc = item_class_plural_name.lower() + %> + <% item_name = get_item_name(item) %> - <h2>Sharing and Publishing ${item_class_name} '${item_name}'</h2> + <h2>Sharing and Publishing ${item_class_name} '${item_name}'</h2> - ## Require that user have a public username before sharing or publishing an item. - %if trans.get_user().username is None or trans.get_user().username is "": - To make a ${item_class_name_lc} accessible via link or publish it, you must create a public username: - <p> - <form action="${h.url_for( action='set_public_username', id=trans.security.encode_id( item.id ) )}" - method="POST"> - <div class="form-row"> - <label>Public Username:</label> - <div class="form-row-input"> - <input type="text" name="username" size="40"/> - </div> - </div> - <div style="clear: both"></div> - <div class="form-row"> - <input class="action-button" type="submit" name="Set Username" value="Set Username"/> - </div> - </form> - %else: - ## User has a public username, so private sharing and publishing options. - <div class="indent" style="margin-top: 2em"> - <h3>Making ${item_class_name} Accessible via Link and Publishing It</h3> + ## Require that user have a public username before sharing or publishing an item. + %if trans.get_user().username is None or trans.get_user().username is "": + To make a ${item_class_name_lc} accessible via link or publish it, you must create a public username: + <p> + <form action="${h.url_for( action='set_public_username', id=trans.security.encode_id( item.id ) )}" + method="POST"> + <div class="form-row"> + <label>Public Username:</label> + <div class="form-row-input"> + <input type="text" name="username" size="40"/> + </div> + </div> + <div style="clear: both"></div> + <div class="form-row"> + <input class="action-button" type="submit" name="Set Username" value="Set Username"/> + </div> + </form> + %else: + ## User has a public username, so private sharing and publishing options. + <div class="indent" style="margin-top: 2em"> + <h3>Making ${item_class_name} Accessible via Link and Publishing It</h3> - <div> - %if item.importable: - <% - item_status = "accessible via link" - if item.published: - item_status = item_status + " and published" - %> - This ${item_class_name_lc} <strong>${item_status}</strong>. - <div> - <p>Anyone can view and import this ${item_class_name_lc} by visiting the following URL: - <% url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True ) %> - <blockquote> - <a href="${url}" target="_top">${url}</a> - </blockquote> - - %if item.published: - This ${item_class_name_lc} is publicly listed and searchable in Galaxy's <a href='${h.url_for( action='list_published' )}' target="_top">Published ${item_class_plural_name}</a> section. - %endif - </div> - - <p>You can: - <div> - <form action="${h.url_for( action='sharing', id=trans.security.encode_id( item.id ) )}" - method="POST"> - %if not item.published: - ## Item is importable but not published. User can disable importable or publish. - <input class="action-button" type="submit" name="disable_link_access" value="Disable Access to ${item_class_name} Link"> - <div class="toolParamHelp">Disables ${item_class_name_lc}'s link so that it is not accessible.</div> - <br> - <input class="action-button" type="submit" name="publish" value="Publish ${item_class_name}" method="POST"> - <div class="toolParamHelp">Publishes the ${item_class_name_lc} to Galaxy's <a href='${h.url_for( action='list_published' )}' target="_top">Published ${item_class_plural_name}</a> section, where it is publicly listed and searchable.</div> + <div> + %if item.importable: + <% + item_status = "accessible via link" + if item.published: + item_status = item_status + " and published" + %> + This ${item_class_name_lc} <strong>${item_status}</strong>. + <div> + <p>Anyone can view and import this ${item_class_name_lc} by visiting the following URL: + <% url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True ) %> + <blockquote> + <a href="${url}" target="_top">${url}</a> + </blockquote> + + %if item.published: + This ${item_class_name_lc} is publicly listed and searchable in Galaxy's <a href='${h.url_for( action='list_published' )}' target="_top">Published ${item_class_plural_name}</a> section. + %endif + </div> + + <p>You can: + <div> + <form action="${h.url_for( action='sharing', id=trans.security.encode_id( item.id ) )}" + method="POST"> + %if not item.published: + ## Item is importable but not published. User can disable importable or publish. + <input class="action-button" type="submit" name="disable_link_access" value="Disable Access to ${item_class_name} Link"> + <div class="toolParamHelp">Disables ${item_class_name_lc}'s link so that it is not accessible.</div> + <br> + <input class="action-button" type="submit" name="publish" value="Publish ${item_class_name}" method="POST"> + <div class="toolParamHelp">Publishes the ${item_class_name_lc} to Galaxy's <a href='${h.url_for( action='list_published' )}' target="_top">Published ${item_class_plural_name}</a> section, where it is publicly listed and searchable.</div> - <br> - %else: ## item.published == True - ## Item is importable and published. User can unpublish or disable import and unpublish. - <input class="action-button" type="submit" name="unpublish" value="Unpublish ${item_class_name}"> - <div class="toolParamHelp">Removes ${item_class_name_lc} from Galaxy's <a href='${h.url_for( action='list_published' )}' target="_top">Published ${item_class_plural_name}</a> section so that it is not publicly listed or searchable.</div> - <br> - <input class="action-button" type="submit" name="disable_link_access_and_unpubish" value="Disable Access to ${item_class_name} via Link and Unpublish"> - <div class="toolParamHelp">Disables ${item_class_name_lc}'s link so that it is not accessible and removes ${item_class_name_lc} from Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published ${item_class_plural_name}</a> section so that it is not publicly listed or searchable.</div> - %endif - - </form> - </div> + <br> + %else: ## item.published == True + ## Item is importable and published. User can unpublish or disable import and unpublish. + <input class="action-button" type="submit" name="unpublish" value="Unpublish ${item_class_name}"> + <div class="toolParamHelp">Removes ${item_class_name_lc} from Galaxy's <a href='${h.url_for( action='list_published' )}' target="_top">Published ${item_class_plural_name}</a> section so that it is not publicly listed or searchable.</div> + <br> + <input class="action-button" type="submit" name="disable_link_access_and_unpubish" value="Disable Access to ${item_class_name} via Link and Unpublish"> + <div class="toolParamHelp">Disables ${item_class_name_lc}'s link so that it is not accessible and removes ${item_class_name_lc} from Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published ${item_class_plural_name}</a> section so that it is not publicly listed or searchable.</div> + %endif + + </form> + </div> - %else: + %else: - This ${item_class_name_lc} is currently restricted so that only you and the users listed below can access it. You can: - <p> - <form action="${h.url_for( action='sharing', id=trans.security.encode_id(item.id) )}" method="POST"> - <input class="action-button" type="submit" name="make_accessible_via_link" value="Make ${item_class_name} Accessible via Link"> - <div class="toolParamHelp">Generates a web link that you can share with other people so that they can view and import the ${item_class_name_lc}.</div> - - <br> - <input class="action-button" type="submit" name="make_accessible_and_publish" value="Make ${item_class_name} Accessible and Publish" method="POST"> - <div class="toolParamHelp">Makes the ${item_class_name_lc} accessible via link (see above) and publishes the ${item_class_name_lc} to Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published ${item_class_plural_name}</a> section, where it is publicly listed and searchable.</div> - </form> + This ${item_class_name_lc} is currently restricted so that only you and the users listed below can access it. You can: + <p> + <form action="${h.url_for( action='sharing', id=trans.security.encode_id(item.id) )}" method="POST"> + <input class="action-button" type="submit" name="make_accessible_via_link" value="Make ${item_class_name} Accessible via Link"> + <div class="toolParamHelp">Generates a web link that you can share with other people so that they can view and import the ${item_class_name_lc}.</div> + + <br> + <input class="action-button" type="submit" name="make_accessible_and_publish" value="Make ${item_class_name} Accessible and Publish" method="POST"> + <div class="toolParamHelp">Makes the ${item_class_name_lc} accessible via link (see above) and publishes the ${item_class_name_lc} to Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published ${item_class_plural_name}</a> section, where it is publicly listed and searchable.</div> + </form> - %endif - </div> + %endif + </div> - <h3>Sharing ${item_class_name} with Specific Users</h3> + <h3>Sharing ${item_class_name} with Specific Users</h3> - <div> - %if item.users_shared_with: + <div> + %if item.users_shared_with: - <p> - The following users will see this ${item_class_name_lc} in their ${item_class_name_lc} list and will be - able to run/view and import it. - </p> + <p> + The following users will see this ${item_class_name_lc} in their ${item_class_name_lc} list and will be + able to run/view and import it. + </p> - <table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%"> - <tr class="header"> - <th>Email</th> - <th></th> - </tr> - %for i, association in enumerate( item.users_shared_with ): - <% user = association.user %> - <tr> - <td> - ${user.email} - <a id="user-${i}-popup" class="popup-arrow" style="display: none;">▼</a> - </td> - <td> - <div popupmenu="user-${i}-popup"> - <a class="action-button" href="${h.url_for( action='sharing', id=trans.security.encode_id( item.id ), unshare_user=trans.security.encode_id( user.id ) )}">Unshare</a> - </div> - </td> - </tr> - %endfor - </table> - - <p> - <a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(item.id) )}"> - <span>Share with another user</span> - </a> + <table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%"> + <tr class="header"> + <th>Email</th> + <th></th> + </tr> + %for i, association in enumerate( item.users_shared_with ): + <% user = association.user %> + <tr> + <td> + ${user.email} + <a id="user-${i}-popup" class="popup-arrow" style="display: none;">▼</a> + </td> + <td> + <div popupmenu="user-${i}-popup"> + <a class="action-button" href="${h.url_for( action='sharing', id=trans.security.encode_id( item.id ), unshare_user=trans.security.encode_id( user.id ) )}">Unshare</a> + </div> + </td> + </tr> + %endfor + </table> + + <p> + <a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(item.id) )}"> + <span>Share with another user</span> + </a> - %else: + %else: - <p>You have not shared this ${item_class_name_lc} with any users.</p> + <p>You have not shared this ${item_class_name_lc} with any users.</p> - <a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(item.id) )}"> - <span>Share with a user</span> - </a> - <br> + <a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(item.id) )}"> + <span>Share with a user</span> + </a> + <br> - %endif - </div> - </div> - %endif + %endif + </div> + </div> + %endif - <p><br><br> - <a href=${h.url_for( action="list" )}>Back to ${item_class_plural_name} List</a> + <p><br><br> + <a href=${h.url_for( action="list" )}>Back to ${item_class_plural_name} List</a> </%def> \ No newline at end of file diff -r 1a3339f017e9 -r 63201eefad88 templates/workflow/edit_attributes.mako --- a/templates/workflow/edit_attributes.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/workflow/edit_attributes.mako Wed Feb 03 11:27:21 2010 -0500 @@ -17,21 +17,21 @@ %endif <%def name="body()"> - <div class="toolForm"> - <div class="toolFormTitle">${_('Edit Workflow Attributes')}</div> - <div class="toolFormBody"> - <form name="edit_attributes" action="${h.url_for( action='edit_attributes' )}" method="post"> - <input type="hidden" name="id" value="${trans.security.encode_id( stored.id )}"/> - <div class="form-row"> - <label> - Name: - </label> - <div style="float: left; width: 225px; margin-right: 10px;"> - <input type="text" name="name" value="${stored.name}" size="30"/> - </div> + <div class="toolForm"> + <div class="toolFormTitle">${_('Edit Workflow Attributes')}</div> + <div class="toolFormBody"> + <form name="edit_attributes" action="${h.url_for( action='edit_attributes' )}" method="post"> + <input type="hidden" name="id" value="${trans.security.encode_id( stored.id )}"/> + <div class="form-row"> + <label> + Name: + </label> + <div style="float: left; width: 225px; margin-right: 10px;"> + <input type="text" name="name" value="${stored.name}" size="30"/> + </div> <div style="clear: both"></div> - </div> - <%namespace file="/tagging_common.mako" import="render_individual_tagging_element" /> + </div> + <%namespace file="/tagging_common.mako" import="render_individual_tagging_element" /> <div class="form-row"> <label> Tags: @@ -57,10 +57,10 @@ <div style="clear: both"></div> <div class="toolParamHelp">Add an annotation notes to a workflow; annotations are available when a workflow is viewed.</div> </div> - <div class="form-row"> - <input type="submit" name="save" value="${_('Save')}"/> - </div> - </form> - </div> - </div> + <div class="form-row"> + <input type="submit" name="save" value="${_('Save')}"/> + </div> + </form> + </div> + </div> </%def> \ No newline at end of file diff -r 1a3339f017e9 -r 63201eefad88 templates/workflow/editor.mako --- a/templates/workflow/editor.mako Wed Feb 03 10:31:26 2010 -0500 +++ b/templates/workflow/editor.mako Wed Feb 03 11:27:21 2010 -0500 @@ -218,18 +218,17 @@ }); }); - // Rename async. - async_save_text("workflow-rename", "workflow-name", "${h.url_for( action="rename_async", id=trans.security.encode_id(stored.id) )}", "new_name"); - - // Tag async. Simply have the workflow tag element generate a click on the tag element to activate tagging. - $('#workflow-tag').click( function() - { - $('.tag-area').click(); - return false; - }); - - // Annotate async. - async_save_text("workflow-annotate", "workflow-annotation", "${h.url_for( action="annotate_async", id=trans.security.encode_id(stored.id) )}", "new_annotation", true, 4); + // Rename async. + async_save_text("workflow-rename", "workflow-name", "${h.url_for( action="rename_async", id=trans.security.encode_id(stored.id) )}", "new_name"); + + // Tag async. Simply have the workflow edit element generate a click on the tag element to activate tagging. + $('#workflow-tag').click( function() + { + $('.tag-area').click(); + return false; + }); + // Annotate async. + async_save_text("workflow-annotate", "workflow-annotation", "${h.url_for( action="annotate_async", id=trans.security.encode_id(stored.id) )}", "new_annotation", true, 4); }); // Global state for the whole workflow @@ -338,17 +337,17 @@ $(this).remove(); make_popupmenu( b, options ); }); - // Add annotation field to form. - // TODO: need to set the annotation for this tool. - var annotation_div = - $( "<div class='form-row'> \ - <label>Annotation / Notes:</label> \ - <div style='margin-right: 10px;'> \ - <textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \ - <div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \ - </div> \ - </div>"); - $(this).append( annotation_div ); + // Add annotation field to form. + // TODO: need to set the annotation for this tool. + var annotation_div = + $( "<div class='form-row'> \ + <label>Annotation / Notes:</label> \ + <div style='margin-right: 10px;'> \ + <textarea name='annotation' rows='3' style='width: 100%'>" + node.annotation + "</textarea> \ + <div class='toolParamHelp'>Add an annotation or notes to this step; annotations are available when a workflow is viewed.</div> \ + </div> \ + </div>"); + $(this).append( annotation_div ); // Implements auto-saving based on whether the inputs change. We consider // "changed" to be when a field is accessed and not necessarily modified // because of an issue where "onchange" is not triggered when activating @@ -777,23 +776,23 @@ </div> </div> <div class="unified-panel-body" style="overflow: auto;"> - ## Div for elements to modify workflow attributes. - <div id="edit-attributes" class="toolForm right-content"> - <div class="toolFormTitle">Edit Workflow Attributes</div> - <div class="toolFormBody"> - ## Workflow name. - <div id="workflow-name-area" class="form-row"> - <label>Name:</label> - <div style="float: right"><a id="workflow-rename" title="Rename" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='rename_sync' )}"></a></div> - <div id="workflow-name">${stored.name}</div> - <div style="clear: both"></div> - </div> - ## Workflow tags. - <%namespace file="/tagging_common.mako" import="render_individual_tagging_element" /> - <div class="form-row"> - <label> - Tags: - </label> + ## Div for elements to modify workflow attributes. + <div id="edit-attributes" class="toolForm right-content"> + <div class="toolFormTitle">Edit Workflow Attributes</div> + <div class="toolFormBody"> + ## Workflow name. + <div id="workflow-name-area" class="form-row"> + <label>Name:</label> + <div style="float: right"><a id="workflow-rename" title="Rename" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='rename_sync' )}"></a></div> + <div id="workflow-name">${stored.name}</div> + <div style="clear: both"></div> + </div> + ## Workflow tags. + <%namespace file="/tagging_common.mako" import="render_individual_tagging_element" /> + <div class="form-row"> + <label> + Tags: + </label> <div style="float: right"><a id="workflow-tag" title="Tag" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div> <div style="float: left; width: 225px; margin-right: 10px; border-style: inset; border-width: 1px; margin-left: 2px"> <style> @@ -806,17 +805,17 @@ <div style="clear: both"></div> <div class="toolParamHelp">Apply tags to make it easy to search for and find items with the same tag.</div> </div> - ## Workflow annotation. - <div id="workflow-annotation-area" class="form-row"> - <label>Annotation / Notes:</label> - <div style="float: right"><a id="workflow-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div> - <div id="workflow-annotation">${annotation}</div> + ## Workflow annotation. + <div id="workflow-annotation-area" class="form-row"> + <label>Annotation / Notes:</label> + <div style="float: right"><a id="workflow-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div> + <div id="workflow-annotation">${annotation}</div> <div style="clear: both"></div> - <div class="toolParamHelp">Add an annotation or notes to a workflow; annotations are available when a workflow is viewed.</div> - </div> - </div> - </div> - ## Div where tool details are loaded and modified. - <div id="right-content" class="right-content"></div> + <div class="toolParamHelp">Add an annotation or notes to a workflow; annotations are available when a workflow is viewed.</div> + </div> + </div> + </div> + ## Div where tool details are loaded and modified. + <div id="right-content" class="right-content"></div> </div> </%def>