diff --git a/lib/galaxy/web/__init__.py b/lib/galaxy/web/__init__.py index d32cd9f7353..703d0735084 100644 --- a/lib/galaxy/web/__init__.py +++ b/lib/galaxy/web/__init__.py @@ -2,5 +2,5 @@ The Galaxy web application. """ -from framework import expose, json, url_for, error, FormBuilder +from framework import expose, json, require_login, url_for, error, FormBuilder diff --git a/lib/galaxy/web/controllers/root.py b/lib/galaxy/web/controllers/root.py index 330a75c3530..ec91a04cf1c 100644 --- a/lib/galaxy/web/controllers/root.py +++ b/lib/galaxy/web/controllers/root.py @@ -13,12 +13,7 @@ import urllib log = logging.getLogger( __name__ ) -class Universe( BaseController ): - pref_cookie_name = 'universe_prefs' - - @web.expose - def generate_error( self, trans ): - raise Exception( "Fake error!" ) +class RootController( BaseController ): @web.expose def default(self, trans, target1=None, target2=None, **kwd): @@ -26,50 +21,32 @@ class Universe( BaseController ): @web.expose def index(self, trans, id=None, tool_id=None, mode=None, **kwd): - # if mode: - # trans.set_cookie(name=self.pref_cookie_name, value=mode) - # else: - # mode = trans.get_cookie(name=self.pref_cookie_name) - # trans.ensure_valid_galaxy_session() - # result = trans.fill_template('index_frames.tmpl', mode=mode) - # return [ result ] if trans.app.config.get( "use_new_layout", "false" ) == "true": return trans.fill_template( "root/index.tmpl", tool_id=tool_id ) else: return trans.fill_template( "index_frames.tmpl" ) + ## ---- Tool related ----------------------------------------------------- + @web.expose def tool_menu( self, trans ): return trans.fill_template('tool_menu.tmpl', toolbox=self.get_toolbox() ) @web.expose - def last_hid( self, trans ): - """Returns the largest (last) history id""" - trans.response.set_content_type("text/plain") - history = trans.get_history() - # if history.datasets : - # maxhid = max( [ data.hid for data in history.datasets ] ) - # else: - # maxhid = -1 - if len( history.datasets ) > 0: - return len( history.datasets ) + 1 + def tool_help( self, trans, id ): + """Return help page for tool identified by 'id' if available""" + toolbox = self.get_toolbox() + tool = toolbox.tools_by_id.get(id, '') + yield "" + if not tool: + yield "Unknown tool id '%d'" % id + elif tool.help: + yield tool.help else: - return -1 - return str(maxhid) - - @web.expose - def last_dataset_id( self, trans ): - """Returns the largest (last) dataset id""" - trans.response.set_content_type("text/plain") - history = trans.get_history() - # if history.datasets : - # maxhid = max( [ data.hid for data in history.datasets ] ) - # else: - # maxhid = -1 - if len( history.datasets ) > 0: - return history.datasets[-1].id - else: - return -1 + yield "No additional help available for tool '%s'" % tool.name + yield "" + + ## ---- Root history display --------------------------------------------- @web.expose def history( self, trans, as_xml=False ): @@ -87,8 +64,55 @@ class Universe( BaseController ): return trans.fill_template_mako( "root/history_as_xml.mako", history=history ) else: template = "root/history.mako" - mode = trans.get_cookie( name=self.pref_cookie_name ) - return trans.fill_template( "root/history.mako", history=history, mode=mode ) + return trans.fill_template( "root/history.mako", history=history ) + + @web.expose + def dataset_state ( self, trans, id=None, stamp=None ): + if id is not None: + try: + data = self.app.model.Dataset.get( id ) + except: + return trans.show_error_message( "Unable to check dataset %s." %str( id ) ) + trans.response.headers['X-Dataset-State'] = data.state + trans.response.headers['Pragma'] = 'no-cache' + trans.response.headers['Expires'] = '0' + return data.state + else: + return trans.show_error_message( "Must specify a dataset id.") + + @web.expose + def dataset_code( self, trans, id=None, hid=None, stamp=None ): + if id is not None: + try: + data = self.app.model.Dataset.get( id ) + except: + return trans.show_error_message( "Unable to check dataset %s." %str( id ) ) + trans.response.headers['Pragma'] = 'no-cache' + trans.response.headers['Expires'] = '0' + return trans.fill_template("root/history_item.mako", data=data, hid=hid) + else: + return trans.show_error_message( "Must specify a dataset id.") + + @web.json + def history_item_updates( self, trans, ids=None, states=None ): + # Avoid caching + trans.response.headers['Pragma'] = 'no-cache' + trans.response.headers['Expires'] = '0' + # Create new HTML for any that have changed + rval = {} + if ids is not None and states is not None: + ids = map( int, ids.split( "," ) ) + states = states.split( "," ) + for id, state in zip( ids, states ): + data = self.app.model.Dataset.get( id ) + if data.state != state: + rval[id] = { + "state": data.state, + "html": trans.fill_template( "root/history_item.mako", data=data, hid=data.hid ) + } + return rval + + ## ---- Dataset display / editing ---------------------------------------- @web.expose def display(self, trans, id=None, hid=None, tofile=None, toext=".txt"): @@ -298,10 +322,13 @@ class Universe( BaseController ): pass # upload tool will cause this since it doesn't have a job return "OK" + ## ---- History management ----------------------------------------------- + @web.expose def history_options( self, trans ): - """Displays a list of history related actions""" - return trans.fill_template( "history_options.tmpl", history = trans.get_history() ) + """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): @@ -344,45 +371,12 @@ class Universe( BaseController ): dataset.deleted = True self.app.model.flush() trans.log_event( "History id %s cleared" % (str(history.id)) ) - trans.response.send_redirect("/index") - - @web.expose - def tool_help( self, trans, id ): - """Return help page for tool identified by 'id' if available""" - toolbox = self.get_toolbox() - tool = toolbox.tools_by_id.get(id, '') - yield "" - if not tool: - yield "Unknown tool id '%d'" % id - elif tool.help: - yield tool.help - else: - yield "No additional help available for tool '%s'" % tool.name - yield "" - - # @web.expose - # def share_history( self, trans, id=None, create=None ): - # """Shares the history""" - # history = trans.get_history() - # if create: - # # create a new history - # history = obj.History() - # history.store() - # history = trans.get_history(id=history.id) - # trans.response.send_redirect("/index") - # elif id: - # # load a previous one - # history = trans.get_history(id=id) - # trans.response.send_redirect("/index") - # - # url = '%s/share_history?id=%s' % (trans.request.base, history.id) - # return trans.fill_template( "share.tmpl", url=url) - + 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=None, **kwd ): send_to_err = "" - user = trans.get_user() if not id: id = trans.get_history().id if not isinstance( id, list ): @@ -393,7 +387,7 @@ class Universe( BaseController ): histories.append( trans.app.model.History.get( hid ) ) history_names.append(histories[-1].name) if not email: - return trans.fill_template("history_share.tmpl", histories=histories, user=user, email=email, send_to_err=send_to_err) + return trans.fill_template("/history/share.mako", histories=histories, email=email, send_to_err=send_to_err) send_to_user = trans.app.model.User.get_by( email = email ) if not send_to_user: @@ -409,20 +403,23 @@ class Universe( BaseController ): 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.tmpl", histories=histories, user=user, email=email, send_to_err=send_to_err) + 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=None, as_xml=False, **kwd ): """ List all available histories """ if as_xml: trans.response.set_content_type('text/xml') - return trans.fill_template( "history_ids.xml" ) + return trans.fill_template( "/history/list_as_xml.mako" ) if not isinstance( id, list ): id = [ id ] trans.log_event( "History id %s available" % str( id ) ) - return trans.fill_template( "history_available.tmpl", ids=id ) + return trans.fill_template( "/history/list.mako", ids=id, + user=trans.get_user(), + current_history=trans.get_history() ) @web.expose def history_import( self, trans, id=None, confirm=False, **kwd ): @@ -445,7 +442,9 @@ class Universe( BaseController ): 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.fill_template("history_imported.tmpl", history=new_history) + return trans.show_ok_message( """ + History "%s" has been imported. Click here + 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 @@ -454,59 +453,19 @@ class Universe( BaseController ): 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.fill_template("history_imported.tmpl", history=new_history) - return trans.fill_template("history_import.tmpl", history=import_history) - - @web.expose - def dataset_state ( self, trans, id=None, stamp=None ): - if id is not None: - try: - data = self.app.model.Dataset.get( id ) - except: - return trans.show_error_message( "Unable to check dataset %s." %str( id ) ) - trans.response.headers['X-Dataset-State'] = data.state - trans.response.headers['Pragma'] = 'no-cache' - trans.response.headers['Expires'] = '0' - return data.state - else: - return trans.show_error_message( "Must specify a dataset id.") - - @web.expose - def dataset_code( self, trans, id=None, hid=None, stamp=None ): - if id is not None: - try: - data = self.app.model.Dataset.get( id ) - except: - return trans.show_error_message( "Unable to check dataset %s." %str( id ) ) - trans.response.headers['Pragma'] = 'no-cache' - trans.response.headers['Expires'] = '0' - return trans.fill_template("root/history_item.mako", data=data, hid=hid) - else: - return trans.show_error_message( "Must specify a dataset id.") - - @web.json - def history_item_updates( self, trans, ids=None, states=None ): - # Avoid caching - trans.response.headers['Pragma'] = 'no-cache' - trans.response.headers['Expires'] = '0' - # Create new HTML for any that have changed - rval = {} - if ids is not None and states is not None: - ids = map( int, ids.split( "," ) ) - states = states.split( "," ) - for id, state in zip( ids, states ): - data = self.app.model.Dataset.get( id ) - if data.state != state: - rval[id] = { - "state": data.state, - "html": trans.fill_template( "root/history_item.mako", data=data, hid=data.hid ) - } - return rval + return trans.show_ok_message( """ + History "%s" has been imported. Click here + 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 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.fill_template( "history_switch.tmpl" ) + return trans.response.send_redirect( web.url_for( action='history_available' ) ) else: new_history = trans.app.model.History.get( id ) if new_history: @@ -524,32 +483,12 @@ class Universe( BaseController ): trans.new_history() trans.log_event( "Created new History, id: %s." % str(trans.get_history().id) ) return trans.show_message( "New history created", refresh_frames = ['history'] ) - - @web.expose - def history_store( self, trans, name=None ): - user = trans.get_user() - if not user: - return trans.show_error_message( "Must be logged in to save history" ) - history = trans.get_history() - if history.user: - if history.user == user: - return trans.show_error_message( "Current history already stored (name: %s)" % history.name ) - else: - return trans.show_error_message( "Current history already associated with a different user" ) - if not name: - return trans.fill_template( "history_store.tmpl" ) - name = escape(name.replace("\n","").replace("\r","")) - history.name = name - history.user = user - trans.app.model.flush() - trans.log_event( "History stored, id: %s, name: '%s'" % (str(history.id), history.name ) ) - return trans.show_message( "Current history stored as %s" % name, refresh_frames=['history'] ) @web.expose + @web.require_login( "renames histories" ) def history_rename( self, trans, id=None, name=None, **kwd ): user = trans.get_user() - if not user: - return trans.show_error_message( "Must be logged in to rename your history" ) + if not isinstance( id, list ): if id != None: id = [ id ] @@ -568,7 +507,7 @@ class Universe( BaseController ): histories.append(history) cur_names.append(history.name) if not name or len(histories)!=len(name): - return trans.fill_template( "history_rename.tmpl",histories=histories ) + return trans.fill_template( "/history/rename.mako",histories=histories ) change_msg = "" for i in range(len(histories)): if histories[i].user_id == user.id: @@ -584,7 +523,7 @@ class Universe( BaseController ): 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.

