diff --git a/lib/galaxy/web/buildapp.py b/lib/galaxy/web/buildapp.py index a9ab866cdc2..797a4aca263 100644 --- a/lib/galaxy/web/buildapp.py +++ b/lib/galaxy/web/buildapp.py @@ -57,6 +57,8 @@ def app_factory( global_conf, **kwargs ): # Create the universe WSGI application webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxysession' ) add_controllers( webapp, app ) + # Force /history to go to /root/history -- needed since the tests assume this + webapp.add_route( '/history', controller='root', action='history' ) # These two routes handle our simple needs at the moment webapp.add_route( '/async/:tool_id/:data_id/:data_secret', controller='async', action='index', tool_id=None, data_id=None, data_secret=None ) webapp.add_route( '/:controller/:action', action='index' ) diff --git a/lib/galaxy/web/controllers/root.py b/lib/galaxy/web/controllers/root.py index e6abee11d59..faa2dd2540b 100644 --- a/lib/galaxy/web/controllers/root.py +++ b/lib/galaxy/web/controllers/root.py @@ -371,128 +371,13 @@ class RootController( BaseController ): """Displays a list of history related actions""" return trans.fill_template( "/history/options.mako", user = trans.get_user(), history = trans.get_history() ) - + @web.expose - def history_delete( self, trans, id=None, **kwd): - """Deletes a list of histories, ensures that histories are owned by current user""" - if trans.app.memory_usage: - # Keep track of memory usage - m0 = self.app.memory_usage.memory() - history_names = [] - if id: - if isinstance( id, list ): - history_ids = id - else: - history_ids = [ id ] - user = trans.get_user() - for hid in history_ids: - try: - int( hid ) - except: - return trans.show_message( "Invalid history: %s" % str( hid ) ) - history = self.app.model.History.get( hid ) - if history: - if history.user_id != None and user: - assert user.id == history.user_id, "History does not belong to current user" - # Delete DefaultHistoryPermissions - for dhp in history.default_permissions: - dhp.delete() - dhp.flush() - # Mark history as deleted in db - history.deleted = True - history_names.append(history.name) - # If deleting the current history, make a new current. - if history == trans.get_history(): - trans.new_history() - else: - return trans.show_message( "Not able to find history %s" % str( hid ) ) - self.app.model.flush() - trans.log_event( "History id %s marked as deleted" % str(hid) ) - else: - return trans.show_message( "You must select at least one history to delete." ) - if self.app.memory_usage: - m1 = trans.app.memory_usage.memory( m0, pretty=True ) - log.info( "End of root/history_delete, memory used increased by %s" % m1 ) - return trans.show_message( "History deleted: %s" % ",".join(history_names), - refresh_frames=['history']) - - @web.expose - def history_undelete( self, trans, id=[], **kwd): - """Undeletes a list of histories, ensures that histories are owned by current user""" - history_names = [] - errors = [] - ok_msg = "" - if id: - if not isinstance( id, list ): - id = id.split( "," ) - user = trans.get_user() - for hid in id: - try: - int( hid ) - except: - errors.append( "Invalid history: %s" % str( hid ) ) - continue - history = self.app.model.History.get( hid ) - if history: - if history.user != user: - errors.append( "History does not belong to current user." ) - continue - if history.purged: - errors.append( "History has already been purged and can not be undeleted." ) - continue - history_names.append( history.name ) - history.deleted = False - else: - errors.append( "Not able to find history %s." % str( hid ) ) - trans.log_event( "History id %s marked as undeleted" % str(hid) ) - self.app.model.flush() - if history_names: - ok_msg = "Histories (%s) have been undeleted." % ", ".join( history_names ) - else: - errors.append( "You must select at least one history to undelete." ) - return self.history_available( trans, id=','.join( id ), show_deleted=True, ok_msg = ok_msg, error_msg = " ".join( errors ) ) - - @web.expose - def history_undelete( self, trans, id=[], **kwd): - """Undeletes a list of histories, ensures that histories are owned by current user""" - if trans.app.memory_usage: - # Keep track of memory usage - m0 = self.app.memory_usage.memory() - history_names = [] - errors = [] - ok_msg = "" - if id: - if not isinstance( id, list ): - id = id.split( "," ) - user = trans.get_user() - for hid in id: - try: - int( hid ) - except: - errors.append( "Invalid history: %s" % str( hid ) ) - continue - history = self.app.model.History.get( hid ) - if history: - if history.user != user: - errors.append( "History does not belong to current user." ) - continue - if history.purged: - errors.append( "History has already been purged and can not be undeleted." ) - continue - history_names.append( history.name ) - history.deleted = False - else: - errors.append( "Not able to find history %s." % str( hid ) ) - trans.log_event( "History id %s marked as undeleted" % str(hid) ) - self.app.model.flush() - if history_names: - ok_msg = "Histories (%s) have been undeleted." % ", ".join( history_names ) - else: - errors.append( "You must select at least one history to undelete." ) - if self.app.memory_usage: - m1 = trans.app.memory_usage.memory( m0, pretty=True ) - log.info( "End of root/history_undelete, memory used increased by %s" % m1 ) - return self.history_available( trans, id=','.join( id ), show_deleted=True, ok_msg = ok_msg, error_msg = " ".join( errors ) ) + def history_delete( self, trans, id ): + """ + Backward compatibility with check_galaxy script. + """ + return trans.webapp.controllers['history'].list( trans, id, operation='delete' ) @web.expose def clear_history( self, trans ): @@ -510,117 +395,6 @@ class RootController( BaseController ): m1 = trans.app.memory_usage.memory( m0, pretty=True ) log.info( "End of root/clear_history, memory used increased by %s" % m1 ) trans.response.send_redirect( url_for("/index" ) ) - - @web.expose - @web.require_login( "share histories with other users" ) - def history_share( self, trans, id=None, email="", **kwd ): - send_to_err = "" - if not id: - id = trans.get_history().id - if not isinstance( id, list ): - id = [ id ] - histories = [] - history_names = [] - for hid in id: - histories.append( trans.app.model.History.get( hid ) ) - history_names.append(histories[-1].name) - if not email: - return trans.fill_template("/history/share.mako", histories=histories, email=email, send_to_err=send_to_err) - user = trans.get_user() - send_to_user = trans.app.model.User.filter( trans.app.model.User.table.c.email==email ).first() - params = util.Params( kwd ) - action = params.get( 'action', None ) - if action == "no_share": - trans.response.send_redirect( url_for( action='history_options' ) ) - if not send_to_user: - send_to_err = "No such user" - elif user.email == email: - send_to_err = "You can't send histories to yourself" - else: - if 'history_share_btn' in kwd or action != 'share': - # The user is attempting to share a history whose datasets cannot all be accessed by the other user. In this case, - # the user sharing the history can chose to make the datasets public ( action == 'public' ) if he has the authority - # to do so, or automatically create a new "sharing role" that allows the user to share his private datasets only with the - # desired user ( action == 'private' ). - can_change = {} - cannot_change = {} - for history in histories: - for hda in history.activatable_datasets: - # Only deal with datasets that have not been purged - if not trans.app.security_agent.allow_action( send_to_user, - trans.app.security_agent.permitted_actions.DATASET_ACCESS, - dataset=hda ): - # The user with which we are sharing the history does not have access permission on the current dataset - if trans.app.security_agent.allow_action( user, - trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, - dataset=hda ) and not hda.dataset.library_associations: - # The current user has authority to change permissions on the current dataset because - # they have permission to manage permissions on the dataset and the dataset is not associated - # with a library. - if action == "private": - trans.app.security_agent.privately_share_dataset( hda.dataset, users=[ user, send_to_user ] ) - elif action == "public": - trans.app.security_agent.make_dataset_public( hda.dataset ) - elif history not in can_change: - # Build the set of histories / datasets on which the current user has authority - # to "manage permissions". This is used in /history/share.mako - can_change[ history ] = [ hda ] - else: - can_change[ history ].append( hda ) - else: - if action in [ "private", "public" ]: - # Don't change stuff that the user doesn't have permission to change - continue - elif history not in cannot_change: - # Build the set of histories / datasets on which the current user does - # not have authority to "manage permissions". This is used in /history/share.mako - cannot_change[ history ] = [ hda ] - else: - cannot_change[ history ].append( hda ) - if can_change or cannot_change: - return trans.fill_template( "/history/share.mako", - histories=histories, - email=email, - send_to_err=send_to_err, - can_change=can_change, - cannot_change=cannot_change ) - for history in histories: - new_history = history.copy( target_user=send_to_user ) - new_history.name = history.name + " from " + user.email - new_history.user_id = send_to_user.id - trans.log_event( "History share, id: %s, name: '%s': to new id: %s" % ( str( history.id ), history.name, str( new_history.id ) ) ) - self.app.model.flush() - return trans.show_message( "History (%s) has been shared with: %s" % ( ",".join( history_names ),email ) ) - return trans.fill_template( "/history/share.mako", histories=histories, email=email, send_to_err=send_to_err ) - - @web.expose - @web.require_login( "work with multiple histories" ) - def history_available( self, trans, id=[], do_operation = "view", show_deleted = False, ok_msg = "", error_msg="", as_xml=False, **kwd ): - """ - List all available histories - """ - if trans.app.memory_usage: - # Keep track of memory usage - m0 = self.app.memory_usage.memory() - if as_xml: - trans.response.set_content_type('text/xml') - return trans.fill_template( "/history/list_as_xml.mako" ) - if not isinstance( id, list ): - id = id.split( "," ) - trans.log_event( "History id %s available" % str( id ) ) - history_operations = dict( share=self.history_share, rename=self.history_rename, delete=self.history_delete, undelete=self.history_undelete ) - if self.app.memory_usage: - m1 = trans.app.memory_usage.memory( m0, pretty=True ) - log.info( "End of root/history_available, memory used increased by %s" % m1 ) - if do_operation in history_operations: - return history_operations[do_operation]( trans, id=id, show_deleted=show_deleted, ok_msg=ok_msg, error_msg=error_msg, **kwd ) - return trans.fill_template( "/history/list.mako", ids=id, - user=trans.get_user(), - current_history=trans.get_history(), - show_deleted=util.string_as_bool( show_deleted ), - ok_msg=ok_msg, error_msg=error_msg ) - - @web.expose def history_import( self, trans, id=None, confirm=False, **kwd ): @@ -677,34 +451,6 @@ class RootController( BaseController ): Warning! If you import this history, you will lose your current history. Click here to confirm. """ % web.url_for( id=id, confirm=True ) ) - - @web.expose - @web.require_login( "switch histories" ) - def history_switch( self, trans, id=None ): - if not id: - return trans.response.send_redirect( web.url_for( action='history_available' ) ) - else: - if trans.app.memory_usage: - # Keep track of memory usage - m0 = self.app.memory_usage.memory() - new_history = trans.app.model.History.get( id ) - if new_history: - 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 switched to id: %s, name: '%s'" % (str(new_history.id), new_history.name ) ) - if self.app.memory_usage: - m1 = trans.app.memory_usage.memory( m0, pretty=True ) - log.info( "End of root/history_switch, memory used increased by %s" % m1 ) - return trans.show_message( "History switched to: %s" % new_history.name, - refresh_frames=['history']) - else: - return trans.show_error_message( "History not found" ) @web.expose def history_new( self, trans ): @@ -718,53 +464,6 @@ class RootController( BaseController ): log.info( "End of root/history_new, memory used increased by %s" % m1 ) return trans.show_message( "New history created", refresh_frames = ['history'] ) - @web.expose - @web.require_login( "renames histories" ) - def history_rename( self, trans, id=None, name=None, **kwd ): - if trans.app.memory_usage: - # Keep track of memory usage - m0 = self.app.memory_usage.memory() - user = trans.get_user() - - if not isinstance( id, list ): - if id != None: - id = [ id ] - if not isinstance( name, list ): - if name != None: - name = [ name ] - histories = [] - cur_names = [] - if not id: - if not trans.get_history().user: - return trans.show_error_message( "You must save your history before renaming it." ) - id = [trans.get_history().id] - for history_id in id: - history = trans.app.model.History.get( history_id ) - if history and history.user_id == user.id: - histories.append(history) - cur_names.append(history.name) - if not name or len(histories)!=len(name): - return trans.fill_template( "/history/rename.mako",histories=histories ) - change_msg = "" - for i in range(len(histories)): - if histories[i].user_id == user.id: - if name[i] == histories[i].name: - change_msg = change_msg + "

