lists.galaxyproject.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
List overview
Download
galaxy-dev
May 2009
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
galaxy-dev@lists.galaxyproject.org
9 participants
41 discussions
Start a n
N
ew thread
[hg] galaxy 2401: Fixes for deleting library items on the admin ...
by Nate Coraor
05 May '09
05 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/2e2b80fcbd47
changeset: 2401:2e2b80fcbd47 user: Greg Von Kuster <greg(a)bx.psu.edu> date: Tue May 05 13:48:01 2009 -0400 description: Fixes for deleting library items on the admin side. - Purged library items will not be displayed - Deleted library items can only be viewed or undeleted - Differentiate between displaying deleted libraries and displaying deleted items within an undeleted library 8 file(s) affected in this change: lib/galaxy/web/controllers/admin.py lib/galaxy/web/controllers/library.py templates/admin/dataset_security/group_create.mako templates/admin/library/browse_libraries.mako templates/admin/library/browse_library.mako templates/admin/library/common.mako templates/admin/library/ldda_info.mako templates/library/ldda_info.mako diffs (551 lines): diff -r 8da91a231cdf -r 2e2b80fcbd47 lib/galaxy/web/controllers/admin.py --- a/lib/galaxy/web/controllers/admin.py Tue May 05 13:03:23 2009 -0400 +++ b/lib/galaxy/web/controllers/admin.py Tue May 05 13:48:01 2009 -0400 @@ -678,6 +678,7 @@ libraries=trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted==False ) \ .order_by( trans.app.model.Library.name ).all(), deleted=False, + show_deleted=False, msg=msg, messagetype=messagetype ) @web.expose @@ -687,6 +688,8 @@ msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) id = params.get( 'id', None ) + deleted = util.string_as_bool( params.get( 'deleted', False ) ) + show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) if not id: msg = "You must specify a library id." return trans.response.send_redirect( web.url_for( controller='admin', @@ -701,9 +704,9 @@ msg=util.sanitize_text( msg ), messagetype='error' ) ) created_ldda_ids = params.get( 'created_ldda_ids', '' ) - show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) return trans.fill_template( '/admin/library/browse_library.mako', library=trans.app.model.Library.get( id ), + deleted=deleted, created_ldda_ids=created_ldda_ids, msg=msg, messagetype=messagetype, @@ -842,7 +845,7 @@ deleted=True, msg=msg, messagetype=messagetype, - show_deleted = True ) + show_deleted=True ) @web.expose @web.require_admin def undelete_library( self, trans, **kwd ): @@ -1088,7 +1091,9 @@ def library_dataset_dataset_association( self, trans, library_id, folder_id, id=None, **kwd ): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) - messagetype = params.get( 'messagetype', 'done' ) + messagetype = params.get( 'messagetype', 'done' ) + deleted = util.string_as_bool( params.get( 'deleted', False ) ) + show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) dbkey = params.get( 'dbkey', None ) if isinstance( dbkey, list ): last_used_build = dbkey[0] @@ -1250,6 +1255,8 @@ return trans.fill_template( '/admin/library/ldda_info.mako', ldda=ldda, library_id=library_id, + deleted=deleted, + show_deleted=show_deleted, msg=msg, messagetype=messagetype ) elif action == 'edit_info': @@ -1322,8 +1329,6 @@ msg=msg, messagetype=messagetype ) elif params.get( 'delete', False ): - # TODO: need to revamp the way we remove datasets from disk. - # The user selected the "Remove this dataset from the library" pop-up menu option ldda.deleted = True ldda.flush() msg = 'Dataset %s has been removed from this library' % ldda.name @@ -1955,69 +1960,56 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype=messagetype ) ) - @web.expose @web.require_admin - def delete_library_item( self, trans, library_id = None, library_item_id = None, library_item_type = None ): - #this action will handle deleting all types of library items in library browsing mode - library_item_types = { 'library': trans.app.model.Library, 'folder': trans.app.model.LibraryFolder, 'dataset': trans.app.model.LibraryDataset, } + def delete_library_item( self, trans, library_id, library_item_id, library_item_type ): + # This action will handle deleting all types of library items. State is saved for libraries and + # folders ( i.e., if undeleted, the state of contents of the library or folder will remain, so previously + # deleted / purged contents will have the same state ). When a library or folder has been deleted for + # the amount of time defined in the cleanup_datasets.py script, the library or folder and all of its + # contents will be purged. The association between this method and the cleanup_datasets.py script + # enables clean maintenance of libraries and library dataset disk files. This is also why the following + # 3 objects, and not any of the associations ( the cleanup_datasets.py scipot handles everything else ). + library_item_types = { 'library': trans.app.model.Library, + 'folder': trans.app.model.LibraryFolder, + 'library_dataset': trans.app.model.LibraryDataset } if library_item_type not in library_item_types: - raise ValueError( 'Bad library_item_type specified: %s' % library_item_types ) - if library_item_id is None: - raise ValueError( 'library_item_id not specified' ) - library_item = library_item_types[ library_item_type ].get( int( library_item_id ) ) - library_item.deleted = True - library_item.flush() - #need to str because unicode isn't accepted... - msg = str( "%s '%s' has been marked deleted" % ( library_item_type, library_item.name ) ) - messagetype = str( "done" ) - if library_item_type == 'library' or library_id is None: - return self.browse_libraries( trans, msg = msg, messagetype = messagetype ) + msg = 'Bad library_item_type specified: %s' % str( library_item_type ) + messagetype = 'error' else: - return self.browse_library( trans, id = library_id , msg = msg, messagetype = messagetype ) - + library_item = library_item_types[ library_item_type ].get( int( library_item_id ) ) + library_item.deleted = True + library_item.flush() + msg = util.sanitize_text( "%s '%s' has been marked deleted" % ( library_item_type, library_item.name ) ) + messagetype = 'done' + if library_item_type == 'library': + return self.browse_libraries( trans, msg=msg, messagetype=messagetype ) + else: + return self.browse_library( trans, id=library_id , msg=msg, messagetype=messagetype ) @web.expose @web.require_admin - def undelete_library_item( self, trans, library_id = None, library_item_id = None, library_item_type = None ): - #this action will handle deleting all types of library items in library browsing mode - library_item_types = { 'library': trans.app.model.Library, 'folder': trans.app.model.LibraryFolder, 'dataset': trans.app.model.LibraryDataset, } + def undelete_library_item( self, trans, library_id, library_item_id, library_item_type ): + # This action will handle undeleting all types of library items + library_item_types = { 'library': trans.app.model.Library, + 'folder': trans.app.model.LibraryFolder, + 'library_dataset': trans.app.model.LibraryDataset } if library_item_type not in library_item_types: - raise ValueError( 'Bad library_item_type specified: %s' % library_item_types ) - if library_item_id is None: - raise ValueError( 'library_item_id not specified' ) - library_item = library_item_types[ library_item_type ].get( int( library_item_id ) ) - if library_item.purged: - raise ValueError( '%s %s cannot be undeleted' % ( library_item_type, library_item.name ) ) - library_item.deleted = False - library_item.flush() - msg = str( "%s '%s' has been undeleted" % ( library_item_type, library_item.name ) ) - messagetype = str( "done" ) - if library_item_type == 'library' or library_id is None: - return self.browse_libraries( trans, msg = msg, messagetype = messagetype ) + msg = 'Bad library_item_type specified: %s' % str( library_item_type ) + messagetype = 'error' else: - return self.browse_library( trans, id = library_id , msg = msg, messagetype = messagetype ) - - - - #(a)web.expose - #(a)web.require_admin - #def delete_dataset( self, trans, id=None, **kwd): - # if id: - # # id is a LibraryDatasetDatasetAssociation.id - # ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id ) - # ldda.deleted = True - # ldda.flush() - # msg = "Dataset %s was deleted from library folder %s" % ( ldda.name, ldda.folder.name ) - # trans.response.send_redirect( web.url_for( action='folder', - # id=str( ldda.folder.id ), - # msg=util.sanitize_text( msg ), - # messagetype='done' ) ) - # msg = "You did not specify a dataset to delete." - # return trans.response.send_redirect( web.url_for( action='folder', - # id=str( ldda.folder.id ), - # msg=util.sanitize_text( msg ), - # messagetype='error' ) ) - + library_item = library_item_types[ library_item_type ].get( int( library_item_id ) ) + if library_item.purged: + msg = '%s %s has been purged, so it cannot be undeleted' % ( library_item_type, library_item.name ) + messagetype = 'error' + else: + library_item.deleted = False + library_item.flush() + msg = util.sanitize_text( "%s '%s' has been marked undeleted" % ( library_item_type, library_item.name ) ) + messagetype = 'done' + if library_item_type == 'library': + return self.browse_libraries( trans, msg=msg, messagetype=messagetype ) + else: + return self.browse_library( trans, id=library_id , msg=msg, messagetype=messagetype ) @web.expose @web.require_admin def memdump( self, trans, ids = 'None', sorts = 'None', pages = 'None', new_id = None, new_sort = None, **kwd ): diff -r 8da91a231cdf -r 2e2b80fcbd47 lib/galaxy/web/controllers/library.py --- a/lib/galaxy/web/controllers/library.py Tue May 05 13:03:23 2009 -0400 +++ b/lib/galaxy/web/controllers/library.py Tue May 05 13:48:01 2009 -0400 @@ -587,8 +587,6 @@ msg=msg, messagetype=messagetype ) elif params.get( 'delete', False ): - # TODO: need to revamp the way we remove datasets from disk. - # The user selected the "Remove this dataset from the library" pop-up menu option if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=folder ): diff -r 8da91a231cdf -r 2e2b80fcbd47 templates/admin/dataset_security/group_create.mako --- a/templates/admin/dataset_security/group_create.mako Tue May 05 13:03:23 2009 -0400 +++ b/templates/admin/dataset_security/group_create.mako Tue May 05 13:48:01 2009 -0400 @@ -57,24 +57,24 @@ </div> <div class="form-row"> <div style="float: left; margin-right: 10px;"> - <label>Groups associated with new role</label> + <label>Roles associated with new group</label> ${render_select( "in_roles", in_roles )}<br/> <input type="submit" id="roles_remove_button" value=">>"/> </div> <div> - <label>Groups not associated with new role</label> + <label>Roles not associated with new group</label> ${render_select( "out_roles", out_roles )}<br/> <input type="submit" id="roles_add_button" value="<<"/> </div> </div> <div class="form-row"> <div style="float: left; margin-right: 10px;"> - <label>Users associated with new role</label> + <label>Users associated with new group</label> ${render_select( "in_users", in_users )}<br/> <input type="submit" id="users_remove_button" value=">>"/> </div> <div> - <label>Users not associated with new role</label> + <label>Users not associated with new group</label> ${render_select( "out_users", out_users )}<br/> <input type="submit" id="users_add_button" value="<<"/> </div> diff -r 8da91a231cdf -r 2e2b80fcbd47 templates/admin/library/browse_libraries.mako --- a/templates/admin/library/browse_libraries.mako Tue May 05 13:03:23 2009 -0400 +++ b/templates/admin/library/browse_libraries.mako Tue May 05 13:48:01 2009 -0400 @@ -42,7 +42,7 @@ <tbody> %for library in libraries: <tr class="libraryRow libraryOrFolderRow" id="libraryRow"> - <td><a href="${h.url_for( controller='admin', action='browse_library', id=library.id )}">${library.name}</a></td> + <td><a href="${h.url_for( controller='admin', action='browse_library', id=library.id, deleted=deleted, show_deleted=show_deleted )}">${library.name}</a></td> <td><i>${library.description}</i></td> </tr> %endfor diff -r 8da91a231cdf -r 2e2b80fcbd47 templates/admin/library/browse_library.mako --- a/templates/admin/library/browse_library.mako Tue May 05 13:03:23 2009 -0400 +++ b/templates/admin/library/browse_library.mako Tue May 05 13:48:01 2009 -0400 @@ -72,20 +72,20 @@ } </script> -<%def name="render_folder( parent, parent_pad, deleted, created_ldda_ids, library_id )"> +<%def name="render_folder( folder, folder_pad, deleted, show_deleted, created_ldda_ids, library_id )"> <% - root_folder = not parent.parent + root_folder = not folder.parent if root_folder: - pad = parent_pad + pad = folder_pad else: - pad = parent_pad + 20 - if parent_pad == 0: + pad = folder_pad + 20 + if folder_pad == 0: expander = "/static/images/silk/resultset_bottom.png" - folder = "/static/images/silk/folder_page.png" + folder_img = "/static/images/silk/folder_page.png" subfolder = False else: expander = "/static/images/silk/resultset_next.png" - folder = "/static/images/silk/folder.png" + folder_img = "/static/images/silk/folder.png" subfolder = True created_ldda_id_list = util.listify( created_ldda_ids ) if created_ldda_id_list: @@ -93,35 +93,37 @@ %> %if not root_folder: <li class="folderRow libraryOrFolderRow" style="padding-left: ${pad}px;"> - <div class="rowTitle libraryItemDeleted-${parent.deleted}"> - <img src="${h.url_for( expander )}" class="expanderIcon"/><img src="${h.url_for( folder )}" class="rowIcon"/> - ${parent.name} - %if parent.description: - <i>- ${parent.description}</i> - %endif - <a id="folder-${parent.id}-popup" class="popup-arrow" style="display: none;">▼</a> - </div> - %if not parent.deleted: + %if not folder.deleted or show_deleted: + <div class="rowTitle libraryItemDeleted-${deleted}"> + <img src="${h.url_for( expander )}" class="expanderIcon"/><img src="${h.url_for( folder_img )}" class="rowIcon"/> + ${folder.name} + %if folder.description: + <i>- ${folder.description}</i> + %endif + <a id="folder-${folder.id}-popup" class="popup-arrow" style="display: none;">▼</a> + </div> + %endif + %if not folder.deleted: <% library_item_ids = {} - library_item_ids[ 'folder' ] = parent.id + library_item_ids[ 'folder' ] = folder.id %> - <div popupmenu="folder-${parent.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=parent.id )}">Add datasets to this folder</a> - <a class="action-button" href="${h.url_for( controller='admin', action='folder', new=True, id=parent.id, library_id=library_id )}">Create a new sub-folder in this folder</a> - <a class="action-button" href="${h.url_for( controller='admin', action='folder', information=True, id=parent.id, library_id=library_id )}">Edit this folder's information</a> - %if parent.library_folder_info_template_associations: - <% template = parent.get_library_item_info_templates( template_list=[], restrict=True )[0] %> - <a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library.id, id=template.id, edit_template=True )}">Edit this folder's information template</a> + <div popupmenu="folder-${folder.id}-popup"> + <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=folder.id )}">Add datasets to this folder</a> + <a class="action-button" href="${h.url_for( controller='admin', action='folder', new=True, id=folder.id, library_id=library_id )}">Create a new sub-folder in this folder</a> + <a class="action-button" href="${h.url_for( controller='admin', action='folder', information=True, id=folder.id, library_id=library_id )}">Edit this folder's information</a> + %if folder.library_folder_info_template_associations: + <% template = folder.get_library_item_info_templates( template_list=[], restrict=True )[0] %> + <a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library_id, id=template.id, edit_template=True )}">Edit this folder's information template</a> %else: - <a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library.id, folder_id=parent.id, new_template=True )}">Add an information template to this folder</a> + <a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library_id, folder_id=folder.id, new_template=True )}">Add an information template to this folder</a> %endif - <a class="action-button" href="${h.url_for( controller='admin', action='folder', permissions=True, id=parent.id, library_id=library_id )}">Edit this folder's permissions</a> - <a class="action-button" confirm="Click OK to delete the folder '${parent.name}'" href="${h.url_for( controller='admin', action='delete_library_item', library_id=library_id, library_item_id=parent.id, library_item_type='folder' )}">Remove this folder and its contents from the library</a> + <a class="action-button" href="${h.url_for( controller='admin', action='folder', permissions=True, id=folder.id, library_id=library_id )}">Edit this folder's permissions</a> + <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='admin', action='delete_library_item', library_id=library_id, library_item_id=folder.id, library_item_type='folder' )}">Delete this folder and its contents</a> </div> - %else: - <div popupmenu="folder-${parent.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_id=library_id, library_item_id=parent.id, library_item_type='folder' )}">Undelete this folder</a> + %elif not deleted and folder.deleted and not folder.purged: + <div popupmenu="folder-${folder.id}-popup"> + <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_id=library_id, library_item_id=folder.id, library_item_type='folder' )}">Undelete this folder</a> </div> %endif </li> @@ -131,31 +133,31 @@ %else: <ul> %endif - %if deleted: + %if show_deleted: <% - parent_folders = parent.activatable_folders - parent_datasets = parent.activatable_datasets + parent_folders = folder.activatable_folders + parent_datasets = folder.activatable_datasets %> %else: <% - parent_folders = parent.active_folders - parent_datasets = parent.active_datasets + parent_folders = folder.active_folders + parent_datasets = folder.active_datasets %> %endif %for folder in name_sorted( parent_folders ): - ${render_folder( folder, pad, deleted, created_ldda_ids, library.id )} + ${render_folder( folder, pad, deleted, show_deleted, created_ldda_ids, library_id )} %endfor %for library_dataset in name_sorted( parent_datasets ): <% selected = created_ldda_ids and library_dataset.library_dataset_dataset_association.id in created_ldda_ids %> - <li class="datasetRow" style="padding-left: ${pad + 18}px;">${render_dataset( library_dataset, selected, library )}</li> + <li class="datasetRow" style="padding-left: ${pad + 18}px;">${render_dataset( library_dataset, selected, library, deleted, show_deleted )}</li> %endfor </ul> </%def> <h2> - %if library.deleted: + %if deleted: Deleted %endif Library '${library.name}' @@ -183,7 +185,7 @@ <table cellspacing="0" cellpadding="0" border="0" width="100%" class="libraryTitle"> <th width="*"> <img src="${h.url_for( '/static/images/silk/resultset_bottom.png' )}" class="expanderIcon"/><img src="${h.url_for( '/static/images/silk/book_open.png' )}" class="rowIcon"/> - <span class="libraryItemDeleted-${library.deleted}"> + <span class="libraryItemDeleted-${deleted}"> ${library.name} %if library.description: <i>- ${library.description}</i> @@ -191,7 +193,7 @@ </span> <a id="library-${library.id}-popup" class="popup-arrow" style="display: none;">▼</a> <div popupmenu="library-${library.id}-popup"> - %if not library.deleted: + %if not deleted: <% library_item_ids = {} library_item_ids[ 'library' ] = library.id @@ -205,14 +207,14 @@ <a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library.id, new_template=True )}">Add an information template to this library</a> %endif <a class="action-button" href="${h.url_for( controller='admin', action='library', id=library.id, permissions=True )}">Edit this library's permissions</a> - <a class="action-button" confirm="Current state will not be saved, so undeleting the library will restore all of its contents. Click OK to delete the library named '${library.name}'?" href="${h.url_for( controller='admin', action='delete_library_item', library_item_type='library', library_item_id=library.id )}">Delete this library and its contents</a> + <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='admin', action='delete_library_item', library_id=library.id, library_item_id=library.id, library_item_type='library' )}">Delete this library and its contents</a> %if show_deleted: <a class="action-button" href="${h.url_for( controller='admin', action='browse_library', id=library.id, show_deleted=False )}">Hide deleted library items</a> %else: <a class="action-button" href="${h.url_for( controller='admin', action='browse_library', id=library.id, show_deleted=True )}">Show deleted library items</a> %endif %elif not library.purged: - <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_item_type='library', library_item_id=library.id )}">Undelete this library</a> + <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_id=library.id, library_item_id=library.id, library_item_type='library' )}">Undelete this library</a> %endif </div> </th> @@ -223,16 +225,16 @@ </div> </li> <ul> - ${render_folder( library.root_folder, 0, library.deleted or show_deleted, created_ldda_ids, library.id )} + ${render_folder( library.root_folder, 0, deleted, show_deleted, created_ldda_ids, library.id )} </ul> <br/> </ul> - %if not library.deleted: + %if not deleted and not show_deleted: <p> <b>Perform action on selected datasets:</b> <select name="action" id="action_on_datasets_select"> <option value="edit">Edit selected datasets' permissions</option> - ##TODO: fix deleting library items<option value="delete">Remove selected datasets from this library</option> + <option value="delete">Delete selected datasets</option> </select> <input type="submit" class="primary-button" name="action_on_datasets_button" id="action_on_datasets_button" value="Go"/> </p> diff -r 8da91a231cdf -r 2e2b80fcbd47 templates/admin/library/common.mako --- a/templates/admin/library/common.mako Tue May 05 13:03:23 2009 -0400 +++ b/templates/admin/library/common.mako Tue May 05 13:48:01 2009 -0400 @@ -1,6 +1,6 @@ <% from time import strftime %> -<%def name="render_dataset( library_dataset, selected, library, show_deleted = False )"> +<%def name="render_dataset( library_dataset, selected, library, deleted, show_deleted )"> <% ## The received data must always be a LibraryDataset object, but the object id passed to methods from the drop down menu ## should be the underlying ldda id to prevent id collision ( which could happen when displaying children, which are always @@ -28,10 +28,10 @@ <input type="checkbox" name="ldda_ids" value="${ldda.id}"/> %endif <span class="libraryItemDeleted-${library_dataset.deleted}"> - <a href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, info=True )}"><b>${ldda.name[:50]}</b></a> + <a href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, info=True, deleted=deleted, show_deleted=show_deleted )}"><b>${ldda.name[:50]}</b></a> </span> <a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a> - %if not library_dataset.deleted: + %if not library.deleted and not library_dataset.folder.deleted and not library_dataset.deleted: <% library_item_ids = {} library_item_ids[ 'ldda' ] = ldda.id @@ -47,12 +47,11 @@ %if ldda.has_data: <a class="action-button" href="${h.url_for( controller='admin', action='download_dataset_from_folder', id=ldda.id, library_id=library.id )}">Download this dataset</a> %endif - ##TODO: need to revamp the way we remove datasets from disk. - <a class="action-button" confirm="Click OK to remove dataset '${ldda.name}'?" href="${h.url_for( controller='admin', action='delete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='dataset' )}">Remove this dataset from the library</a> + <a class="action-button" confirm="Click OK to delete dataset '${ldda.name}'." href="${h.url_for( controller='admin', action='delete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='library_dataset' )}">Delete this dataset</a> </div> - %else: + %elif not library.deleted and not library_dataset.folder.deleted and library_dataset.deleted: <div popupmenu="dataset-${ldda.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='dataset' )}">Undelete this dataset</a> + <a class="action-button" href="${h.url_for( controller='admin', action='undelete_library_item', library_id=library.id, library_item_id=library_dataset.id, library_item_type='library_dataset' )}">Undelete this dataset</a> </div> %endif </td> diff -r 8da91a231cdf -r 2e2b80fcbd47 templates/admin/library/ldda_info.mako --- a/templates/admin/library/ldda_info.mako Tue May 05 13:03:23 2009 -0400 +++ b/templates/admin/library/ldda_info.mako Tue May 05 13:48:01 2009 -0400 @@ -5,6 +5,7 @@ <% from galaxy import util %> <% + library = trans.app.model.Library.get( library_id ) if ldda == ldda.library_dataset.library_dataset_dataset_association: current_version = True else: @@ -20,7 +21,7 @@ <ul class="manage-table-actions"> <li> - <a class="action-button" href="${h.url_for( controller='admin', action='browse_library', id=library_id )}"><span>Browse this library</span></a> + <a class="action-button" href="${h.url_for( controller='admin', action='browse_library', id=library_id, deleted=library.deleted, show_deleted=show_deleted )}"><span>Browse this library</span></a> </li> </ul> @@ -38,21 +39,24 @@ <div class="toolForm"> <div class="toolFormTitle"> Information about ${ldda.name} - <a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a> - <div popupmenu="dataset-${ldda.id}-popup"> - <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a> - ## We're disabling the ability to add templates at the LDDA and LibraryDataset level, but will leave this here for possible future use - ##<a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library_id, library_dataset_id=ldda.library_dataset.id, new_template=True )}">Add an information template to this dataset</a> - <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a> - %if current_version: - <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, replace_id=ldda.library_dataset.id )}">Upload a new version of this dataset</a> - %endif - %if ldda.has_data: - <a class="action-button" href="${h.url_for( controller='admin', action='download_dataset_from_folder', id=ldda.id, library_id=library_id )}">Download this dataset</a> - %endif - ##TODO: need to revamp the way we remove datasets from disk. - ##<a class="action-button" confirm="Click OK to remove dataset '${ldda.name}'?" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, delete=True )}">Remove this dataset from the library</a> - </div> + %if not library.deleted and not ldda.library_dataset.folder.deleted and not ldda.deleted: + <a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a> + <div popupmenu="dataset-${ldda.id}-popup"> + <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a> + ## We're disabling the ability to add templates at the LDDA and LibraryDataset level, but will leave this here for possible future use + ##<a class="action-button" href="${h.url_for( controller='admin', action='info_template', library_id=library_id, library_dataset_id=ldda.library_dataset.id, new_template=True )}">Add an information template to this dataset</a> + <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a> + %if current_version: + <a class="action-button" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, replace_id=ldda.library_dataset.id )}">Upload a new version of this dataset</a> + %endif + %if ldda.has_data: + <a class="action-button" href="${h.url_for( controller='admin', action='download_dataset_from_folder', id=ldda.id, library_id=library_id )}">Download this dataset</a> + %endif + %if not library.deleted and not ldda.library_dataset.folder.deleted and not ldda.deleted: + <a class="action-button" confirm="Click OK to remove dataset '${ldda.name}'?" href="${h.url_for( controller='admin', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, delete=True )}">Delete this dataset</a> + %endif + </div> + %endif </div> <div class="toolFormBody"> <div class="form-row"> @@ -104,7 +108,10 @@ <div> There are ${len( ldda.visible_children )} secondary datasets. %for idx, child in enumerate( ldda.visible_children ): - ${ render_dataset( child, selected, library.deleted ) } + ## TODO: do we need to clarify if the child is deleted? + %if not child.purged: + ${ render_dataset( child, selected, library, False, False ) } + %endif %endfor </div> %endif diff -r 8da91a231cdf -r 2e2b80fcbd47 templates/library/ldda_info.mako --- a/templates/library/ldda_info.mako Tue May 05 13:03:23 2009 -0400 +++ b/templates/library/ldda_info.mako Tue May 05 13:48:01 2009 -0400 @@ -111,7 +111,10 @@ <div> There are ${len( ldda.visible_children )} secondary datasets. %for idx, child in enumerate( ldda.visible_children ): - ${ render_dataset( child, selected, library.deleted ) } + ## TODO: do we need to clarify if the child is deleted? + %if not child.purged: + ${ render_dataset( child, selected, library ) } + %endif %endfor </div> %endif
1
0
0
0
[hg] galaxy 2399: Directly stream .tar.gz and .tar.bz2 library d...
by Nate Coraor
05 May '09
05 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/3abf689d6f6f
changeset: 2399:3abf689d6f6f user: Nate Coraor <nate(a)bx.psu.edu> date: Tue May 05 12:03:40 2009 -0400 description: Directly stream .tar.gz and .tar.bz2 library downloads. .zip is still created on-disk first since Python's zipfile can't write to file-like objects like tarfile can. For response body generators (e.g. this feature) to work properly, you must set use_interactive and debug to False in universe_wsgi.ini. 3 file(s) affected in this change: lib/galaxy/util/streamball.py lib/galaxy/web/controllers/library.py templates/library/browse_library.mako diffs (277 lines): diff -r 6c76023580e3 -r 3abf689d6f6f lib/galaxy/util/streamball.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/util/streamball.py Tue May 05 12:03:40 2009 -0400 @@ -0,0 +1,50 @@ +""" +A simple wrapper for writing tarballs as a stream. The work is performed in a +thread and data is written to a Queue instead of a file. +""" + +import logging, tarfile + +from Queue import Queue, Empty, Full +from threading import Thread + +log = logging.getLogger( __name__ ) + +class QueueArchive( object ): + queue_size = 32 + def __init__( self ): + self.queue = Queue( QueueArchive.queue_size ) + self.get = self.queue.get + self.empty = self.queue.empty + def write( self, data ): + self.queue.put( data, block=True, timeout=300 ) + def tell( self ): + return 0 + +class StreamBall( object ): + def __init__( self, mode, members={} ): + self.mode = mode + self.members = members + self.tarfileobj = QueueArchive() + def add( self, file, relpath ): + self.members[file] = relpath + def stream( self ): + t = Thread( target=self.thread_write ) + t.start() + while t.isAlive(): + try: + yield self.tarfileobj.get( block=False ) + except Empty: + pass + t.join() + # exhaust the queue + while not self.tarfileobj.empty(): + yield self.tarfileobj.get() + def thread_write( self ): + tf = tarfile.open( mode=self.mode, fileobj=self.tarfileobj ) + try: + for file, rel in self.members.items(): + tf.add( file, arcname=rel ) + tf.close() + except Full: + log.warning( 'Queue full for longer than 300 seconds, timing out' ) diff -r 6c76023580e3 -r 3abf689d6f6f lib/galaxy/web/controllers/library.py --- a/lib/galaxy/web/controllers/library.py Tue May 05 08:29:23 2009 -0400 +++ b/lib/galaxy/web/controllers/library.py Tue May 05 12:03:40 2009 -0400 @@ -2,6 +2,7 @@ from galaxy.model.orm import * from galaxy.datatypes import sniff from galaxy import util +from galaxy.util.streamball import StreamBall import logging, tempfile, zipfile, tarfile, os, sys if sys.version_info[:2] < ( 2, 6 ): @@ -10,6 +11,40 @@ zipfile.LargeZipFile = zipfile.error log = logging.getLogger( __name__ ) + +# Test for available compression types +tmpd = tempfile.mkdtemp() +comptypes = [] +for comptype in ( 'gz', 'bz2' ): + tmpf = os.path.join( tmpd, 'compression_test.tar.' + comptype ) + try: + archive = tarfile.open( tmpf, 'w:' + comptype ) + archive.close() + comptypes.append( comptype ) + except tarfile.CompressionError: + log.exception( "Compression error when testing %s compression. This option will be disabled for library downloads." % comptype ) + try: + os.unlink( tmpf ) + except OSError: + pass +ziptype = '32' +tmpf = os.path.join( tmpd, 'compression_test.zip' ) +try: + archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED, True ) + archive.close() + comptypes.append( 'zip' ) + ziptype = '64' +except RuntimeError: + log.exception( "Compression error when testing zip compression. This option will be disabled for library downloads." ) +except (TypeError, zipfile.LargeZipFile): + # ZIP64 is only in Python2.5+. Remove TypeError when 2.4 support is dropped + log.warning( 'Max zip file size is 2GB, ZIP64 not supported' ) + comptypes.append( 'zip' ) +try: + os.unlink( tmpf ) +except OSError: + pass +os.rmdir( tmpd ) class Library( BaseController ): @web.expose @@ -66,6 +101,7 @@ library=trans.app.model.Library.get( id ), created_ldda_ids=created_ldda_ids, default_action=params.get( 'default_action', None ), + comptypes=comptypes, msg=msg, messagetype=messagetype ) @web.expose @@ -195,49 +231,21 @@ msg=util.sanitize_text( msg ), messagetype=messagetype ) ) else: - # Can't use mkstemp - the file must not exist first try: - tmpd = tempfile.mkdtemp() - tmpf = os.path.join( tmpd, 'library_download.' + params.do_action ) if params.do_action == 'zip': - try: + # Can't use mkstemp - the file must not exist first + tmpd = tempfile.mkdtemp() + tmpf = os.path.join( tmpd, 'library_download.' + params.do_action ) + if ziptype == '64': archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED, True ) - except RuntimeError: - log.exception( "Compression error when opening zipfile for library download" ) - msg = "ZIP compression is not available in this Python, please notify an administrator" - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - except (TypeError, zipfile.LargeZipFile): - # ZIP64 is only in Python2.5+. Remove TypeError when 2.4 support is dropped - log.warning( 'Max zip file size is 2GB, ZIP64 not supported' ) + else: archive = zipfile.ZipFile( tmpf, 'w', zipfile.ZIP_DEFLATED ) archive.add = lambda x, y: archive.write( x, y.encode('CP437') ) elif params.do_action == 'tgz': - try: - archive = tarfile.open( tmpf, 'w:gz' ) - except tarfile.CompressionError: - log.exception( "Compression error when opening tarfile for library download" ) - msg = "gzip compression is not available in this Python, please notify an administrator" - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) + archive = util.streamball.StreamBall( 'w|gz' ) elif params.do_action == 'tbz': - try: - archive = tarfile.open( tmpf, 'w:bz2' ) - except tarfile.CompressionError: - log.exception( "Compression error when opening tarfile for library download" ) - msg = "bzip2 compression is not available in this Python, please notify an administrator" - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - except (OSError, zipfile.BadZipFile, tarfile.ReadError): + archive = util.streamball.StreamBall( 'w|bz2' ) + except (OSError, zipfile.BadZipFile): log.exception( "Unable to create archive for download" ) msg = "Unable to create archive for download, please report this error" return trans.response.send_redirect( web.url_for( controller='library', @@ -255,9 +263,11 @@ path = "" parent_folder = ldda.library_dataset.folder while parent_folder is not None: - path = os.path.join( parent_folder.name, path ) + # Exclude the now-hidden "root folder" if parent_folder.parent is None: path = os.path.join( parent_folder.library_root[0].name, path ) + break + path = os.path.join( parent_folder.name, path ) parent_folder = parent_folder.parent path += ldda.name while path in seen: @@ -273,22 +283,28 @@ id=library_id, msg=util.sanitize_text( msg ), messagetype='error' ) ) - archive.close() - tmpfh = open( tmpf ) - # clean up now - try: - os.unlink( tmpf ) - os.rmdir( tmpd ) - except OSError: - log.exception( "Unable to remove temporary library download archive and directory" ) - msg = "Unable to create archive for download, please report this error" - return trans.response.send_redirect( web.url_for( controller='library', - action='browse_library', - id=library_id, - msg=util.sanitize_text( msg ), - messagetype='error' ) ) - trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryFiles.%s" % params.do_action - return tmpfh + if params.do_action == 'zip': + archive.close() + tmpfh = open( tmpf ) + # clean up now + try: + os.unlink( tmpf ) + os.rmdir( tmpd ) + except OSError: + log.exception( "Unable to remove temporary library download archive and directory" ) + msg = "Unable to create archive for download, please report this error" + return trans.response.send_redirect( web.url_for( controller='library', + action='browse_library', + id=library_id, + msg=util.sanitize_text( msg ), + messagetype='error' ) ) + trans.response.set_content_type( "application/x-zip-compressed" ) + trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryFiles.%s" % params.do_action + return tmpfh + else: + trans.response.set_content_type( "application/x-tar" ) + trans.response.headers[ "Content-Disposition" ] = "attachment; filename=GalaxyLibraryFiles.%s" % params.do_action + return archive.stream() @web.expose def download_dataset_from_folder(self, trans, id, library_id=None, **kwd): """Catches the dataset id and displays file contents as directed""" diff -r 6c76023580e3 -r 3abf689d6f6f templates/library/browse_library.mako --- a/templates/library/browse_library.mako Tue May 05 08:29:23 2009 -0400 +++ b/templates/library/browse_library.mako Tue May 05 12:03:40 2009 -0400 @@ -268,13 +268,38 @@ # This condition should not contain an else clause because the user is not authorized # to manage dataset permissions unless the default action is 'manage_permissions' %endif - %if default_action == 'download': - <option value="zip" selected>Download selected datasets as a .zip file</option> - %else: + %if 'bz2' in comptypes: + <option value="tbz" + %if default_action == 'download': + selected + %endif> + >Download selected datasets as a .tar.bz2 file</option> + %endif + %if 'gz' in comptypes: + <option value="tgz">Download selected datasets as a .tar.gz file</option> + %endif + %if 'zip' in comptypes: <option value="zip">Download selected datasets as a .zip file</option> %endif - <option value="tgz">Download selected datasets as a .tar.gz file</option> - <option value="tbz">Download selected datasets as a .tar.bz2 file</option> </select> <input type="submit" class="primary-button" name="action_on_datasets_button" id="action_on_datasets_button" value="Go"/> </form> + +%if len( comptypes ) > 1: + <div> + <p class="infomark"> + TIP: Multiple compression options are available for downloading library datasets: + </p> + <ul style="padding-left: 1em; list-style-type: disc;"> + %if 'bz2' in comptypes: + <li>bzip2: Compression takes the most time but is better for slower network connections (that transfer slower than the rate of compression) since the resulting file size is smallest.</li> + %endif + %if 'gz' in comptypes: + <li>gzip: Compression is faster and yields a larger file, making it more suitable for fast network connections.</li> + %endif + %if 'zip' in comptypes: + <li>ZIP: Not recommended but is provided as an option for those on Windows without WinZip (since WinZip can read .bz2 and .gz files).</li> + %endif + </ul> + </div> +%endif
1
0
0
0
[hg] galaxy 2400: Fix history deletion method in Galaxy check sc...
by Nate Coraor
05 May '09
05 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/8da91a231cdf
changeset: 2400:8da91a231cdf user: Nate Coraor <nate(a)bx.psu.edu> date: Tue May 05 13:03:23 2009 -0400 description: Fix history deletion method in Galaxy check script 1 file(s) affected in this change: scripts/check_galaxy.py diffs (38 lines): diff -r 3abf689d6f6f -r 8da91a231cdf scripts/check_galaxy.py --- a/scripts/check_galaxy.py Tue May 05 12:03:40 2009 -0400 +++ b/scripts/check_galaxy.py Tue May 05 13:03:23 2009 -0400 @@ -141,15 +141,8 @@ print "Remaining datasets ids:", " ".join( p.dids ) raise Exception, "History still contains datasets after attempting to delete them" if new_history: - self.get("/root/history_options") - p = hidParser() - p.feed(tc.browser.get_html()) - if p.hid is None: - print "Unable to determine hid to delete old history" - sys.exit(1) - else: - self.get("/root/history_delete?id=%s" % p.hid) - tc.save_cookies(self.cookie_jar) + self.get("/history/delete_current") + tc.save_cookies(self.cookie_jar) def check_redir(self, url): try: @@ -334,16 +327,6 @@ self.dids.append( i[1].rsplit("historyItemContainer-", 1)[1] ) dprint("got a dataset id: %s" % self.dids[-1]) -class hidParser(htmllib.HTMLParser): - def __init__(self): - htmllib.HTMLParser.__init__(self, formatter.NullFormatter()) - self.hid = None - def start_a(self, attrs): - for i in attrs: - if i[0] == "href" and i[1].startswith("/root/history_delete"): - self.hid = i[1].rsplit("=", 1)[1] - dprint("got a history id: %s" % self.hid) - class loggedinParser(htmllib.HTMLParser): def __init__(self): htmllib.HTMLParser.__init__(self, formatter.NullFormatter())
1
0
0
0
[hg] galaxy 2396: Fix import history links, now using encode_id ...
by Nate Coraor
05 May '09
05 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/6de7eb773877
changeset: 2396:6de7eb773877 user: James Taylor <james(a)jamestaylor.org> date: Mon May 04 12:06:11 2009 -0400 description: Fix import history links, now using encode_id as well 2 file(s) affected in this change: lib/galaxy/web/controllers/history.py templates/history/share.mako diffs (73 lines): diff -r df824c53f2f3 -r 6de7eb773877 lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py Fri May 01 17:19:17 2009 -0400 +++ b/lib/galaxy/web/controllers/history.py Mon May 04 12:06:11 2009 -0400 @@ -213,6 +213,57 @@ ## These have been moved from 'root' but not cleaned up @web.expose + def imp( self, trans, id=None, confirm=False, **kwd ): + msg = "" + user = trans.get_user() + user_history = trans.get_history() + if not id: + return trans.show_error_message( "You must specify a history you want to import.") + id = trans.security.decode_id( id ) + import_history = trans.app.model.History.get( id ) + if not import_history: + return trans.show_error_message( "The specified history does not exist.") + if user: + if import_history.user_id == user.id: + return trans.show_error_message( "You cannot import your own history.") + new_history = import_history.copy( target_user=trans.user ) + new_history.name = "imported: "+new_history.name + new_history.user_id = user.id + galaxy_session = trans.get_galaxy_session() + try: + association = trans.app.model.GalaxySessionToHistoryAssociation.filter_by( session_id=galaxy_session.id, history_id=new_history.id ).first() + except: + association = None + new_history.add_galaxy_session( galaxy_session, association=association ) + new_history.flush() + if not user_history.datasets: + trans.set_history( new_history ) + trans.log_event( "History imported, id: %s, name: '%s': " % (str(new_history.id) , new_history.name ) ) + return trans.show_ok_message( """ + History "%s" has been imported. Click <a href="%s">here</a> + to begin.""" % ( new_history.name, web.url_for( '/' ) ) ) + elif not user_history.datasets or confirm: + new_history = import_history.copy() + new_history.name = "imported: "+new_history.name + new_history.user_id = None + galaxy_session = trans.get_galaxy_session() + try: + association = trans.app.model.GalaxySessionToHistoryAssociation.filter_by( session_id=galaxy_session.id, history_id=new_history.id ).first() + except: + association = None + new_history.add_galaxy_session( galaxy_session, association=association ) + new_history.flush() + trans.set_history( new_history ) + trans.log_event( "History imported, id: %s, name: '%s': " % (str(new_history.id) , new_history.name ) ) + return trans.show_ok_message( """ + History "%s" has been imported. Click <a href="%s">here</a> + to begin.""" % ( new_history.name, web.url_for( '/' ) ) ) + return trans.show_warn_message( """ + Warning! If you import this history, you will lose your current + history. Click <a href="%s">here</a> to confirm. + """ % web.url_for( id=id, confirm=True ) ) + + @web.expose @web.require_login( "share histories with other users" ) def share( self, trans, id=None, email="", **kwd ): send_to_err = "" diff -r df824c53f2f3 -r 6de7eb773877 templates/history/share.mako --- a/templates/history/share.mako Fri May 01 17:19:17 2009 -0400 +++ b/templates/history/share.mako Mon May 04 12:06:11 2009 -0400 @@ -18,7 +18,7 @@ ${len(history.datasets)} %endif </td> - <td align="center"><a href="${h.url_for( action='history_import', id=history.id )}">${_('copy link to share')}</a></td> + <td align="center"><a href="${h.url_for( controller='history', action='imp', id=trans.security.encode_id(history.id) )}">${_('copy link to share')}</a></td> </tr> %endfor <tr><td>${_('Email of User to share with:')}</td><td><input type="text" name="email" value="${email}" size="40"></td></tr>
1
0
0
0
[hg] galaxy 2395: Simplifying the grid helper a bit. Fix a bug w...
by Nate Coraor
05 May '09
05 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/df824c53f2f3
changeset: 2395:df824c53f2f3 user: James Taylor <james(a)jamestaylor.org> date: Fri May 01 17:19:17 2009 -0400 description: Simplifying the grid helper a bit. Fix a bug where sort/filter were not retained when performing actions on multiple items 4 file(s) affected in this change: lib/galaxy/web/controllers/history.py lib/galaxy/web/framework/helpers/__init__.py lib/galaxy/web/framework/helpers/grids.py templates/grid.mako diffs (279 lines): diff -r 80e00a9cdeb0 -r df824c53f2f3 lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py Fri May 01 12:24:24 2009 -0400 +++ b/lib/galaxy/web/controllers/history.py Fri May 01 17:19:17 2009 -0400 @@ -1,5 +1,5 @@ from galaxy.web.base.controller import * -from galaxy.web.framework.helpers.grids import * +from galaxy.web.framework.helpers import time_ago, iff, grids import webhelpers from datetime import datetime from cgi import escape @@ -9,42 +9,33 @@ # States for passing messages SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error" -def time_ago( x ): - return webhelpers.date.distance_of_time_in_words( x, datetime.utcnow() ) - -def iff( a, b, c ): - if a: - return b - else: - return c - -class HistoryListGrid( Grid ): +class HistoryListGrid( grids.Grid ): title = "Stored histories" model_class = model.History default_sort_key = "-create_time" columns = [ - GridColumn( "Name", key="name", + grids.GridColumn( "Name", key="name", link=( lambda item: iff( item.deleted, None, dict( operation="switch", id=item.id ) ) ), attach_popup=True ), - GridColumn( "Datasets (by state)", method='_build_datasets_by_state', ncells=4 ), - GridColumn( "Status", method='_build_status' ), - GridColumn( "Age", key="create_time", format=time_ago ), - GridColumn( "Last update", key="update_time", format=time_ago ), + grids.GridColumn( "Datasets (by state)", method='_build_datasets_by_state', ncells=4 ), + grids.GridColumn( "Status", method='_build_status' ), + grids.GridColumn( "Age", key="create_time", format=time_ago ), + grids.GridColumn( "Last update", key="update_time", format=time_ago ), # Valid for filtering but invisible - GridColumn( "Deleted", key="deleted", visible=False ) + grids.GridColumn( "Deleted", key="deleted", visible=False ) ] operations = [ - GridOperation( "Switch", allow_multiple=False, condition=( lambda item: not item.deleted ) ), - GridOperation( "Share", condition=( lambda item: not item.deleted ) ), - GridOperation( "Rename", condition=( lambda item: not item.deleted ) ), - GridOperation( "Delete", condition=( lambda item: not item.deleted ) ), - GridOperation( "Undelete", condition=( lambda item: item.deleted ) ) + grids.GridOperation( "Switch", allow_multiple=False, condition=( lambda item: not item.deleted ) ), + grids.GridOperation( "Share", condition=( lambda item: not item.deleted ) ), + grids.GridOperation( "Rename", condition=( lambda item: not item.deleted ) ), + grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ), + grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ) ] standard_filters = [ - GridColumnFilter( "Active", args=dict( deleted=False ) ), - GridColumnFilter( "Deleted", args=dict( deleted=True ) ), - GridColumnFilter( "All", args=dict( deleted='All' ) ) + grids.GridColumnFilter( "Active", args=dict( deleted=False ) ), + grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ), + grids.GridColumnFilter( "All", args=dict( deleted='All' ) ) ] default_filter = dict( deleted=False ) @@ -53,41 +44,7 @@ def apply_default_filter( self, trans, query ): return query.filter_by( user=trans.user, purged=False ) - - def handle_operation( self, trans, operation, history_ids ): - # Display no message by default - status, message = None, None - refresh_history = False - # Load the histories and ensure they all belong to the current user - histories = [] - for hid in history_ids: - history = model.History.get( hid ) - if history: - # Ensure history is owned by current user - if history.user_id != None and trans.user: - assert trans.user.id == history.user_id, "History does not belong to current user" - histories.append( history ) - else: - log.warn( "Invalid history id '%r' passed to list", hid ) - operation = operation.lower() - if operation == "switch": - status, message = self._list_switch( trans, histories ) - # Current history changed, refresh history frame - trans.template_context['refresh_frames'] = ['history'] - elif operation == "share": - ## Caught above for now - pass - elif operation == "rename": - ## Caught above for now - pass - elif operation == "delete": - status, message = self._list_delete( trans, histories ) - elif operation == "undelete": - status, message = self._list_undelete( trans, histories ) - trans.sa_session.flush() - # Render the list view - return status, message - + def _build_datasets_by_state( self, trans, history ): rval = [] for state in ( 'ok', 'running', 'queued', 'error' ): @@ -102,6 +59,64 @@ if history.deleted: return "deleted" return "" + +class HistoryController( BaseController ): + + @web.expose + def index( self, trans ): + return "" + + @web.expose + def list_as_xml( self, trans ): + """ + XML history list for functional tests + """ + return trans.fill_template( "/history/list_as_xml.mako" ) + + list_grid = HistoryListGrid() + + @web.expose + @web.require_login( "work with multiple histories" ) + def list( self, trans, **kwargs ): + """ + List all available histories + """ + status = message = None + if 'operation' in kwargs: + operation = kwargs['operation'].lower() + if operation == "share": + return self.share( trans, **kwargs ) + elif operation == "rename": + return self.rename( trans, **kwargs ) + # Display no message by default + status, message = None, None + refresh_history = False + # Load the histories and ensure they all belong to the current user + history_ids = kwargs.get( 'id', [] ) + if type( history_ids ) is not list: + history_ids = [ history_ids ] + histories = [] + for hid in history_ids: + history = model.History.get( hid ) + if history: + # Ensure history is owned by current user + if history.user_id != None and trans.user: + assert trans.user.id == history.user_id, "History does not belong to current user" + histories.append( history ) + else: + log.warn( "Invalid history id '%r' passed to list", hid ) + if histories: + if operation == "switch": + status, message = self._list_switch( trans, histories ) + # Current history changed, refresh history frame + trans.template_context['refresh_frames'] = ['history'] + elif operation == "delete": + status, message = self._list_delete( trans, histories ) + elif operation == "undelete": + status, message = self._list_undelete( trans, histories ) + trans.sa_session.flush() + # Render the list view + return self.list_grid( trans, status=status, message=message, **kwargs ) def _list_delete( self, trans, histories ): """Delete histories""" @@ -164,37 +179,6 @@ trans.log_event( "History switched to id: %s, name: '%s'" % (str(new_history.id), new_history.name ) ) # No message return None, None - -class HistoryController( BaseController ): - - @web.expose - def index( self, trans ): - return "" - - @web.expose - def list_as_xml( self, trans ): - """ - XML history list for functional tests - """ - return trans.fill_template( "/history/list_as_xml.mako" ) - - _list_grid = HistoryListGrid() - - @web.expose - @web.require_login( "work with multiple histories" ) - def list( self, trans, *args, **kwargs ): - """ - List all available histories - """ - # TODO: these two operations need to be updates still - operation = kwargs.get( 'operation', None ) - if operation: - operation = operation.lower() - if operation == "share": - return self.share( trans, **kwargs ) - elif operation == "rename": - return self.rename( trans, **kwargs ) - return self._list_grid( trans, *args, **kwargs ) @web.expose def delete_current( self, trans ): diff -r 80e00a9cdeb0 -r df824c53f2f3 lib/galaxy/web/framework/helpers/__init__.py --- a/lib/galaxy/web/framework/helpers/__init__.py Fri May 01 12:24:24 2009 -0400 +++ b/lib/galaxy/web/framework/helpers/__init__.py Fri May 01 17:19:17 2009 -0400 @@ -0,0 +1,12 @@ +from webhelpers import * + +from datetime import datetime + +def time_ago( x ): + return date.distance_of_time_in_words( x, datetime.utcnow() ) + +def iff( a, b, c ): + if a: + return b + else: + return c \ No newline at end of file diff -r 80e00a9cdeb0 -r df824c53f2f3 lib/galaxy/web/framework/helpers/grids.py --- a/lib/galaxy/web/framework/helpers/grids.py Fri May 01 12:24:24 2009 -0400 +++ b/lib/galaxy/web/framework/helpers/grids.py Fri May 01 17:19:17 2009 -0400 @@ -16,18 +16,13 @@ standard_filters = [] default_filter = None default_sort_key = None + pass_through_operations = {} def __init__( self ): pass def __call__( self, trans, **kwargs ): - # Session + status = kwargs.get( 'status', None ) + message = kwargs.get( 'message', None ) session = trans.sa_session - # Process any actions - status = message = None - ids = self.get_ids( **kwargs ) - operation = kwargs.get( 'operation', None ) - if operation: - operation = operation.lower() - status, message = self.handle_operation( trans, operation, ids ) # Build initial query query = self.build_initial_query( session ) query = self.apply_default_filter( trans, query ) @@ -83,7 +78,7 @@ encoded_sort_key=encoded_sort_key, sort_order=sort_order, current_item=current_item, - ids = ids, + ids = kwargs.get( 'id', [] ), url = url, message_type = status, message = message ) diff -r 80e00a9cdeb0 -r df824c53f2f3 templates/grid.mako --- a/templates/grid.mako Fri May 01 12:24:24 2009 -0400 +++ b/templates/grid.mako Fri May 01 17:19:17 2009 -0400 @@ -85,9 +85,7 @@ %endfor </div> -<form name="history_actions" action="${h.url_for()}" method="post" > - - <input type="hidden" name="sort" value="${sort_key}"> +<form name="history_actions" action="${url()}" method="post" > <table class="grid"> <thead>
1
0
0
0
[hg] galaxy 2397: Fix closing label tags in 2 ldda_info_templates.
by Nate Coraor
05 May '09
05 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/8edceee8c818
changeset: 2397:8edceee8c818 user: Greg Von Kuster <greg(a)bx.psu.edu> date: Mon May 04 12:20:26 2009 -0400 description: Fix closing label tags in 2 ldda_info_templates. 2 file(s) affected in this change: templates/admin/library/ldda_info.mako templates/library/ldda_info.mako diffs (90 lines): diff -r 6de7eb773877 -r 8edceee8c818 templates/admin/library/ldda_info.mako --- a/templates/admin/library/ldda_info.mako Mon May 04 12:06:11 2009 -0400 +++ b/templates/admin/library/ldda_info.mako Mon May 04 12:20:26 2009 -0400 @@ -63,28 +63,28 @@ <div style="clear: both"></div> </div> <div class="form-row"> - <label>Uploaded by:</lable> + <label>Uploaded by:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${uploaded_by} </div> <div style="clear: both"></div> </div> <div class="form-row"> - <label>Date uploaded:</lable> + <label>Date uploaded:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${ldda.create_time.strftime( "%Y-%m-%d" )} </div> <div style="clear: both"></div> </div> <div class="form-row"> - <label>Build:</lable> + <label>Build:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${ldda.dbkey} </div> <div style="clear: both"></div> </div> <div class="form-row"> - <label>Miscellaneous information:</lable> + <label>Miscellaneous information:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${ldda.info} </div> @@ -96,7 +96,7 @@ <div class="form-row"> <div id="info${ldda.id}" class="historyItemBody"> %if ldda.peek != "no peek": - <label>Peek:</lable> + <label>Peek:</label> <div><pre id="peek${ldda.id}" class="peek">${ldda.display_peek()}</pre></div> %endif ## Recurse for child datasets diff -r 6de7eb773877 -r 8edceee8c818 templates/library/ldda_info.mako --- a/templates/library/ldda_info.mako Mon May 04 12:06:11 2009 -0400 +++ b/templates/library/ldda_info.mako Mon May 04 12:20:26 2009 -0400 @@ -70,28 +70,28 @@ <div style="clear: both"></div> </div> <div class="form-row"> - <label>Uploaded by:</lable> + <label>Uploaded by:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${uploaded_by} </div> <div style="clear: both"></div> </div> <div class="form-row"> - <label>Date uploaded:</lable> + <label>Date uploaded:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${ldda.create_time.strftime( "%Y-%m-%d" )} </div> <div style="clear: both"></div> </div> <div class="form-row"> - <label>Build:</lable> + <label>Build:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${ldda.dbkey} </div> <div style="clear: both"></div> </div> <div class="form-row"> - <label>Miscellaneous information:</lable> + <label>Miscellaneous information:</label> <div style="float: left; width: 250px; margin-right: 10px;"> ${ldda.info} </div> @@ -103,7 +103,7 @@ <div class="form-row"> <div id="info${ldda.id}" class="historyItemBody"> %if ldda.peek != "no peek": - <label>Peek:</lable> + <label>Peek:</label> <div><pre id="peek${ldda.id}" class="peek">${ldda.display_peek()}</pre></div> %endif ## Recurse for child datasets
1
0
0
0
[hg] galaxy 2398: Exclude controllers from unit tests to elimina...
by Nate Coraor
05 May '09
05 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/6c76023580e3
changeset: 2398:6c76023580e3 user: Greg Von Kuster <greg(a)bx.psu.edu> date: Tue May 05 08:29:23 2009 -0400 description: Exclude controllers from unit tests to eliminate the broken genetrack test. 1 file(s) affected in this change: run_unit_tests.sh diffs (12 lines): diff -r 8edceee8c818 -r 6c76023580e3 run_unit_tests.sh --- a/run_unit_tests.sh Mon May 04 12:20:26 2009 -0400 +++ b/run_unit_tests.sh Tue May 05 08:29:23 2009 -0400 @@ -1,5 +1,7 @@ #!/bin/sh + +## Excluding controllers due to the problematic genetrack dependency python -ES ./scripts/nosetests.py -v -w lib \ --with-nosehtml --html-report-file run_unit_tests.html \ - --with-doctest --exclude=functional --exclude="^get" + --with-doctest --exclude=functional --exclude="^get" --exclude=controllers
1
0
0
0
[hg] galaxy 2394: Tweaking styles for quickies
by Greg Von Kuster
01 May '09
01 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/80e00a9cdeb0
changeset: 2394:80e00a9cdeb0 user: James Taylor <james(a)jamestaylor.org> date: Fri May 01 12:24:24 2009 -0400 description: Tweaking styles for quickies 1 file(s) affected in this change: static/welcome.html diffs (108 lines): diff -r a9d5f8e80bcd -r 80e00a9cdeb0 static/welcome.html --- a/static/welcome.html Fri May 01 12:24:07 2009 -0400 +++ b/static/welcome.html Fri May 01 12:24:24 2009 -0400 @@ -8,39 +8,22 @@ <style type="text/css"> .quickie { text-align: center; - min-height: 100px; background: black; + margin: 10px; } .current-quickie { width: 100%; background: black; } - .quickie .head { - font-size: 200%; - color: white; - padding: 20px 20px; - } - .quickie .sub { - font-size: 150%; - color: orange; - padding: 20px 20px; - } .previous { width: 100%; overflow: auto; + border: solid #ccc 1px; } .previous .quickie { + padding-top: 10px; + min-height: 90px; min-width: 150px; - } - .previous .quickie .head { - font-size: 120%; - padding: 10px 10px; - text-decoration: none; - } - .previous .quickie .sub { - font-size: 100%; - padding: 10px 10px; - text-decoration: none; } #screencasts { max-width: 50em; @@ -64,7 +47,6 @@ <div id="screencasts"> <h2>Introducing Galactic Quickies</h2> -<hr> <p> Galactic quickies are <i>super-short</i> screencasts that are <i>always</i> under 5 minutes. We thought it may be a good way to spread the word about Galaxy's functionality while keeping the "annoyance factor" to the minimum. The quickies will be updated weekly. </p> @@ -84,35 +66,32 @@ </div> <h3>Previous Quickies</h3> -<hr> -<div class="previous"> +<div class="previous" id="previous"> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr> - <td width="50%" style="border-right: solid white 10px; border-bottom: solid white 10px"> + <td> <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie1_TabSeq/flow.html
',width:640,height:500,scroll:'no'})"> <div class="quickie"> <img src="images/qk/quickie1_small.png" border="0"> </div> </a> </td> - <td width="50%" style="border-left: solid white 10px; border-bottom: solid white 10px"> + <td> <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie2_Grouping/flow.html
',width:640,height:500,scroll:'no'})"> <div class="quickie"> <img src="images/qk/quickie2_small.png" border="0"> </div> </a> </td> - </tr> - <tr> - <td width="50%" style="border-right: solid white 10px; border-top: solid white 10px" > + <td> <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie3_Intervals/flow.html
',width:640,height:500,scroll:'no'})"> <div class="quickie"> <img src="images/qk/quickie3_small.png" border="0"> </div> </a> </td> - <td width="50%" style="border-left: solid white 10px; border-top: solid white 10px" > + <td> <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie4_whatsNew/flow.html
',width:640,height:500,scroll:'no'})"> <div class="quickie"> <img src="images/qk/quickie4_small.png" border="0"> @@ -123,6 +102,11 @@ </table> </div> +<script type="text/javascript"> + // Scroll to last quickie in box + document.getElementById("previous").scrollLeft = 100000000; +</script> + <br/> <br/> <br/>
1
0
0
0
[hg] galaxy 2393: Updating packed script for workflow editor
by Greg Von Kuster
01 May '09
01 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/a9d5f8e80bcd
changeset: 2393:a9d5f8e80bcd user: James Taylor <james(a)jamestaylor.org> date: Fri May 01 12:24:07 2009 -0400 description: Updating packed script for workflow editor 1 file(s) affected in this change: static/scripts/packed/galaxy.workflow_editor.canvas.js diffs (8 lines): diff -r 84ecf82a2ce7 -r a9d5f8e80bcd static/scripts/packed/galaxy.workflow_editor.canvas.js --- a/static/scripts/packed/galaxy.workflow_editor.canvas.js Fri May 01 11:09:04 2009 -0400 +++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js Fri May 01 12:24:07 2009 -0400 @@ -1,1 +1,1 @@ -function Terminal(a){this.element=a;this.connectors=[]}Terminal.prototype={connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}};function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal;function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal;$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(t in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[t])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a) }}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var m=function(c){return $(c).offset().left-d.offset().left};var h=function(c){return $(c).offset().top-d.offset().top};var g=m(this.handle1.element)+5;var f=h(this.handle1.element)+5;var o=m(this.handle2.element)+5;var l=h(this.handle2.element)+5;var e=100;var j=Math.min(g,o);var a=Math.max(g,o);var i=Math.min(f,l);var s=Math.max(f,l);var b=Math.min(Math.max(Math.abs(s-i)/2,100),300);var n=j-e;var r=i-e;var p=a-j+2*e;var k=s-i+2*e;this.canvas.style. left=n+"px";this.canvas.style.top=r+"px";this.canvas.setAttribute("width",p);this.canvas.setAttribute("height",k);g-=n;f-=r;o-=n;l-=r;var q=this.canvas.getContext("2d");q.lineCap="round";q.strokeStyle=this.outer_color;q.lineWidth=7;q.beginPath();q.moveTo(g,f);q.bezierCurveTo(g+b,f,o-b,l,o,l);q.stroke();q.strokeStyle=this.inner_color;q.lineWidth=5;q.beginPath();q.moveTo(g,f);q.bezierCurveTo(g+b,f,o-b,l,o,l);q.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var e=this.terminal=new InputTerminal(this,b);e.node=c;e.name=a;$(this).bind("dropstart",function(f){f.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(f){f.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(f){new Connector(f.dragTarget.terminal,f.dropTarget.terminal).redraw()}).bind("hover",function(){if(e. connectors.length>0){var f=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(e.connectors,function(h,g){g.destroy()});f.remove()}))).bind("mouseleave",function(){$(this).remove()});f.css({top:$(this).offset().top-2,left:$(this).offset().left-f.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=e})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this;var e=this.terminal=new OutputTerminal(this,b);e.node=c;e.name=a;$(this).bind("dragstart",function(i){var g=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);g.terminal=new OutputTerminal(g);var j=new Connector();j.dragging=true;j.connect(this.terminal,g.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(e)}}).addClass("input-terminal-active");return g}).bind("drag", function(h){var g=function(){var j=$(h.dragProxy).offsetParent().offset(),i=h.offsetX-j.left,k=h.offsetY-j.top;$(h.dragProxy).css({left:i,top:k});h.dragProxy.terminal.redraw()};g();$("#canvas-container").get(0).scroll_panel.test(h,g)}).bind("dragend",function(g){g.dragProxy.terminal.connectors[0].destroy();$(g.dragProxy).remove();$.dropManage().removeClass("input-terminal-active")});c.output_terminals[a]=e})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(e){var d=this.ele ment;if(e.type){this.type=e.type}this.form_html=e.form_html;this.tool_state=e.tool_state;this.tool_errors=e.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var g=$("<div class='inputs'></div>").appendTo(a);$.each(e.data_inputs,function(h,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);g.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((e.data_inputs.length>0)&&(e.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(e.data_outputs,function(j,b){var h=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(h,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extension+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(h))});workflow.node_changed(this)},update_field_data:functi on(e){var c=$(this.element),d=this;this.tool_state=e.tool_state;this.form_html=e.form_html;this.tool_errors=e.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var f=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=f.find("div.input-data-row");$.each(e.data_inputs,function(j,g){var h=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(h,g.name,g.extensions);f.find("div[name="+g.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){h[0].terminal.connectors[0]=i;i.handle2=h[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+g.name+"'>"+g.label+"</div>").prepend(h))});f.replaceWith(b);f.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c= "<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(){this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var e={};$.each(d.input_terminals,function(f,g){e[g.name]=null;$.each(g.connectors,function(h,j){e[g.name]={id:j.handle1.node.id,output_name:j.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connec tions:e,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(e,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(e))});wf.id_counter=b+1;$.each(a.steps,function(e,d){var c=wf.nodes[e];$.each(d.input_connections,function(g,f){if(f){var h=wf.nodes[f.id];var i=new Connector();i.connect(h.output_terminals[f.output_name],c.input_terminals[g]);i.redraw()}})})},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.clear_active_node();parent.show_form_for_tool(a.form_html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form _for_tool(a.form_html,a)}}});function prebuild_node(j,h,m){var g=$("<div class='toolForm toolFormInCanvas'></div>");var d=new Node(g);d.type=j;if(j=="tool"){d.tool_id=m}var l=$("<div class='toolFormTitle unselectable'>"+h+"</div>");g.append(l);g.css("left",$(window).scrollLeft()+20);g.css("top",$(window).scrollTop()+20);var k=$("<div class='toolFormBody'></div>");var e="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";k.append(e);d.form_html=e;g.append(k);var i=$("<div class='buttons' style='float: right;'></div>");i.append($("<img src='../images/delete_icon.png' />").click(function(b){d.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));g.appendTo("#canvas-container");var c=$("#canvas-container").position();g.css({left:(-c.left)+10,top:(-c.top)+10});var a=g.width();i.prependTo(l);a+=(i.width()+10);g.css("width",a);$(g).bi nd("dragstart",function(){workflow.activate_node(d)}).bind("dragend",function(){workflow.node_changed(this)}).bind("dragclickonly",function(){workflow.activate_node(d)}).bind("drag",function(n){var f=$(this).offsetParent().offset(),b=n.offsetX-f.left,o=n.offsetY-f.top;$(this).css({left:b,top:o});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return d}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(f,c){clearTimeout(this.timeout);var a=f.pageX,g=f.pageY;b=$(this.panel),panel_pos=b.position(),panel_w=b.width(),panel_h=b.height();viewport=b.parent();viewport_w=viewport.width(),viewport_h=viewport.height(),viewport_offset=viewport.offset(),min_x=viewport_offset.left,min_y=viewport_offset.top,max_x= min_x+viewport.width(),max_y=min_y+viewport.height(),p_min_x=-(panel_w-viewport_w),p_min_y=-(panel_h-viewport_h),p_max_x=0,p_max_y=0,moved=false,close_dist=5,nudge=23;if(a-close_dist<min_x){if(panel_pos.left<p_max_x){var d=Math.min(nudge,p_max_x-panel_pos.left);b.css("left",panel_pos.left+d);moved=true}}else{if(a+close_dist>max_x){if(panel_pos.left>p_min_x){var d=Math.min(nudge,panel_pos.left-p_min_x);b.css("left",panel_pos.left-d);moved=true}}else{if(g-close_dist<min_y){if(panel_pos.top<p_max_y){var d=Math.min(nudge,p_max_y-panel_pos.top);b.css("top",panel_pos.top+d);moved=true}}else{if(g+close_dist>max_y){if(panel_pos.top>p_min_y){var d=Math.min(nudge,panel_pos.top-p_min_x);b.css("top",(panel_pos.top-d)+"px");moved=true}}}}}if(moved){c();var b=this;this.timeout=setTimeout(function(){b.test(f,c)},50)}},drag:function(g,h){clearTimeout(this.timeout);var c=g.dragProxy,a=this.panel,b=a.position(),i=a.width(),d=a.height();viewport=a.parent();viewport_w=viewport.width(),viewport_ h=viewport.height(),element_w=c.width(),element_h=c.height(),moved=false,close_dist=5,nudge=23,p_min_x=-(i-viewport_w),p_min_y=-(d-viewport_h),p_max_x=0,p_max_y=0,min_vis_x=-b.left,max_vis_x=min_vis_x+viewport_w,min_vis_y=-b.top,max_vis_y=min_vis_y+viewport_h,mouse_x=h.position.left+instance.offset.click.left;mouse_y=h.position.top+instance.offset.click.top;if((b.left<p_max_x)&&(mouse_x-close_dist<min_vis_x)){var j=Math.min(nudge,p_max_x-b.left);a.css("left",b.left+j);moved=true;instance.offset.parent.left+=j;h.position.left-=j}if((!moved)&&(b.left>p_min_x)&&(mouse_x+close_dist>max_vis_x)){var j=Math.min(nudge,b.left-p_min_x);a.css("left",b.left-j);moved=true;instance.offset.parent.left-=j;h.position.left+=j}if((!moved)&&(b.top<p_max_y)&&(mouse_y-close_dist<min_vis_y)){var j=Math.min(nudge,p_max_y-b.top);a.css("top",b.top+j);var f=a.position().top-b.top;instance.offset.parent.top+=f;h.position.top-=f;moved=true}if((!moved)&&(b.top>p_min_y)&&(mouse_y+close_dist>max_vis_y)){va r j=Math.min(nudge,b.top-p_min_x);a.css("top",(b.top-j)+"px");var f=b.top-a.position().top;instance.offset.parent.top-=f;h.position.top+=f;moved=true}h.position.left=Math.max(h.position.left,0);h.position.top=Math.max(h.position.top,0);h.position.left=Math.min(h.position.left,i-element_w);h.position.top=Math.min(h.position.top,d-element_h);if(moved){$.ui.ddmanager.prepareOffsets(instance,g)}if(moved){this.timeout=setTimeout(function(){instance.mouseMove(g)},50)}},stop:function(c,b){var a=$(this).data("draggable");clearTimeout(a.timeout)}}); \ No newline at end of file +function Terminal(a){this.element=a;this.connectors=[]}Terminal.prototype={connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}};function OutputTerminal(a,b){Terminal.call(this,a);this.datatype=b}OutputTerminal.prototype=new Terminal;function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal;$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(t in this.datatypes){if(a.datatype=="input"){return true}if(issubtype(a.datatype,this.datatypes[t])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a) }}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var o=function(c){return $(c).offset().left-d.offset().left};var j=function(c){return $(c).offset().top-d.offset().top};var i=o(this.handle1.element)+5;var g=j(this.handle1.element)+5;var q=o(this.handle2.element)+5;var n=j(this.handle2.element)+5;var f=100;var l=Math.min(i,q);var a=Math.max(i,q);var k=Math.min(g,n);var v=Math.max(g,n);var b=Math.min(Math.max(Math.abs(v-k)/2,100),300);var p=l-f;var u=k-f;var r=a-l+2*f;var m=v-k+2*f;this.canvas.style. left=p+"px";this.canvas.style.top=u+"px";this.canvas.setAttribute("width",r);this.canvas.setAttribute("height",m);i-=p;g-=u;q-=p;n-=u;var s=this.canvas.getContext("2d");s.lineCap="round";s.strokeStyle=this.outer_color;s.lineWidth=7;s.beginPath();s.moveTo(i,g);s.bezierCurveTo(i+b,g,q-b,n,q,n);s.stroke();s.strokeStyle=this.inner_color;s.lineWidth=5;s.beginPath();s.moveTo(i,g);s.bezierCurveTo(i+b,g,q-b,n,q,n);s.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){new Connector(g.dragTarget.terminal,g.dropTarget.terminal).redraw()}).bind("hover",function(){if(f. connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(j,i){i.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(l){return this.terminal.can_accept(f)}}).addClass("input-terminal-active");return i}).bind("drag", function(j){var i=function(){var l=$(j.dragProxy).offsetParent().offset(),k=j.offsetX-l.left,m=j.offsetY-l.top;$(j.dragProxy).css({left:k,top:m});j.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};i();$("#canvas-container").get(0).scroll_panel.test(j,i)}).bind("dragend",function(i){i.dragProxy.terminal.connectors[0].destroy();$(i.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a. parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var i=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);i.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extension);var f=b.name;if(b.extension!="input"){f=f+" ("+b.extension+")"}a.append($("<d iv class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(l,j){var k=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(k,j.name,j.extensions);g.find("div[name="+j.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){k[0].terminal.connectors[0]=i;i.handle2=k[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+j.name+"'>"+j.label+"</div>").prepend(k))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed( );this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(b,d){var f={};$.each(d.input_terminals,function(g,i){f[i.name]=null;$.each(i.connectors,function(j,k){f[i.name]={id:k.handle1.node.id,output _name:k.handle1.name}})});var c={id:d.id,type:d.type,tool_id:d.tool_id,tool_state:d.tool_state,tool_errors:d.tool_errors,input_connections:f,position:$(d.element).position()};a[d.id]=c});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(i,g){if(g){var j=wf.nodes[g.id];var l=new Connector();l.connect(j.output_terminals[g.output_name],c.input_terminals[i]);l.redraw()}})})},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.clear_active_node();parent.show_form_for_tool(a.form _html,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){parent.show_form_for_tool(a.form_html,a)}},layout:function(){var a={};var b={};$.each(this.nodes,function(i,g){if(a[i]===undefined){a[i]=0}if(b[i]===undefined){b[i]=[]}});$.each(this.nodes,function(i,g){$.each(g.input_terminals,function(k,l){$.each(l.connectors,function(m,n){var j=n.handle1.node;a[g.id]+=1;b[j.id].push(g.id)})})});node_ids_by_level=[];while(true){level_parents=[];$.each(a,function(i,g){if(g==0){level_parents.push(i)}});if(level_parents.length==0){break}node_ids_by_level.push(level_parents);$.each(level_parents,function(i,g){delete a[g];$.each(b[g],function(k,j){a[j]-=1})})}if(a.length){return}var d=this.nodes;var c=80;v_pad=30;var f=c;$.each(node_ids_by_level,function(g,j){j.sort(function(m,i){return $(d[m].element).position().top-$(d[i].element).position().top});var k=0;var l=v_pad;$.each(j,function(i,o){var n=d[o];var m=$(n.element);$(m).css ({top:l,left:f});k=Math.max(k,$(m).width());l+=$(m).height()+v_pad});f+=k+c});$.each(d,function(g,i){i.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(i,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var j=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var i=fix_delta(a.ymin,100);d=Math.max(d,f.left);i=Math.max(i,f.top);var c=f.left-d;var g=f.top-i;var b=round_up(a.xmax+100,100)+d;var k=round_up(a.ymax+100,100)+i;b=Math.max(b,-c+j.width());k=Math.max(k,-g+j.height());this.canvas_container.css({left:c,top:g,width:b,height:k,});this.canvas_container.children().each(function(){var l=$(this).position();$(this).css("left",l.left+d);$(this).css("top",l.top+i)})}});func tion fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(m,k,s){var j=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(j);g.type=m;if(m=="tool"){g.tool_id=s}var q=$("<div class='toolFormTitle unselectable'>"+k+"</div>");j.append(q);j.css("left",$(window).scrollLeft()+20);j.css("top",$(window).scrollTop()+20);var n=$("<div class='toolFormBody'></div>");var i="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";n.append(i);g.form_html=i;j.append(n);var l=$("<div class='buttons' style='float: right;'></div>");l.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));j.appendTo("#canvas-container");var d=$("#canvas-container").position( );var c=$("#canvas-container").parent();var a=j.width();var r=j.height();j.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(r/2)});l.prependTo(q);a+=(l.width()+10);j.css("width",a);$(j).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(f,c){clearTim eout(this.timeout);var a=f.pageX,g=f.pageY;b=$(this.panel),panel_pos=b.position(),panel_w=b.width(),panel_h=b.height();viewport=b.parent();viewport_w=viewport.width(),viewport_h=viewport.height(),viewport_offset=viewport.offset(),min_x=viewport_offset.left,min_y=viewport_offset.top,max_x=min_x+viewport.width(),max_y=min_y+viewport.height(),p_min_x=-(panel_w-(viewport_w/2)),p_min_y=-(panel_h-(viewport_h/2)),p_max_x=(viewport_w/2),p_max_y=(viewport_h/2),moved=false,close_dist=5,nudge=23;if(a-close_dist<min_x){if(panel_pos.left<p_max_x){var d=Math.min(nudge,p_max_x-panel_pos.left);b.css("left",panel_pos.left+d);moved=true}}else{if(a+close_dist>max_x){if(panel_pos.left>p_min_x){var d=Math.min(nudge,panel_pos.left-p_min_x);b.css("left",panel_pos.left-d);moved=true}}else{if(g-close_dist<min_y){if(panel_pos.top<p_max_y){var d=Math.min(nudge,p_max_y-panel_pos.top);b.css("top",panel_pos.top+d);moved=true}}else{if(g+close_dist>max_y){if(panel_pos.top>p_min_y){var d=Math.min(nudge,pane l_pos.top-p_min_x);b.css("top",(panel_pos.top-d)+"px");moved=true}}}}}if(moved){c();var b=this;this.timeout=setTimeout(function(){b.test(f,c)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var i=$(this).offset();var f=b.cc.position();c=f.top-i.top;d=f.left-i.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("dra g",function(l){var k=b.cc.width();var g=b.cc.height();var f=b.oc.width();var i=b.oc.height();var j=$(this).offsetParent().offset();var n=l.offsetX-j.left;var m=l.offsetY-j.top;a(-(n/f*k),-(m/i*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var j=$(this).offsetParent();var i=j.offset();var f=Math.max(j.width()-(g.offsetX-i.left),j.height()-(g.offsetY-i.top));$(this).css({width:f,height:f});b.draw_overview()})},update_viewport_overlay:function(){var b=this.cc;var f=this.cv;var a=this.oc;var c=this.ov;var d=b.width();var k=b.height();var j=a.width();var g=a.height();var i=b.position();c.css({left:-(i.left/d*j),top:-(i.top/k*g),width:(f.width()/d*j)-2,height:(f.height()/k*g)-2})},draw_overview:function(){var k=$("#overview-canvas");var n=k.parent().parent().width();var j=k.get(0).getContext("2d");var d=$("#canvas-container").width();var m=$("#canvas-container").height();var g,a,l,f;var i=this.cv.wi dth();var b=this.cv.height();if(d<i&&m<b){l=d/i*n;f=(n-l)/2;g=m/b*n;a=(n-g)/2}else{if(d<m){a=0;g=n;l=Math.ceil(g*d/m);f=(n-l)/2}else{l=n;f=0;g=Math.ceil(l*m/d);a=(n-g)/2}}k.parent().css({left:f,top:a,width:l,height:g});k.attr("width",l);k.attr("height",g);j.fillStyle="#D2C099";j.strokeStyle="#D8B365";j.lineWidth=1;$.each(workflow.nodes,function(p,c){var o=$(c.element);position=o.position(),x=position.left/d*l,y=position.top/m*g,w=o.width()/d*l,h=o.height()/m*g;j.fillRect(x,y,w,h);j.strokeRect(x,y,w,h)});this.update_viewport_overlay()}}); \ No newline at end of file
1
0
0
0
[hg] galaxy 2392: New quickie
by Greg Von Kuster
01 May '09
01 May '09
details:
http://www.bx.psu.edu/hg/galaxy/rev/84ecf82a2ce7
changeset: 2392:84ecf82a2ce7 user: Anton Nekrutenko <anton(a)bx.psu.edu> date: Fri May 01 11:09:04 2009 -0400 description: New quickie 3 file(s) affected in this change: static/images/qk/quickie5_lrg.png static/images/qk/quickie5_small.png static/welcome.html diffs (99 lines): diff -r 9ad7b4abbfc7 -r 84ecf82a2ce7 static/images/qk/quickie5_lrg.png Binary file static/images/qk/quickie5_lrg.png has changed diff -r 9ad7b4abbfc7 -r 84ecf82a2ce7 static/images/qk/quickie5_small.png Binary file static/images/qk/quickie5_small.png has changed diff -r 9ad7b4abbfc7 -r 84ecf82a2ce7 static/welcome.html --- a/static/welcome.html Fri May 01 10:11:00 2009 -0400 +++ b/static/welcome.html Fri May 01 11:09:04 2009 -0400 @@ -71,15 +71,15 @@ <div class="current-quickie"> <table border="0" cellpadding="0" cellspacing="0" width="100%"> - <tr> - <td align="center"> - <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie4_whatsnew/flow.html
',width:640,height:500,scroll:'no'})"> - <img src="images/qk/quickie4_lrg.png" border="0"> - <br> - </a> + <tr> + <td align="center"> + <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie5_join/flow.html
',width:640,height:500,scroll:'no'})"> + <img src="images/qk/quickie5_lrg.png" border="0"> + <br> + </a> - </td> - </tr> + </td> + </tr> </table> </div> @@ -87,34 +87,40 @@ <hr> <div class="previous"> - <table border="0" cellpadding="0" cellspacing="0" width="100%"> - <tr> - <td width="32%" style="border-right: solid white 10px;"> - <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie1_TabSeq/flow.html
',width:640,height:500,scroll:'no'})"> - <div class="quickie"> - <img src="images/qk/quickie1_small.png" border="0"> - </div> - </a> - </td> - <td width="32%" style="border-left: solid white 5px; border-right: solid white 5px"> - <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie2_Grouping/flow.html
',width:640,height:500,scroll:'no'})"> - <div class="quickie"> - <img src="images/qk/quickie2_small.png" border="0"> - </div> - </a> - </div> - </td> - <td width="32%" style="border-left: solid white 10px;" > - <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie3_Intervals/flow.html
',width:640,height:500,scroll:'no'})"> - <div class="quickie"> - <img src="images/qk/quickie3_small.png" border="0"> - </div> - </a> - </td> - - </tr> + <table border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> + <td width="50%" style="border-right: solid white 10px; border-bottom: solid white 10px"> + <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie1_TabSeq/flow.html
',width:640,height:500,scroll:'no'})"> + <div class="quickie"> + <img src="images/qk/quickie1_small.png" border="0"> + </div> + </a> + </td> + <td width="50%" style="border-left: solid white 10px; border-bottom: solid white 10px"> + <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie2_Grouping/flow.html
',width:640,height:500,scroll:'no'})"> + <div class="quickie"> + <img src="images/qk/quickie2_small.png" border="0"> + </div> + </a> + </td> + </tr> + <tr> + <td width="50%" style="border-right: solid white 10px; border-top: solid white 10px" > + <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie3_Intervals/flow.html
',width:640,height:500,scroll:'no'})"> + <div class="quickie"> + <img src="images/qk/quickie3_small.png" border="0"> + </div> + </a> + </td> + <td width="50%" style="border-left: solid white 10px; border-top: solid white 10px" > + <a href="javascript:parent.show_in_overlay({url:'
http://screencast.g2.bx.psu.edu/galaxy/quickie4_whatsNew/flow.html
',width:640,height:500,scroll:'no'})"> + <div class="quickie"> + <img src="images/qk/quickie4_small.png" border="0"> + </div> + </a> + </td> + </tr> </table> -</div> </div> <br/>
1
0
0
0
← Newer
1
2
3
4
5
Older →
Jump to page:
1
2
3
4
5
Results per page:
10
25
50
100
200