" - return trans.show_message( "

Rename history

%s" % change_msg, refresh_frames=['history'] ) + 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="?",**kwd ): @@ -676,3 +615,7 @@ class Universe( BaseController ): if isinstance( kwd[k], FieldStorage ): rval += "-> %s" % kwd[k].file.read() return rval + + @web.expose + def generate_error( self, trans ): + raise Exception( "Fake error!" ) \ No newline at end of file diff --git a/lib/galaxy/web/framework/__init__.py b/lib/galaxy/web/framework/__init__.py index 42f1eb3eb80..fc4485996b4 100644 --- a/lib/galaxy/web/framework/__init__.py +++ b/lib/galaxy/web/framework/__init__.py @@ -47,6 +47,18 @@ def json( func ): decorator._orig = func decorator.exposed = True return decorator + +def require_login( verb="perform this action" ): + def argcatcher( func ): + def decorator( self, trans, *args, **kwargs ): + if trans.get_user(): + return func( self, trans, *args, **kwargs ) + else: + return trans.show_error_message( + "You must be logged in to %s" + % ( url_for( controller='user', action='login' ), verb ) ) + return decorator + return argcatcher NOT_SET = object() @@ -338,7 +350,7 @@ class UniverseWebTransaction( base.DefaultWebTransaction ): """ Convenience method for displaying an warn message. See `show_message`. """ - return self.show_message( message, 'warn', refresh_frames ) + return self.show_message( message, 'warning', refresh_frames ) def show_form( self, form ): """ Convenience method for displaying a simple page with a single HTML diff --git a/templates/base.mako b/templates/base.mako index f5bfac89e0e..bca9403263a 100644 --- a/templates/base.mako +++ b/templates/base.mako @@ -5,6 +5,7 @@ ${self.title()} ${self.stylesheets()} +${self.javascripts()} @@ -18,4 +19,9 @@ ${self.stylesheets()} ## Default stylesheets <%def name="stylesheets()"> + + +## Default javascripts +<%def name="javascripts()"> + \ No newline at end of file diff --git a/templates/history/list.mako b/templates/history/list.mako new file mode 100644 index 00000000000..680e0500f10 --- /dev/null +++ b/templates/history/list.mako @@ -0,0 +1,75 @@ +<%inherit file="/base.mako"/> +<%def name="title()">Your saved histories + +<%def name="javascripts()"> +${parent.javascripts()} + + + +%if user.histories: +