History: "+cur_names[i]+" is already named: "+name[i]+"

" - elif name[i] not in [None,'',' ']: - name[i] = escape(name[i]) - histories[i].name = name[i] - histories[i].flush() - change_msg = change_msg + "

History: "+cur_names[i]+" renamed to: "+name[i]+"

" - trans.log_event( "History renamed: id: %s, renamed to: '%s'" % (str(histories[i].id), name[i] ) ) - else: - change_msg = change_msg + "

You must specify a valid name for History: "+cur_names[i]+"

" - else: - change_msg = change_msg + "

History: "+cur_names[i]+" does not appear to belong to you.

" - if self.app.memory_usage: - m1 = trans.app.memory_usage.memory( m0, pretty=True ) - log.info( "End of root/history_rename, memory used increased by %s" % m1 ) - return trans.show_message( "

%s" % change_msg, refresh_frames=['history'] ) - @web.expose def history_add_to( self, trans, history_id=None, file_data=None, name="Data Added to History",info=None,ext="txt",dbkey="?",copy_access_from=None,**kwd ): """Adds a POSTed file to a History""" diff --git a/static/june_2007_style/base.css.tmpl b/static/june_2007_style/base.css.tmpl index b780a8acda6..fc06c2008ff 100644 --- a/static/june_2007_style/base.css.tmpl +++ b/static/june_2007_style/base.css.tmpl @@ -142,6 +142,7 @@ div.form-row label select, input, textarea { + font: inherit; font-size: 115%; } @@ -444,6 +445,30 @@ ul.manage-table-actions li { margin-left: 0.5em; } +## State colors + +.state-color-queued { + border-color: $history_queued_border; + background: $history_queued_bg; +} + +.state-color-ok { + border-color: $history_ok_border; + background: $history_ok_bg; +} + +.state-color-error { + border-color: $history_error_border; + background: $history_error_bg; +} + +.state-color-running { + border-color: $history_running_border; + background: $history_running_bg; +} + +## Button styles + .action-button { background: #eeeeee; color: #333; @@ -459,6 +484,9 @@ ul.manage-table-actions li { -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; border-radius: 0.5em; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; } .action-button > * { @@ -467,13 +495,15 @@ ul.manage-table-actions li { .action-button:hover { color: black; - background: #aaaaaa; + background: #dddddd; } .action-button:active { color: white; background: #aaaaaa; } +## Popup menu styles + div.popupmenu { display: none; background: #eeeeee; @@ -488,6 +518,9 @@ div.popupmenu { -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; border-radius: 0.5em; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; } div.popupmenu-item { @@ -515,3 +548,35 @@ div.popupmenu-item:hover { div.permissionContainer { padding-left: 20px; } + +## Data grid style + +.grid { + padding-top: 1em; + border-collapse: collapse; + width: 100%; +} +.grid tbody td { + border-top: solid #DDDDDD 1px; + border-bottom: solid #DDDDDD 1px; + padding: 0.5em 1em; +} +.grid thead th { + background: $table_header_bg; + background-image: url(form_title_bg.png); + background-repeat: repeat-x; + background-position: top; + border-top: solid $table_border 1px; + border-bottom: solid $table_border 1px; + padding: 0.5em 1em; + text-align: left; +} +.grid tfoot td { + background-color: #F8F8F8; + border-top: solid #DDDDDD 1px; + border-bottom: solid #DDDDDD 1px; + padding: 0.5em 1em; +} +.grid .current { + background-color: #EEEEFF; +} \ No newline at end of file diff --git a/static/june_2007_style/blue/base.css b/static/june_2007_style/blue/base.css index 173f0d6dfa4..2962cfb40b2 100644 --- a/static/june_2007_style/blue/base.css +++ b/static/june_2007_style/blue/base.css @@ -142,6 +142,7 @@ div.form-row label select, input, textarea { + font: inherit; font-size: 115%; } @@ -152,7 +153,7 @@ select, textarea, input[type="text"], input[type="file"] /* Messages */ -.errormessage, .warningmessage, .donemessage, .infomessage, .welcomeBlue, .welcomeRed, .screencastBox, .yellowbox, .redbox, .bluebox, .greenbox +.errormessage, .warningmessage, .donemessage, .infomessage, .welcomeBlue, .welcomeRed , .screencastBox, .yellowbox, .redbox, .bluebox, .greenbox { padding: 10px; padding-left: 52px; @@ -443,6 +444,28 @@ ul.manage-table-actions li { margin-left: 0.5em; } + +.state-color-queued { + border-color: #888888; + background: #EEEEEE; +} + +.state-color-ok { + border-color: #66AA66; + background: #CCFFCC; +} + +.state-color-error { + border-color: #AA6666; + background: #FFCCCC; +} + +.state-color-running { + border-color: #AAAA66; + background: #FFFFCC; +} + + .action-button { background: #eeeeee; color: #333; @@ -458,6 +481,9 @@ ul.manage-table-actions li { -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; border-radius: 0.5em; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; } .action-button > * { @@ -466,13 +492,14 @@ ul.manage-table-actions li { .action-button:hover { color: black; - background: #aaaaaa; + background: #dddddd; } .action-button:active { color: white; background: #aaaaaa; } + div.popupmenu { display: none; background: #eeeeee; @@ -487,6 +514,9 @@ div.popupmenu { -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; border-radius: 0.5em; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; } div.popupmenu-item { @@ -514,3 +544,34 @@ div.popupmenu-item:hover { div.permissionContainer { padding-left: 20px; } + + +.grid { + padding-top: 1em; + border-collapse: collapse; + width: 100%; +} +.grid tbody td { + border-top: solid #DDDDDD 1px; + border-bottom: solid #DDDDDD 1px; + padding: 0.5em 1em; +} +.grid thead th { + background: #ebd9b2; + background-image: url(form_title_bg.png); + background-repeat: repeat-x; + background-position: top; + border-top: solid #d8b365 1px; + border-bottom: solid #d8b365 1px; + padding: 0.5em 1em; + text-align: left; +} +.grid tfoot td { + background-color: #F8F8F8; + border-top: solid #DDDDDD 1px; + border-bottom: solid #DDDDDD 1px; + padding: 0.5em 1em; +} +.grid .current { + background-color: #EEEEFF; +} \ No newline at end of file diff --git a/static/june_2007_style/blue/panel_layout.css b/static/june_2007_style/blue/panel_layout.css index 7dda79706a8..e48f52009af 100644 --- a/static/june_2007_style/blue/panel_layout.css +++ b/static/june_2007_style/blue/panel_layout.css @@ -131,31 +131,6 @@ body right: 0px; z-index: 200; } -td.panel-header -{ - background: #f5f5f5; - background-image: url(panel_header_bg.png); - background-position: top center; - background-repeat: repeat-x; - padding: 0; - border-bottom: solid #999 1px; -} -div.panel-header -{ - margin: 0; - padding: 4px; - padding-right: 10px; - padding-left: 10px; - color: #333; - font-weight: bold; -} - -table.column-layout -{ - position: absolute; - width: 100%; - height: 100%; -} .unified-panel-header { height: 2em; @@ -171,6 +146,9 @@ table.column-layout padding-left: 10px; color: #333; font-weight: bold; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; } .unified-panel-header-inner { @@ -214,43 +192,6 @@ div.unified-panel-body { background: #aaaaaa; } -div.popupmenu { - display: none; - background: #eee; - position: fixed; - z-index: 20000; - background: #cccccc; - background-image: url(panel_header_bg.png); - background-position: top center; - background-repeat: repeat-x; - border: solid #999 1px; - padding-top: 3px; - padding-bottom: 3px; -} - -div.popupmenu-top { - padding-bottom: 3px; -} -div.popupmenu-top-inner { - height: 10px; - width: 20px; - margin-top: -13px; - margin-left: auto; - margin-right: 20px; - background: url(popupmenu_callout_top.png); -} - -div.popupmenu-item { - padding: 3px; - padding-left: 10px; - padding-right: 10px; - cursor: pointer; -} - -div.popupmenu-item:hover { - background: #AAAAEE; -} - #overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; diff --git a/static/june_2007_style/make_style.py b/static/june_2007_style/make_style.py index f3a6a08503a..5d62c7f1f56 100755 --- a/static/june_2007_style/make_style.py +++ b/static/june_2007_style/make_style.py @@ -1,11 +1,11 @@ #!/usr/bin/env python -from galaxy import eggs -import pkg_resources -pkg_resources.require("Cheetah") +#from galaxy import eggs +#import pkg_resources +#pkg_resources.require("Cheetah") import sys, string, os.path -from galaxy import eggs +#from galaxy import eggs import pkg_resources pkg_resources.require( "Cheetah" ) diff --git a/static/june_2007_style/panel_layout.css.tmpl b/static/june_2007_style/panel_layout.css.tmpl index 4df44dba18a..016b228a0e0 100644 --- a/static/june_2007_style/panel_layout.css.tmpl +++ b/static/june_2007_style/panel_layout.css.tmpl @@ -131,31 +131,6 @@ body right: 0px; z-index: 200; } -td.panel-header -{ - background: ${panel_header_bg_top}; - background-image: url(panel_header_bg.png); - background-position: top center; - background-repeat: repeat-x; - padding: 0; - border-bottom: solid ${layout_border} 1px; -} -div.panel-header -{ - margin: 0; - padding: 4px; - padding-right: 10px; - padding-left: 10px; - color: #333; - font-weight: bold; -} - -table.column-layout -{ - position: absolute; - width: 100%; - height: 100%; -} .unified-panel-header { height: 2em; @@ -171,6 +146,9 @@ table.column-layout padding-left: 10px; color: #333; font-weight: bold; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; } .unified-panel-header-inner { @@ -214,43 +192,6 @@ div.unified-panel-body { background: #aaaaaa; } -div.popupmenu { - display: none; - background: #eee; - position: fixed; - z-index: 20000; - background: ${panel_header_bg_bottom}; - background-image: url(panel_header_bg.png); - background-position: top center; - background-repeat: repeat-x; - border: solid ${layout_border} 1px; - padding-top: 3px; - padding-bottom: 3px; -} - -div.popupmenu-top { - padding-bottom: 3px; -} -div.popupmenu-top-inner { - height: 10px; - width: 20px; - margin-top: -13px; - margin-left: auto; - margin-right: 20px; - background: url(popupmenu_callout_top.png); -} - -div.popupmenu-item { - padding: 3px; - padding-left: 10px; - padding-right: 10px; - cursor: pointer; -} - -div.popupmenu-item:hover { - background: ${layout_hover}; -} - #overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; diff --git a/static/scripts/galaxy.base.js b/static/scripts/galaxy.base.js index a14244dcac8..f343c31269a 100644 --- a/static/scripts/galaxy.base.js +++ b/static/scripts/galaxy.base.js @@ -1,3 +1,19 @@ +$.fn.makeAbsolute = function(rebase) { + return this.each(function() { + var el = $(this); + var pos = el.position(); + el.css({ + position: "absolute", + marginLeft: 0, marginTop: 0, + top: pos.top, left: pos.left, + right: $(window).width() - ( pos.left + el.width() ) + }); + if (rebase) { + el.remove().appendTo("body"); + } + }); +} + jQuery(document).ready( function() { // Links with confirmation jQuery( "a[@confirm]" ).click( function() { diff --git a/templates/history/list.mako b/templates/history/list.mako index a30e5c5f7c2..a5de3273c68 100644 --- a/templates/history/list.mako +++ b/templates/history/list.mako @@ -1,65 +1,201 @@ <%inherit file="/base.mako"/> <%def name="title()">Your saved histories -%if error_msg: -

-

${error_msg}
-
-

-%endif -%if ok_msg: -

-

${ok_msg}
-
-

+%if message: +

+

${message}
+
+

%endif -%if user.histories: -

Stored Histories

- %if show_deleted: -
hide deleted
- %else: -
show deleted
- %endif -
- - - %for history in user.histories: - %if ( show_deleted and not history.purged ) or not( history.deleted ): - - - - - - +<%def name="javascripts()"> + ${parent.javascripts()} + + + +<%def name="stylesheets()"> + + + + + +

Stored Histories

+ + + + + %if show_deleted: + + %endif + +
NameSizeLast modifiedActions
- ${history.name} - %if history == trans.get_history(): - (current history) - %endif - ${len(history.active_datasets)}${str(history.update_time)[:19]} - %if not history.deleted: - rename
- switch to
- delete
- %else: - undelete
- %endif -
+ + + + + + + + + + + + + + %for i, history in enumerate( user.histories ): + + %if ( show_deleted and not history.purged ) or not( history.deleted ): + + + + + + + + + + + + + + + + + + %endif + + %endfor + + + + + + + + + + +
Name (click to activate)Datasets (by state)StatusLast update
+ %if not history.deleted: + ${history.name} + + %else: + ${history.name} + %endif + + + <% + total_ok = sum( 1 for d in history.active_datasets if d.state == 'ok' ) + total_running = sum( 1 for d in history.active_datasets if d.state == 'running' ) + total_queued = sum( 1 for d in history.active_datasets if d.state == 'queued' ) + total_error = sum( 1 for d in history.active_datasets if d.state == 'error' ) + %> + + %if total_ok: +
${total_ok}
+ %else: +
+ %endif + + %if total_error: +
${total_error}
+ %endif + + %if total_running: +
${total_running}
+ %else: +
+ %endif + + %if total_queued: +
${total_queued}
+ %else: +
+ %endif + +
+ %if history == trans.get_history(): + active + %endif + %if history.deleted: + deleted + %endif + ${h.date.distance_of_time_in_words( history.update_time, h.date.datetime.utcnow() )} +
+ + %if not history.deleted: + rename
+ switch to
+ delete
+ %else: + undelete
+ %endif + +
+
+ For selected histories: + + + + %if show_deleted: + + %endif +
+
-%else: - You have no stored histories -%endif + + + diff --git a/templates/history/options.mako b/templates/history/options.mako index 14b3e981455..bb807cb2e97 100644 --- a/templates/history/options.mako +++ b/templates/history/options.mako @@ -11,16 +11,16 @@ diff --git a/templates/history/rename.mako b/templates/history/rename.mako index 07b9a4a9ee2..02b5f01c7c3 100644 --- a/templates/history/rename.mako +++ b/templates/history/rename.mako @@ -4,7 +4,7 @@
Rename History
-
+ %for history in histories: diff --git a/templates/history/share.mako b/templates/history/share.mako index 605693f630f..3ec8a41581e 100644 --- a/templates/history/share.mako +++ b/templates/history/share.mako @@ -5,7 +5,7 @@
Share Histories
Current NameNew Name
- + %for history in histories: @@ -39,7 +39,7 @@ vertical-align: top; } - + %for history in histories: %endfor diff --git a/test/base/twilltestcase.py b/test/base/twilltestcase.py index ef0ccecb703..0f09a8c4d0a 100644 --- a/test/base/twilltestcase.py +++ b/test/base/twilltestcase.py @@ -13,7 +13,7 @@ from elementtree import ElementTree buffer = StringIO.StringIO() #Force twill to log to a buffer -- FIXME: Should this go to stdout and be captured by nose? -twill.set_output(buffer) +## twill.set_output(buffer) tc.config('use_tidy', 0) # Dial ClientCookie logging down (very noisy) @@ -107,10 +107,10 @@ class TwillTestCase( unittest.TestCase ): history_list = self.get_histories() self.assertTrue( history_list ) if id is None: - history = history_list[-1] + history = history_list[0] id = history.get( 'id' ) id = str( id ) - self.visit_page( "history_delete?id=%s" %(id) ) + self.visit_page( "history/list?operation=delete&id=%s" %(id) ) def get_histories( self ): """Returns all histories""" @@ -135,7 +135,7 @@ class TwillTestCase( unittest.TestCase ): def histories_as_xml_tree( self ): """Returns a parsed xml object of all histories""" self.home() - self.visit_page( 'history_available?as_xml=True' ) + self.visit_page( 'history/list_as_xml' ) xml = self.last_page() tree = ElementTree.fromstring(xml) return tree @@ -164,7 +164,7 @@ class TwillTestCase( unittest.TestCase ): old_name = elem.get( 'name' ) self.assertTrue( old_name ) id = str( id ) - self.visit_page( "history_rename?id=%s&name=%s" %(id, name) ) + self.visit_page( "history/rename?id=%s&name=%s" %(id, name) ) return id, old_name, name def set_history( self ): @@ -188,25 +188,25 @@ class TwillTestCase( unittest.TestCase ): id = str( id ) name = elem.get( 'name' ) self.assertTrue( name ) - self.visit_url( "%s/history_share?id=%s&email=%s&history_share_btn=Submit" % ( self.url, id, email ) ) + self.visit_url( "%s/history/share?id=%s&email=%s&history_share_btn=Submit" % ( self.url, id, email ) ) return id, name, email def share_history_containing_private_datasets( self, history_id, email='test@bx.psu.edu' ): """Attempt to share a history containing private datasets with a different user""" - self.visit_url( "%s/history_share?id=%s&email=%s&history_share_btn=Submit" % ( self.url, history_id, email ) ) + self.visit_url( "%s/history/share?id=%s&email=%s&history_share_btn=Submit" % ( self.url, history_id, email ) ) self.last_page() self.check_page_for_string( "The history or histories you've chosen to share contain datasets" ) self.check_page_for_string( "How would you like to proceed?" ) self.home() def make_datasets_public( self, history_id, email='test@bx.psu.edu' ): """Make private datasets public in order to share a history with a different user""" - self.visit_url( "%s/history_share?id=%s&email=%s&action=public&submit=Ok" % ( self.url, history_id, email ) ) + self.visit_url( "%s/history/share?id=%s&email=%s&action=public&submit=Ok" % ( self.url, history_id, email ) ) self.last_page() check_str = "History (Unnamed history) has been shared with: %s" % email self.check_page_for_string( check_str ) self.home() def privately_share_dataset( self, history_id, email='test@bx.psu.edu' ): """Make private datasets public in order to share a history with a different user""" - self.visit_url( "%s/history_share?id=%s&email=%s&action=private&submit=Ok" % ( self.url, history_id, email ) ) + self.visit_url( "%s/history/share?id=%s&email=%s&action=private&submit=Ok" % ( self.url, history_id, email ) ) self.last_page() check_str = "History (Unnamed history) has been shared with: %s" % email self.check_page_for_string( check_str ) @@ -223,10 +223,10 @@ class TwillTestCase( unittest.TestCase ): hid = str(hid) elems = [ elem for elem in data_list if elem.get('hid') == hid ] self.assertEqual(len(elems), 1) - self.visit_page( "history_switch?id=%s" % elems[0].get('id') ) + self.visit_page( "history/list?operation=switch&id=%s" % elems[0].get('id') ) def view_stored_histories( self ): - self.visit_page( "history_available" ) + self.visit_page( "history/list" ) # Functions associated with datasets (history items) and meta data def get_job_stderr( self, id ): @@ -554,7 +554,10 @@ class TwillTestCase( unittest.TestCase ): tc.submit( button ) def visit_page( self, page ): - tc.go("./%s" % page) + # tc.go("./%s" % page) + if not page.startswith( "/" ): + page = "/" + page + tc.go( self.url + page ) tc.code( 200 ) def visit_url( self, url ): diff --git a/test/functional/test_history_functions.py b/test/functional/test_history_functions.py index 31d0c0fd499..89f9aa3accb 100644 --- a/test/functional/test_history_functions.py +++ b/test/functional/test_history_functions.py @@ -16,7 +16,7 @@ class TestHistory( TwillTestCase ): if len(self.get_history()) > 0: raise AssertionError("test_new_history_then_delete failed") self.delete_history() - self.check_page_for_string( 'History deleted:' ) + self.check_page_for_string( 'Deleted 1 histories' ) def test_10_history_options_when_logged_in( self ): """Testing history options when logged in""" self.history_options() @@ -32,10 +32,10 @@ class TestHistory( TwillTestCase ): """Testing viewing previously stored histories""" self.view_stored_histories() self.check_page_for_string( 'Stored Histories' ) - self.check_page_for_string( '
History Name:Number of Datasets:Share Link