Ticket #3950: trac_3950.patch

File trac_3950.patch, 27.2 kB (added by mhansen, 1 month ago)
  • a/sage/server/notebook/notebook.py

    old new  
    9494        # This must happen after twist.notebook is set.  
    9595        self.save() 
    9696 
     97    def all_worksheets(self): 
     98        return self.__worksheets 
    9799         
    98100    def _migrate_worksheets(self): 
    99101        v = [] 
     
    12961298 
    12971299        X = self.get_worksheets_with_viewer(user) 
    12981300        if typ == "trash": 
    1299             worksheet_heading = "Trash
     1301            worksheet_heading = "Deleted Worksheets
    13001302            W = [x for x in X if x.is_trashed(user)] 
    13011303        elif typ == "active": 
    13021304            worksheet_heading = "Active Worksheets" 
     
    13111313         
    13121314        top = self.html_worksheet_list_top(user, typ=typ, search=search) 
    13131315        list = self.html_worksheet_list(W, user, worksheet_heading, sort=sort, reverse=reverse, typ=typ) 
    1314         worksheet_filenames = [x.filename() for x in W] 
    13151316         
    13161317        s = """ 
    13171318        <html> 
     
    13361337        else: 
    13371338            entries.append(('/home/%s'%user, 'Home', 'Back to your personal worksheet list')) 
    13381339            entries.append(('/pub', 'Published', 'Browse the published worksheets')) 
    1339             #entries.append(('/settings', 'Settings', 'Change user settings'))   # TODO -- settings 
    13401340            entries.append(('help()', 'Help', 'Documentation')) 
    13411341 
    13421342        ## TODO -- settings 
  • a/sage/server/notebook/template.py

    old new  
    1212HTML templating for the notebook 
    1313 
    1414AUTHORS: 
    15     -- Bobby Moretti 
    16     -- Timothy Clemans 
     15    -- Bobby Moretti (2007-07-18): initial version 
     16    -- Timothy Clemans and Mike Hansen (2008-10-27): major update 
    1717""" 
    1818 
    19 from jinja import Environment, FileSystemLoader 
    20 from jinja.exceptions import TemplateNotFound 
    21 from os.path import join, exists, getmtime 
    22 from sage.misc.misc import SAGE_ROOT 
     19import jinja 
     20import sage.misc.misc as misc 
    2321 
    24 env = Environment(loader=FileSystemLoader(SAGE_ROOT+"/devel/sage/sage/server/notebook/templates")) 
     22env = jinja.Environment(loader=jinja.FileSystemLoader(misc.SAGE_ROOT + '/devel/sage/sage/server/notebook/templates')) 
    2523 
    26 class PageTemplate: 
    27     def __init__(self, filename): 
    28         self.__template = env.get_template(filename) 
     24def contained_in(container): 
     25    def wrapped(env, context, value): 
     26        return value in container 
     27    return wrapped 
    2928     
    30     def __call__(self, **kwds): 
    31         return str(self.__template.render(kwds)) 
     29env.tests['contained_in'] = contained_in 
    3230 
    33 # Define variables for each template 
    34 G = globals() 
    35 templates = ['login', 'yes_no', 'registration', 'account_settings', 'account_recovery', 'user_management', 'error_message'] 
    36 for name in templates: 
    37     G[name] =  PageTemplate('%s.html'%name) 
     31default_context = {'sitename': 'Sage Notebook'} 
     32 
     33def template(filename, **context):  
     34    """ 
     35    Returns a compiled template.  
     36    """ 
     37    try: 
     38        tmpl = env.get_template(filename) 
     39    except jinja.exceptions.TemplateNotFound: 
     40        return template('template_error.html') 
     41    context.update(default_context) 
     42    return str(tmpl.render(**context))  
  • a/sage/server/notebook/templates/base.html

    old new  
    11<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> 
    22<html lang="en"> 
    33<head> 
    4     <title>{% block title %}{% endblock %} | Sage Notebook</title> 
    5         <link type="text/css" rel="stylesheet" href="/css/{% block css %}master{% endblock %}.css" media="screen" /> 
     4    <title>{% block title %}{% endblock %} | {{ sitename }}</title> 
     5    <link type="text/css" rel="stylesheet" href="/css/{% block css %}master{% endblock %}.css" media="screen" /> 
     6    {% block javascript %}{% endblock %} 
    67</head> 
    78<body> 
    89    {% block body %}{% endblock %} 
  • /dev/null

    old new  
     1{% include 'top_bar.html' %} 
     2{% set actions = True %} 
     3{% if not pub %} 
     4        <a class="boldusercontrol" href="/new_worksheet">New Worksheet</a> 
     5        <a class="boldusercontrol" href="/upload">Upload</a> 
     6{% endif %} 
     7        <span class="flush-right"> 
     8        <input id="search_worksheets" size=20 onkeypress="return search_worksheets_enter_pressed(event, '{{ typ }}');" value="{{ search }}"></input> 
     9        <button class="add_new_worksheet_menu" onClick="search_worksheets('{{ typ }}');">Search Worksheets</button> 
     10        &nbsp;&nbsp;&nbsp; 
     11        </span> 
     12        <br> 
     13        <hr class="usercontrol"> 
     14                {% if not pub %} 
     15            {% if typ == 'archive' %} 
     16                <button onClick="make_active_button();" title="Unarchive selected worksheets so it appears in the default worksheet list">Unarchive</button> 
     17            {% else %} 
     18                <button onClick="archive_button();" title="Archive selected worksheets so they do not appear in the default worksheet list">Archive</button> 
     19            {% endif %} 
     20            {% if typ != 'trash' %} 
     21                &nbsp;&nbsp;<button onClick="delete_button();" title="Move the selected worksheets to the trash">Delete</button> 
     22            {% else %} 
     23                &nbsp;&nbsp;<button onClick="make_active_button();" title="Move the selected worksheets out of the trash">Undelete</button> 
     24            {% endif %} 
     25                         
     26            &nbsp;&nbsp;<button onClick="stop_worksheets_button();" title="Stop selected worksheets">Stop</button> 
     27             
     28            <span> 
     29            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
     30            Current Folder: 
     31            &nbsp;<a class="{{ 'bold' if typ == 'active' else '' }}usercontrol" href=".">Active</a> 
     32            &nbsp;<a class="{{ 'bold' if typ == 'archive' else '' }}usercontrol" href=".?typ=archive">Archived</a> 
     33            &nbsp;<a class="{{ 'bold' if typ == 'trash' else '' }}usercontrol" href=".?typ=trash">Trash</a>&nbsp;&nbsp; 
     34            {% if typ == 'trash' %} 
     35                &nbsp;<a class="boldusercontrol" onClick="empty_trash();return false;" href="">(Empty Trash)</a> 
     36                        {% endif %} 
     37            </span> 
     38            {% endif %} 
  • /dev/null

    old new  
     1        <table width="100%%"><tr><td> 
     2        <div class="banner"> 
     3        <table width="100%%"><tr><td> 
     4        <a class="banner" href="http://www.sagemath.org"><img align="top" src="/images/sagelogo.png" alt="Sage"> Notebook</a></td><td><span class="ping" id="ping">Searching for Sage server...</span></td> 
     5        </tr><tr><td style="font-size:xx-small; text-indent:13px; color:black">Version {{ version }}</td><td></td></tr></table> 
     6        </div> 
     7        </td><td align=right> 
     8        <span class="username">{{ username }}</span> 
     9        {% if username == 'guest' %} 
     10        <span class="vbar"></span><a title="Please log in to the Sage notebook" class="usercontrol" href="/">Log in</a> 
     11        {% else %} 
     12        <span class="vbar"></span><a title="Back to your personal worksheet list" class="usercontrol" href="/home/{{ username }}">Home</a> 
     13        {% if not pub %} 
     14        <span class="vbar"></span><a title="Browse the published worksheets" class="usercontrol" href="/pub">Published</a> 
     15        <span class="vbar"></span><a title="View a log of recent computations" class="usercontrol" onClick="history_window()">Log</a> 
     16        {% else %} 
     17        <span class="vbar"></span><span class="usercontrol">Published</span> 
     18        {% endif %} 
     19        <span class="vbar"></span><a title="Documentation" class="usercontrol" onClick="help()">Help</a> 
     20        <span class="vbar"></span><a title="Change account settings including password" class="usercontrol" href="/settings">Settings</a> 
     21        <span class="vbar"></span><a title="Log out of the Sage notebook" class="usercontrol" href="/logout">Sign out</a> 
     22        {% endif %} 
     23        </td></tr> 
     24        </table> 
     25        <hr class="usercontrol"> 
  • /dev/null

    old new  
     1{% extends "base.html" %} 
     2           {% block title %}{{ worksheet_heading }}{% endblock %} 
     3           {% block css %}main{% endblock %} 
     4           {% block javascript %} 
     5           <script type="text/javascript" src="/javascript/main.js"></script> 
     6{% if not pub %} 
     7           <script type="text/javascript"> 
     8           var worksheet_filenames = {{ worksheet_filenames }};  
     9           </script> 
     10           {% endif %} 
     11           {% endblock %} 
     12           {% block body %} 
     13           {% include "list_top.html" %} 
     14                <br><br> 
     15        <table width="100%" border=0 cellspacing=0 cellpadding=0> 
     16        <tr class="greybox"><td colspan=4><div class="thinspace"></div></td></tr> 
     17        <tr  class="greybox"> 
     18 
     19        {% if not pub %} 
     20           <td>&nbsp;<input id="controlbox" onClick="set_worksheet_list_checks();" class="entry" type=checkbox></td> 
     21        {% else %} 
     22            <td>&nbsp;&nbsp;<a class="listcontrol" href=".?sort=rating">Rating</a></td> 
     23                {% endif %} 
     24 
     25        <td><a class="listcontrol" href=".?typ={{ typ }}&sort=name{{ '' if sort != 'name' or reverse else '&reverse=True' }}">{{ worksheet_heading }}</a> </td> 
     26        
     27        <td><a class="listcontrol" href=".?typ={{ typ }}&sort=owner{{ '' if sort != 'owner' or reverse else '&reverse=True' }}">Owner {{ '' if pub else ' / Collaborators' }}</a> </td> 
     28        <td><a class="listcontrol" href=".?typ={{ typ }}&{{ '' if sort != 'last_edited' or reverse else 'reverse=True' }}">Last Edited</a> </td> 
     29        </tr> 
     30        <tr class="greybox"><td colspan=4><div class="thinspace"></div></td></tr> 
     31{% if not any_worksheets %} 
     32{% if pub %} 
     33      <tr><td colspan="5" style="padding:20px;text-align:center">There are no published worksheets.</td></tr> 
     34{% elif typ == 'active' %} 
     35            <tr><td colspan="5" style="padding:20px;text-align:center">Welcome to Sage! You can 
     36<a href="/new_worksheet">create a new worksheet</a>, view <a href="/pub/">published worksheets</a>, or read the <a href="/help" target="_new">documentation</a>.</td></tr> 
     37{% endif %} 
     38{% else %} 
     39 
     40{% for worksheet in worksheets %} 
     41{% set name = worksheet.filename() %} 
     42<tr><td class="entry"> 
     43{% if pub %} 
     44&nbsp;&nbsp;&nbsp;&nbsp;<a class="worksheet_edit" href="/home/{{ name }}/rating_info">{% if worksheet.rating() < 0 %}---- {% else %} {{ worksheet.rating() }} {% endif %}</a>    
     45{% else %} 
     46<input type=checkbox unchecked id="{{ name }}"> 
     47        &nbsp;&nbsp;&nbsp;&nbsp; 
     48            <select onchange="go_option(this);" class="worksheet_edit"> 
     49            <option value="" title="File options" selected>File</option> 
     50            <option value="list_rename_worksheet('{{ name }}','{{ worksheet.name() }}');" title="Change the name of this worksheet.">Rename...</option>             
     51            <option value="list_edit_worksheet('{{ name }}');" title="Open this worksheet and edit it">Edit</option> 
     52            <option value="list_copy_worksheet('{{ name }}');" title="Copy this worksheet">Copy Worksheet</option> 
     53            <option value="list_share_worksheet('{{ name }}');" title="Share this worksheet with others">Collaborate</option> 
     54            <option value="list_publish_worksheet('{{ name }}');" title="Publish this worksheet on the internet">Publish</option> 
     55            <option value="list_revisions_of_worksheet('{{ name }}');" title="See all revisions of this worksheet">Revisions</option> 
     56            </select> 
     57        &nbsp;&nbsp;&nbsp;&nbsp; 
     58        {% endif %} 
     59        </td> 
     60{% if worksheet.is_active(username) %} 
     61<td class="worksheet_link"> 
     62   {% else %} 
     63   <td class="archived_worksheet_link"> 
     64      {% endif %} 
     65        <a title="{{ worksheet_name }}" id="name/{{ name }}" class="worksheetname" href="/home/{{ name }}">{{ worksheet.truncated_name(35) }}</a> {% if not pub and worksheet.is_published() %}(Published){% endif %} 
     66   </td> 
     67<td class="owner_collab"> 
     68    
     69   {{ worksheet.owner() }} 
     70   {% if not pub and typ != 'trash' %} 
     71   {{ worksheet.collab() }} 
     72   {% if worksheet.collab() %} 
     73   <a class="share" href="/home/{{ worksheet.filename() }}/share">Add or Delete</a> 
     74   {% else %} 
     75   <a class="share" href="/home/{{ worksheet.filename() }}/share">Share now</a> 
     76   {% endif %} 
     77       {% if worksheet.has_published_version() %} 
     78        <a href="/home/{{ worksheet.published_version().filename() }}">(published) 
     79{% endif %} 
     80   {% endif %} 
     81</td> 
     82<td><span class="lastedit">{{ worksheet.ws_time_since_last_edited() }} ago by {{ worksheet.last_to_edit() }}</span></td> 
     83</tr> 
     84<tr class="thingreybox"><td colspan=4><div class="ultrathinspace"></div></td></tr> 
     85{% endfor %} 
     86{% endif %} 
     87        </table> 
     88        {% endblock %} 
  • a/sage/server/notebook/twist.py

    old new  
    3131############################################################ 
    3232 
    3333import os, shutil, time 
    34  
     34from sage.version import version 
    3535import bz2 
    3636 
    3737from twisted.web2 import server, http, resource, channel 
     
    4141 
    4242import notebook as _notebook 
    4343 
    44 import sage.server.notebook.template as template 
     44from sage.server.notebook.template import template 
    4545 
    4646HISTORY_MAX_OUTPUT = 92*5 
    4747HISTORY_NCOLS = 90 
     
    118118# An error message 
    119119############################ 
    120120def message(msg, cont=None): 
    121     return template.error_message(msg=msg, cont=cont) 
     121    template_dict = {'msg': msg, 'cont': cont} 
     122    return template('error_message.html', **template_dict) 
    122123 
    123124############################ 
    124125# Create a Sage worksheet from a latex2html'd file 
     
    930931        if template_dict['email']: 
    931932            template_dict['email_address'] = 'None' if not notebook.user(self.username)._User__email else notebook.user(self.username)._User__email 
    932933            template_dict['email_confirmed'] = 'Not confirmed' if not notebook.user(self.username).is_email_confirmed() else 'Confirmed' 
    933         return http.Response(stream=template.account_settings(**template_dict)) 
     934        return http.Response(stream=template('account_settings.html', **template_dict)) 
    934935 
    935936######################################################## 
    936937# Set output type of a cell 
     
    13071308                    return static.File(h) 
    13081309            return NotImplementedWorksheetOp(op, self.worksheet) 
    13091310 
     1311def worksheets_by_group(user, group): 
     1312    X = notebook.get_worksheets_with_viewer(user) 
     1313    if group == "trash": 
     1314        return ('Trash', [x for x in X if x.is_trashed(user)]) 
     1315    elif group == "active": 
     1316        return ('Active Worksheets', [x for x in X if x.is_active(user)]) 
     1317    else: # typ must be archived or "all" 
     1318        return ('Archived and Active', [x for x in X if not x.is_trashed(user)]) 
     1319     
     1320def sort_worksheet_list(v, sort, reverse): 
     1321    """ 
     1322    INPUT: 
     1323        sort -- 'last_edited', 'owner', or 'name' 
     1324        reverse -- if True, reverse the order of the sort. 
     1325    """ 
     1326    f = None 
     1327    if sort == 'last_edited': 
     1328        def c(a, b): 
     1329            return -cmp(a.last_edited(), b.last_edited()) 
     1330        f = c 
     1331    elif sort == 'name': 
     1332        def c(a,b): 
     1333            return cmp((a.name().lower(), -a.last_edited()), (b.name().lower(), -b.last_edited())) 
     1334        f = c 
     1335    elif sort == 'owner': 
     1336        def c(a,b): 
     1337            return cmp((a.owner().lower(), -a.last_edited()), (b.owner().lower(), -b.last_edited())) 
     1338        f = c 
     1339    elif sort == "rating": 
     1340        def c(a,b): 
     1341            return -cmp((a.rating(), -a.last_edited()), (b.rating(), -b.last_edited())) 
     1342        f = c 
     1343    else: 
     1344        raise ValueError, "invalid sort key '%s'"%sort 
     1345    v.sort(cmp = f, reverse=reverse) 
     1346 
    13101347def render_worksheet_list(args, pub, username): 
    1311     if args.has_key('typ'): 
    1312         typ = args['typ'][0] 
     1348    template_dict = {'pub': pub, 
     1349               'typ': args['typ'][0] if 'typ' in args else 'active', 
     1350               'search': args['search'][0] if 'search' in args else None, 
     1351               'sort': args['sort'][0] if 'sort' in args else 'last_edited', 
     1352               'reverse': (args['reverse'][0] == 'True') if 'reverse' in args else False} 
     1353    typ = template_dict['typ'] 
     1354    if not pub: 
     1355        template_dict['group'], template_dict['worksheets'] = worksheets_by_group(username, template_dict['typ']) 
    13131356    else: 
    1314         typ = 'active' 
    1315     if args.has_key('search'): 
    1316         search = args['search'][0] 
    1317     else: 
    1318         search = None 
    1319     if not args.has_key('sort'): 
    1320         sort = 'last_edited' 
    1321     else: 
    1322         sort = args['sort'][0] 
    1323     if args.has_key('reverse'): 
    1324         reverse = (args['reverse'][0] == 'True') 
    1325     else: 
    1326         reverse = False 
     1357        template_dict['group'] = '' 
     1358        template_dict['worksheets'] = [x for x in notebook.all_worksheets().itervalues() if x.is_published() and not x.is_trashed(username)] 
     1359    sort_worksheet_list(template_dict['worksheets'], template_dict['sort'], template_dict['reverse']) 
     1360    template_dict['worksheet_filenames'] = [x.filename() for x in template_dict['worksheets']] 
     1361    template_dict['username'] = username 
     1362    template_dict['version'] = version 
     1363    if pub and (not username or username == tuple([])): 
     1364        template_dict['username'] = 'pub' 
     1365     
     1366    template_dict['any_worksheets'] = bool(template_dict['worksheets']) 
     1367    #k += '<td class="owner_collab">%s</td>'%html_owner_collab_view(w, username, typ) 
     1368    #k += '<td class="last_edited">%s</td>'%w.html_time_since_last_edited() 
    13271369 
    13281370    if pub: 
    1329         if username is None or username == tuple([]): 
    1330             user = 'pub' 
    1331         else: 
    1332             user = username 
    1333         s = notebook.html_worksheet_list_public( 
    1334             user, sort=sort, reverse=reverse, search=search) 
    1335     else: 
    1336         s = notebook.html_worksheet_list_for_user( 
    1337             username, typ=typ, sort=sort, reverse=reverse, search=search) 
    1338     return s 
     1371        template_dict['worksheet_heading'] = "Published Worksheets" 
     1372    elif template_dict['typ'] == "trash": 
     1373        template_dict['worksheet_heading'] = "Deleted Worksheets" 
     1374        #W = [x for x in X if x.is_trashed(user)] 
     1375    elif template_dict['typ'] == "active": 
     1376        template_dict['worksheet_heading'] = "Active Worksheets" 
     1377        #W = [x for x in X if x.is_active(user)] 
     1378    else: # typ must be archived or "all" 
     1379        template_dict['worksheet_heading'] = "Archived and Active Worksheets" 
     1380        #W = [x for x in X if not x.is_trashed(user)] 
     1381             
     1382    return template('worksheet_listing.html', **template_dict)  
    13391383 
    13401384 
    13411385class WorksheetsByUser(resource.Resource): 
     
    17121756            user.set_email_confirmation(True) 
    17131757        except KeyError: 
    17141758            return http.Response(stream=message(invalid_confirm_key, '/register')) 
    1715         success = """<h1>Hello, %s. Thank you for registering!</h1>""" % username 
     1759        success = """<h1>Email address confirmed for user %s</h1>""" % username 
    17161760        del waiting[key] 
    17171761        return http.Response(stream=message(success))  
    17181762 
     
    18881932                    missing[i] = True 
    18891933             
    18901934            if set(missing) == set([True]): 
    1891                 return http.Response(stream=template.registration(**template_dict)) 
     1935                return http.Response(stream=template('registration.html', **template_dict)) 
    18921936            elif set(missing) == set([False]): 
    18931937                for i, box in enumerate(input_boxes): 
    18941938                    filled_in[box] = request.args[box][0] 
     
    19141958         
    19151959        if template_dict and set(template_dict) != set(['email']): 
    19161960            errors_found() 
    1917             return http.Response(stream=template.registration(**template_dict)) 
     1961            return http.Response(stream=template('registration.html', **template_dict)) 
    19181962        else: 
    19191963            try: 
    19201964                e = filled_in['email'] if notebook.conf()['email'] else '' 
     
    19231967            except ValueError: 
    19241968                template_dict['username_taken'] = True 
    19251969                errors_found() 
    1926                 return http.Response(stream=template.registration(**template_dict)) 
     1970                return http.Response(stream=template('registration.html', **template_dict)) 
    19271971             
    19281972            if notebook.conf()['email']: 
    19291973                destaddr = filled_in['email'] 
     
    19441988                except ValueError: 
    19451989                    pass 
    19461990             
    1947             return http.Response(stream=template.login(accounts=notebook.get_accounts(), 
    1948                                                             default_user=notebook.default_user(), welcome=filled_in['username'], 
    1949                                                             recovery=notebook.conf()['email'])) 
     1991            template_dict = {'accounts': notebook.get_accounts(), 
     1992                             'default_user': notebook.default_user(), 
     1993                             'welcome': filled_in['username'], 
     1994                             'recovery': notebook.conf()['email']} 
     1995            return http.Response(stream=template('login.html', **template_dict)) 
    19501996     
    19511997class ForgotPassPage(resource.Resource): 
    19521998         
     
    19922038             
    19932039            return http.Response(stream=message("A new password has been sent to your e-mail address.", '/')) 
    19942040        else: 
    1995             s = template.account_recovery(
     2041            s = template('account_recovery.html'
    19962042        return http.Response(stream=s) 
    19972043 
    19982044class ListOfUsers(resource.Resource): 
     
    20032049            if user_type(self.username) != 'admin': 
    20042050                s = message('You must an admin to manage other users.') 
    20052051            else: 
    2006                 s = template.user_management(users=notebook.valid_login_names()
     2052                s = template('user_management.html', {'users':notebook.valid_login_names()}
    20072053            return http.Response(stream = s) 
    20082054 
    20092055class InvalidPage(resource.Resource): 
     
    20432089        self.username = username if username else 'guest' 
    20442090 
    20452091    def render(self, ctx): 
    2046         return http.Response(stream = template.login(accounts = notebook.get_accounts(), default_user = notebook.default_user(), recovery=notebook.conf()['email'])) 
    2047  
     2092        template_dict = {'accounts': notebook.get_accounts(), 
     2093                         'default_user': notebook.default_user(), 
     2094                         'recovery': notebook.conf()['email']} 
     2095        return http.Response(stream=template('login.html', **template_dict)) 
     2096     
    20482097    def userchildFactory(self, request, name): 
    20492098        return InvalidPage(msg = "unauthorized request", username = self.username) 
    20502099 
     
    20552104 
    20562105class LoginResourceClass(resource.Resource): 
    20572106    def render(self, ctx): 
    2058         return http.Response(stream =  template.login(accounts=notebook.get_accounts(), default_user=notebook.default_user(), recovery=notebook.conf()['email'])) 
     2107        template_dict = {'accounts': notebook.get_accounts(), 
     2108                         'default_user': notebook.default_user(), 
     2109                         'recovery': notebook.conf()['email']} 
     2110        return http.Response(stream=template('login.html', **template_dict)) 
    20592111     
    20602112    def childFactory(self, request, name): 
    20612113        return LoginResource 
     
    20902142    #child_login = LoginResource 
    20912143     
    20922144    def render(self, ctx): 
    2093         response = http.Response(stream =  template.login(accounts=notebook.get_accounts(), default_user=notebook.default_user(), recovery=notebook.conf()['email'])) 
     2145        template_dict = {'accounts': notebook.get_accounts(), 
     2146                         'default_user': notebook.default_user(), 
     2147                         'recovery': notebook.conf()['email']} 
     2148        response = http.Response(stream=template('login.html', **template_dict)) 
    20942149        response.headers.setHeader("set-cookie", [http_headers.Cookie('cookie_test', 'cookie_test')]) 
    20952150        return response 
    20962151 
     
    21052160        # worksheets and ratings, this gives no new information way. 
    21062161        # If published pages were disabled, then this should be disabled too. 
    21072162        if self.problem == 'username': 
    2108             return http.Response(stream = template.login(accounts=notebook.get_accounts(), default_user='', username_error=True, recovery=notebook.conf()['email'])) 
     2163            template_dict = {'accounts': notebook.get_accounts(), 
     2164                             'default_user': notebook.default_user(), 
     2165                             'username_error': True, 
     2166                             'recovery': notebook.conf()['email']} 
     2167            return http.Response(stream=template('login.html', **template_dict)) 
    21092168        elif self.problem == 'password': 
    2110             return http.Response(stream = template.login(accounts=notebook.get_accounts(), default_user=self.username, password_error=True, recovery=notebook.conf()['email'])) 
     2169            template_dict = {'accounts': notebook.get_accounts(), 
     2170                             'default_user': self.username, 
     2171                             'password_error': True, 
     2172                             'recovery': notebook.conf()['email']} 
     2173            return http.Response(stream=template('login.html', **template_dict)) 
    21112174        else: 
    21122175            return http.Response(stream = message("Please enable cookies and try again.")) 
    21132176 
  • a/sage/server/notebook/worksheet.py

    old new  
    387387            return self.__collaborators 
    388388        except AttributeError: 
    389389            self.__collaborators = [] 
    390             return self.__collaborators             
     390            return self.__collaborators 
     391         
     392    def collab(self): 
     393        collab = [x for x in self.collaborators() if x != self.owner()] 
     394        collaborators = ', '.join([x for x in collab]) 
     395        if len(collaborators) > 21: 
     396            collaborators = collaborators[:21] + '...' 
     397        return collaborators 
    391398 
    392399    def set_collaborators(self, v): 
    393400        """ 
     
    21652172                return True, user 
    21662173        False 
    21672174         
     2175    def ws_time_since_last_edited(self): 
     2176        t = self.time_since_last_edited() 
     2177        tm = convert_seconds_to_meaningful_time_span(t) 
     2178        return tm 
    21682179 
    21692180    def html_time_since_last_edited(self): 
    2170         t = self.time_since_last_edited() 
    2171         tm = convert_seconds_to_meaningful_time_span(t) 
    2172         who = ' by %s'%self.last_to_edit() 
    2173         return '<span class="lastedit">%s ago%s</span>'%(tm, who) 
     2181        tm, who = time_since_last_edited 
     2182        return '<span class="lastedit">%s ago%s</span>'%(tm, self.last_to_edit) 
    21742183 
    21752184    def html_time_last_edited(self): 
    21762185        tm = convert_time_to_string(self.last_edited())