Stored Histories

+
+ + + %for history in user.histories: + %if not( history.deleted ): + + + + + + + %endif + %endfor + + + +
NameSizeLast modifiedActions
${history.name} + %if history.deleted: + (deleted) + %endif + ${len(history.active_datasets)}${str(history.update_time)[:19]} + rename
+ switch to
+ delete +
Action
Share Rename Delete
+
+%else: + You have no stored histories +%endif + \ No newline at end of file diff --git a/templates/history/list_as_xml.mako b/templates/history/list_as_xml.mako new file mode 100644 index 00000000000..6359850e77a --- /dev/null +++ b/templates/history/list_as_xml.mako @@ -0,0 +1,7 @@ + + + %for i, history in enumerate( t.user.histories ): + + + %endfor + diff --git a/templates/history/options.mako b/templates/history/options.mako new file mode 100644 index 00000000000..d7949270634 --- /dev/null +++ b/templates/history/options.mako @@ -0,0 +1,39 @@ +<%inherit file="/base.mako"/> +<%def name="title()">Your saved histories + +<%def name="javascripts()"> +${parent.javascripts()} + + + +

History Options

+ +%if not user: +
+
You must be logged in to store or switch histories.
+
+%endif + + + diff --git a/templates/history/rename.mako b/templates/history/rename.mako new file mode 100644 index 00000000000..07b9a4a9ee2 --- /dev/null +++ b/templates/history/rename.mako @@ -0,0 +1,19 @@ +<%inherit file="/base.mako"/> +<%def name="title()">Rename History + +
+
Rename History
+
+
+ + + %for history in histories: + + %endfor + +
Current NameNew Name
${history.name}
+
+
+
+ + \ No newline at end of file diff --git a/templates/history/share.mako b/templates/history/share.mako new file mode 100644 index 00000000000..5fd21c11a0f --- /dev/null +++ b/templates/history/share.mako @@ -0,0 +1,30 @@ +<%inherit file="/base.mako"/> +<%def name="title()">Share histories + +
+
Share Histories
+ + + + %for history in histories: + + + + %endfor + + %if send_to_err: + + %endif + + +
History Name:Number of Datasets:Share Link
${history.name} + + %if len(history.datasets) < 1: +
+ This history contains no data. +
+ %else: + ${len(history.datasets)} + %endif +
copy link to share
Email of User to share with:
${send_to_err}
+
\ No newline at end of file diff --git a/templates/history_available.tmpl b/templates/history_available.tmpl deleted file mode 100644 index 7d7e67bc64c..00000000000 --- a/templates/history_available.tmpl +++ /dev/null @@ -1,103 +0,0 @@ - - - - Available Histories - - - - - - - - - #set $user = $t.user - #set $history = $t.history - #if $user - - #if $history.user is None and $history.datasets -
- Your current history has not been stored - and will be lost if you switch to another history. -
- #end if - - #if $user.histories -

Stored Histories

-
- - - #for $history in $user.histories - #if not( $history.deleted ) - - - - - - - #end if - #end for - - - -
NameSizeLast modifiedActions
$history.name - #if $history.deleted - (deleted) - #end if - ${len(history.active_datasets)}${str(history.update_time)[:19]} - rename
- switch to
- delete -
Action
Share Rename Delete
-
- #else - You have no stored histories - #end if - - #else - -
- You must be logged in to store and switch histories -
- - #end if - - - diff --git a/templates/history_ids.xml b/templates/history_ids.xml deleted file mode 100644 index 9059477b0c6..00000000000 --- a/templates/history_ids.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - #set $i=1 - #for $data in $t.user.histories - - #set $i=$i+1 - - #end for - diff --git a/templates/history_import.tmpl b/templates/history_import.tmpl deleted file mode 100644 index b803bb25c51..00000000000 --- a/templates/history_import.tmpl +++ /dev/null @@ -1,15 +0,0 @@ - - - - Import History - - - - -
-
Import History
-
- Warning! If you import this history, you will lose your current history. Click here to confirm. -
- - diff --git a/templates/history_imported.tmpl b/templates/history_imported.tmpl deleted file mode 100644 index 0dc984a8890..00000000000 --- a/templates/history_imported.tmpl +++ /dev/null @@ -1,15 +0,0 @@ - - - - History Imported - - - - -
-
History Imported
-
- History "$history.name" has been imported. Click here to begin. -
- - diff --git a/templates/history_options.tmpl b/templates/history_options.tmpl deleted file mode 100644 index 06a8e519c4d..00000000000 --- a/templates/history_options.tmpl +++ /dev/null @@ -1,45 +0,0 @@ - - - - History Options - - - - - - - -

History Options

- -#if not $t.user: -
-
You must be logged in to store or switch histories.
-
-#end if - -
-#end if -
  • Delete current history
  • - - - - diff --git a/templates/history_rename.tmpl b/templates/history_rename.tmpl deleted file mode 100644 index 66012cfd994..00000000000 --- a/templates/history_rename.tmpl +++ /dev/null @@ -1,27 +0,0 @@ - - - - -Rename History - - - - - - -
    -
    Rename History
    -
    -
    - - - #for $history in $histories: - - #end for - - -
    Current NameNew Name
    $history.name
    -
    -
    - - \ No newline at end of file diff --git a/templates/history_share.tmpl b/templates/history_share.tmpl deleted file mode 100644 index b601f7e8b1e..00000000000 --- a/templates/history_share.tmpl +++ /dev/null @@ -1,47 +0,0 @@ - - - - Share History - - - - - - #if $user - - -
    -
    Share Histories
    - - - - #for $history in $histories: - - - - #end for - - #if $send_to_err: - - #end if - - -
    History Name:Number of Datasets:Share Link
    $history.name - - #if $len($history.datasets) < 1: -
    - This history contains no data. -
    - #else: - $len($history.datasets) - #end if -
    copy link to share
    Email of User to share with:
    $send_to_err
    - #else - -
    - You must be logged in to send histories to other users. -
    - #end if - - - diff --git a/templates/history_store.tmpl b/templates/history_store.tmpl deleted file mode 100644 index 9ddb532cd0e..00000000000 --- a/templates/history_store.tmpl +++ /dev/null @@ -1,23 +0,0 @@ - - - - User Create - - - - - -
    -
    Store current history
    -
    -
    - - - -
    History name:
    -
    -
    -
    - - - diff --git a/templates/history_switch.tmpl b/templates/history_switch.tmpl deleted file mode 100644 index cb56dfefb95..00000000000 --- a/templates/history_switch.tmpl +++ /dev/null @@ -1,45 +0,0 @@ - - - - Switch History - - - - - - #set $user = $t.user - #set $history = $t.history - #if $user - - #if $history.user is None and $history.datasets -
    - Your current history has not been stored - and will be lost if you switch to another history. -
    - #end if - - #if $user.histories -

    Stored Histories

    - - - - #for $history in $user.histories: - #if not( $history.deleted ) - - #end if - #end for -
    Name# datasetscreated
    $history.name ${len(history.datasets)}$history.create_timeswitch to
    - #else - You have no stored histories - #end if - - #else - -
    - You must be logged in to store and switch histories -
    - - #end if - - -