Ticket #3950: trac_3950-folded.patch

File trac_3950-folded.patch, 41.1 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          
    9897    def _migrate_worksheets(self): 
    9998        v = [] 
    10099        for key, W in self.__worksheets.iteritems(): 
     
    12601259        s += '\n</body>\n' 
    12611260        return s 
    12621261 
     1262     
    12631263 
    1264     def html_worksheet_list_public(self, username,  
    1265                                   sort='last_edited', reverse=False, search=None): 
     1264    def worksheet_list_for_public(self, username, sort='last_edited', reverse=False, search=None): 
    12661265        W = [x for x in self.__worksheets.itervalues() if x.is_published() and not x.is_trashed(user)] 
    12671266 
    12681267        if search: 
    12691268            W = [x for x in W if x.satisfies_search(search)] 
    12701269 
    12711270        sort_worksheet_list(W, sort, reverse)  # changed W in place 
    1272         worksheet_filenames = [x.filename() for x in W] 
    1273          
    1274         top  = self.html_worksheet_list_top(username, False, pub=True, search=search) 
    1275         list = self.html_worksheet_list(W, username, False, sort=sort, reverse=reverse, typ="all", pub=True) 
    1276          
    1277         s = """ 
    1278         <html> 
    1279            <link rel=stylesheet href="/css/main.css"> 
    1280            <title>Sage: Published Worksheets</title> 
    1281            %s 
    1282         <body> 
    1283         %s 
    1284         %s 
    1285         </body> 
    1286         </html> 
    1287         """%(self.list_window_javascript(worksheet_filenames), top, list) 
     1271        return W 
    12881272 
    1289         return s 
    1290  
    1291     def html_worksheet_list_for_user(self, user, 
    1292                                      typ="active", 
    1293                                      sort='last_edited', 
    1294                                      reverse=False, 
    1295                                      search=None): 
    1296  
     1273    def worksheet_list_for_user(self, user, typ="active", sort='last_edited', reverse=False, search=None): 
    12971274        X = self.get_worksheets_with_viewer(user) 
    12981275        if typ == "trash": 
    1299             worksheet_heading = "Trash" 
    13001276            W = [x for x in X if x.is_trashed(user)] 
    13011277        elif typ == "active": 
    1302             worksheet_heading = "Active Worksheets" 
    13031278            W = [x for x in X if x.is_active(user)] 
    13041279        else: # typ must be archived or "all" 
    1305             worksheet_heading = "Archived and Active" 
    13061280            W = [x for x in X if not x.is_trashed(user)] 
    13071281        if search: 
    13081282            W = [x for x in W if x.satisfies_search(search)] 
    1309  
    13101283        sort_worksheet_list(W, sort, reverse)  # changed W in place 
    1311          
    1312         top = self.html_worksheet_list_top(user, typ=typ, search=search) 
    1313         list = self.html_worksheet_list(W, user, worksheet_heading, sort=sort, reverse=reverse, typ=typ) 
    1314         worksheet_filenames = [x.filename() for x in W] 
    1315          
    1316         s = """ 
    1317         <html> 
    1318            <link rel=stylesheet href="/css/main.css"> 
    1319            <title>Sage: Worksheet List</title> 
    1320            %s 
    1321         <body> 
    1322         %s 
    1323         %s 
    1324         </body> 
    1325         </html> 
    1326         """%(self.list_window_javascript(worksheet_filenames), top, list) 
    1327  
    1328         return s 
     1284        return W 
    13291285 
    13301286    def html_topbar(self, user, pub=False): 
    13311287        s = '' 
     
    13361292        else: 
    13371293            entries.append(('/home/%s'%user, 'Home', 'Back to your personal worksheet list')) 
    13381294            entries.append(('/pub', 'Published', 'Browse the published worksheets')) 
    1339             #entries.append(('/settings', 'Settings', 'Change user settings'))   # TODO -- settings 
    13401295            entries.append(('help()', 'Help', 'Documentation')) 
    13411296 
    13421297        ## TODO -- settings 
     
    13981353        """%ver 
    13991354        return s 
    14001355 
    1401     def html_search(self, search, typ): 
    1402         s = """ 
    1403         <span class="flush-right"> 
    1404         <input id="search_worksheets" size=20 onkeypress="return search_worksheets_enter_pressed(event, '%s');" value="%s"></input> 
    1405         <button class="add_new_worksheet_menu" onClick="search_worksheets('%s');">Search Worksheets</button> 
    1406         &nbsp;&nbsp;&nbsp; 
    1407         </span> 
    1408         """%(typ, '' if search is None else search.replace('"',"'"), typ) 
    1409         return s 
    1410  
    1411     def html_new_or_upload(self): 
    1412         s = """ 
    1413         <a class="boldusercontrol" href="/new_worksheet">New Worksheet</a>\n 
    1414         <a class="boldusercontrol" href="/upload">Upload</a>\n 
    1415         """ 
    1416         return s 
    14171356 
    14181357    def html_worksheet_actions(self, user, typ): 
    1419 ## 
    1420 ##          <option onClick="save_worksheets('sws');" title="Save the selected worksheets to disk">Save ...</option> 
    1421 ##          <option onClick="save_worksheets('html');" title="Save the selected worksheets as a single HTML web page">Save as HTML (zipped) ... </option> 
    1422 ##          <option onClick="save_worksheets('latex');" title="Save the selected worksheets as a single LaTeX document">Save as LaTeX (zipped) ... </option> 
    1423 ##          <option onClick="save_worksheets('pdf');" title="Save the selected worksheets as a single PDF document">Save as PDF...</option> 
    1424 ##          <option onClick="save_worksheets('txt');" title="Save the selected worksheets to a single text file">Save as Text...</option> 
    1425 ##         s = """ 
    1426 ##          <select class="worksheet_list"> 
    1427 ##          <option onClick="archive_button();" title="Archive selected worksheets so they do not appear in the default worksheet list">Archive</option> 
    1428 ##          <option onClick="make_active_button();" title="Unarchive this worksheet so it appears in the default worksheet list">Unarchive</option> 
    1429 ##          <option onClick="uncollaborate_me();" title="Remove myself from collaboration or viewing of this worksheet">Un-collaborate me</option>                            
    1430 ##         </select> 
    1431 ##         """ 
    14321358        s = '' 
    14331359         
    14341360        if not self.user_is_guest(user): 
     
    14571383            s += '</span>' 
    14581384        return s 
    14591385         
    1460  
    1461     def html_worksheet_list(self, worksheets, user, worksheet_heading, sort, reverse, typ, pub=False): 
    1462         s = '' 
    1463  
    1464         s = '<br><br>' 
    1465         s += '<table width="100%" border=0 cellspacing=0 cellpadding=0>' 
    1466         s += '<tr class="greybox"><td colspan=4><div class="thinspace"></div></td></tr>' 
    1467         s += '<tr  class="greybox">' 
    1468  
    1469         if not pub: 
    1470             s += '<td>&nbsp;<input id="controlbox" onClick="set_worksheet_list_checks();" class="entry" type=checkbox></td>' 
    1471         else: 
    1472             s += '<td>&nbsp;&nbsp;<a class="listcontrol" href=".?sort=rating">Rating</a></td>' 
    1473             worksheet_heading = "Published Worksheets" 
    1474  
    1475         s += '<td><a class="listcontrol" href=".?typ=%s&sort=name%s">%s</a> </td>'%(typ, 
    1476             '' if sort != 'name' or reverse else '&reverse=True', worksheet_heading) 
    1477         s += '<td><a class="listcontrol" href=".?typ=%s&sort=owner%s">Owner%s</a> </td>'%(typ, 
    1478             '' if sort != 'owner' or reverse else '&reverse=True', 
    1479             '' if pub else ' / Collaborators') 
    1480         s += '<td><a class="listcontrol" href=".?typ=%s&%s">Last Edited</a> </td>'%(typ, 
    1481             '' if sort != 'last_edited' or reverse else 'reverse=True') 
    1482         s += '</tr>' 
    1483         s += '<tr class="greybox"><td colspan=4><div class="thinspace"></div></td></tr>'         
    1484  
    1485         v = [] 
    1486         for w in worksheets: 
    1487             k = '<tr>' 
    1488             k += '<td class="entry">%s</td>'%self.html_check_col(w, user, pub) 
    1489             name = self.html_worksheet_link(w, pub) 
    1490             if w.compute_process_has_been_started(): 
    1491                 name = '(running) %s'%name 
    1492             if w.is_active(user): 
    1493                 k += '<td class="worksheet_link">%s</td>'%name 
    1494             else: 
    1495                 k += '<td class="archived_worksheet_link">%s</td>'%name 
    1496             k += '<td class="owner_collab">%s</td>'%self.html_owner_collab_view(w, user, typ) 
    1497             k += '<td class="last_edited">%s</td>'%w.html_time_since_last_edited() 
    1498             k += '</tr>' 
    1499             k += '<tr class="thingreybox"><td colspan=4><div class="ultrathinspace"></div></td></tr>'         
    1500             v.append(k) 
    1501  
    1502         s += ''.join(v) 
    1503         if not v and typ != 'trash' and not pub: 
    1504             s += """<tr><td colspan="5" style="padding:20px;text-align:center">Welcome to Sage! You can 
    1505 <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>""" 
    1506         s += '</table>' 
    1507  
    1508         return s 
    1509  
    1510     def html_check_col(self, worksheet, user, pub): 
    1511         def doc_options(name): 
    1512             if pub: 
    1513                 rating = worksheet.rating() 
    1514                 if rating == -1: 
    1515                     r = "----" 
    1516                 else: 
    1517                     r = "%.1f"%rating 
    1518                 if not self.user_is_guest(user) and not worksheet.is_rater(user): 
    1519                     r = '<i>%s</i>'%r 
    1520                 if r != '----': 
    1521                     r = '<a class="worksheet_edit" href="/home/%s/rating_info">%s</a>'%(name,r)                     
    1522                 return r 
    1523                  
    1524             return """ 
    1525             <select onchange="go_option(this);" class="worksheet_edit"> 
    1526             <option value="" title="File options" selected>File</option> 
    1527             <option value="list_rename_worksheet('%s','%s');" title="Change the name of this worksheet.">Rename...</option>             
    1528             <option value="list_edit_worksheet('%s');" title="Open this worksheet and edit it">Edit</option> 
    1529             <option value="list_copy_worksheet('%s');" title="Copy this worksheet">Copy Worksheet</option> 
    1530             <option value="list_share_worksheet('%s');" title="Share this worksheet with others">Collaborate</option> 
    1531             <option value="list_publish_worksheet('%s');" title="Publish this worksheet on the internet">Publish</option> 
    1532             <option value="list_revisions_of_worksheet('%s');" title="See all revisions of this worksheet">Revisions</option> 
    1533             </select> 
    1534             """%(name, worksheet.name(), name, name,name,name,name) 
    1535          
    1536         k = '' 
    1537         if not pub: 
    1538             k += '<input type=checkbox unchecked id="%s">'%worksheet.filename() 
    1539         k += '&nbsp;'*4 
    1540         k += doc_options(worksheet.filename()) 
    1541         k += '&nbsp;'*4 
    1542         return k 
    1543  
    1544     def html_worksheet_link(self, worksheet, pub): 
    1545         name = worksheet.truncated_name(35) 
    1546         if not pub and worksheet.is_published(): 
    1547             name += ' (published)' 
    1548         return '<a title="%s" id="name/%s" class="worksheetname" href="/home/%s">%s</a>\n'%( 
    1549             worksheet.name(), worksheet.filename(), worksheet.filename(), name) 
    1550  
    1551     def html_owner_collab_view(self, worksheet, user, typ): 
    1552         v = [] 
    1553          
    1554         owner = worksheet.owner() 
    1555         pub = False 
    1556         if owner == 'pub': 
    1557             pub = True 
    1558             owner = worksheet.worksheet_that_was_published().owner() 
    1559  
    1560         v.append(owner) 
    1561              
    1562         collab = [x for x in worksheet.collaborators() if not x == owner] 
    1563         share = '' 
    1564  
    1565         if not pub and typ != 'trash' or self.user(user).is_admin(): 
    1566             if len(collab) == 0: 
    1567                 share = '<a class="share" href="/home/%s/share">Share now</a>'%(worksheet.filename()) 
    1568             else: 
    1569                 collaborators = ', '.join([x for x in collab]) 
    1570                 if len(collaborators) > 21: 
    1571                     collaborators = collaborators[:21] + '...' 
    1572                 v.append(collaborators) 
    1573                 share = '<a class="share" href="/home/%s/share">Add or Delete</a>'%(worksheet.filename()) 
    1574         if not (self.user(user).is_admin() or owner == user): 
    1575             share = '' 
    1576              
    1577         if worksheet.has_published_version(): 
    1578             pub_ver = worksheet.published_version().filename() 
    1579             share += ' <a href="/home/%s">(published)'%pub_ver 
    1580  
    1581         viewers = worksheet.viewers() 
    1582         if len(viewers) > 0: 
    1583             viewers = '<i>' + ', '.join(viewers) + '</i>' 
    1584             v.append(viewers) 
    1585  
    1586         s = ' / '.join([str(w) for w in v]) + ' ' + share 
    1587  
    1588         return s 
    1589  
    15901386         
    15911387    ########################################################## 
    15921388    # Revision history for a worksheet 
     
    26122408def sort_worksheet_list(v, sort, reverse): 
    26132409    """ 
    26142410    INPUT: 
    2615         sort -- 'last_edited', 'owner', or 'name' 
     2411        sort -- 'last_edited', 'owner', 'rating', or 'name' 
    26162412        reverse -- if True, reverse the order of the sort. 
    26172413    """ 
    26182414    f = None 
     
    26352431    else: 
    26362432        raise ValueError, "invalid sort key '%s'"%sort 
    26372433    v.sort(cmp = f, reverse=reverse) 
    2638  
    2639  
    2640  
  • a/sage/server/notebook/template.py

    old new  
    1 """nodoctest 
    21""" 
     2HTML templating for the notebook 
    33 
     4AUTHORS: 
     5    -- Bobby Moretti (2007-07-18): initial version 
     6    -- Timothy Clemans and Mike Hansen (2008-10-27): major update 
     7 
     8""" 
    49############################################################################# 
    510#       Copyright (C) 2007 William Stein <wstein@gmail.com> 
    611#  Distributed under the terms of the GNU General Public License (GPL) 
    712#  The full text of the GPL is available at: 
    813#                  http://www.gnu.org/licenses/ 
    914############################################################################# 
     15import jinja 
     16import sage.misc.misc 
     17from sage.version import version 
    1018 
    11 """ 
    12 HTML templating for the notebook 
     19TEMPLATE_PATH = sage.misc.misc.SAGE_ROOT + '/devel/sage/sage/server/notebook/templates' 
     20env = jinja.Environment(loader=jinja.FileSystemLoader(TEMPLATE_PATH)) 
    1321 
    14 AUTHORS: 
    15     -- Bobby Moretti 
    16     -- Timothy Clemans 
    17 """ 
     22def contained_in(container): 
     23    """ 
     24    Returns a function which takes in an environment, context, and value 
     25    and returns True if that value is in the container and False 
     26    otherwise.  This is registered and used as a test in the templates. 
    1827 
    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 
     28    EXAMPLES: 
     29        sage: from sage.server.notebook.template import contained_in 
     30        sage: f = contained_in([1,2,3]) 
     31        sage: f(None, None, 2) 
     32        True 
     33        sage: f(None, None, 4) 
     34        False 
     35    """ 
     36    def wrapped(env, context, value): 
     37        return value in container 
     38    return wrapped 
     39     
     40env.tests['contained_in'] = contained_in 
    2341 
    24 env = Environment(loader=FileSystemLoader(SAGE_ROOT+"/devel/sage/sage/server/notebook/templates")) 
     42#A dictionary containing the default context 
     43#The values in this dictionary will be updated 
     44#by the  
     45default_context = {'sitename': 'Sage Notebook', 
     46                   'sage_version': version} 
    2547 
    26 class PageTemplate: 
    27     def __init__(self, filename): 
    28         self.__template = env.get_template(filename) 
    29      
    30     def __call__(self, **kwds): 
    31         return str(self.__template.render(kwds)) 
     48def template(filename, **user_context):  
     49    """ 
     50    Returns a rendered template as a string. 
    3251 
    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) 
     52    INPUT: 
     53        filename -- the filename of the template relative to 
     54                    $SAGE_ROOT/devel/sage/sage/server/notebook/templates 
     55 
     56    EXAMPLES: 
     57        sage: from sage.server.notebook.template import template 
     58        sage: s = template('yes_no.html'); type(s) 
     59        <type 'str'> 
     60        sage: 'Yes' in s 
     61        True 
     62         
     63    """ 
     64    try: 
     65        tmpl = env.get_template(filename) 
     66    except jinja.exceptions.TemplateNotFound: 
     67        return template('template_error.html') 
     68    context = dict(default_context) 
     69    context.update(user_context) 
     70    return str(tmpl.render(**context))  
  • /dev/null

    old new  
     1<div class="banner"> 
     2  <table width="100%%"> 
     3    <tr> 
     4      <td> 
     5        <a class="banner" href="http://www.sagemath.org"> 
     6        <img align="top" src="/images/sagelogo.png" alt="Sage">Notebook</a> 
     7      </td> 
     8      <td> 
     9        <span class="ping" id="ping">Searching for Sage server...</span> 
     10      </td> 
     11    </tr> 
     12    <tr> 
     13      <td style="font-size:xx-small; text-indent:13px;color:black">Version {{ sage_version }}</td> 
     14      <td></td> 
     15    </tr> 
     16  </table> 
     17</div> 
  • 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 
     3<a class="boldusercontrol" href="/new_worksheet">New Worksheet</a> 
     4<a class="boldusercontrol" href="/upload">Upload</a> 
     5 
     6{% include 'search.html' %} 
     7 
     8<br> 
     9<hr class="usercontrol"> 
     10 
     11 
     12{% if typ == 'archive' %} 
     13<button onClick="make_active_button();" title="Unarchive selected worksheets so it appears in the default worksheet list">Unarchive</button> 
     14{% else %} 
     15<button onClick="archive_button();" title="Archive selected worksheets so they do not appear in the default worksheet list">Archive</button> 
     16{% endif %} 
     17 
     18 
     19{% if typ != 'trash' %} 
     20<button onClick="delete_button();" title="Move the selected worksheets to the trash">Delete</button> 
     21{% else %} 
     22<button onClick="make_active_button();" title="Move the selected worksheets out of the trash">Undelete</button> 
     23{% endif %} 
     24                         
     25<button onClick="stop_worksheets_button();" title="Stop selected worksheets">Stop</button> 
     26 
     27<span style="padding-left:100px;"> 
     28    Current Folder: 
     29    <a class="{{ 'bold' if typ == 'active' else '' }}usercontrol" href=".">Active</a> 
     30    <a class="{{ 'bold' if typ == 'archive' else '' }}usercontrol" href=".?typ=archive">Archived</a> 
     31    <a class="{{ 'bold' if typ == 'trash' else '' }}usercontrol" href=".?typ=trash">Trash</a> 
     32 
     33    {% if typ == 'trash' %} 
     34      <a class="boldusercontrol" onClick="empty_trash();return false;" href="">(Empty Trash)</a> 
     35    {% endif %} 
     36</span> 
  • /dev/null

    old new  
     1{% include 'top_bar.html' %} 
     2 
     3{% include 'search.html' %} 
     4 
     5<br> 
     6<hr class="usercontrol"> 
  • /dev/null

    old new  
     1<span class="flush-right"> 
     2<input id="search_worksheets" size=20 onkeypress="return search_worksheets_enter_pressed(event, '{{ typ }}');" value="{{ search }}"></input> 
     3<button class="add_new_worksheet_menu" onClick="search_worksheets('{{ typ }}');">Search Worksheets</button> 
     4</span> 
  • /dev/null

    old new  
     1<table width="100%%"> 
     2  <tr> 
     3    <td> 
     4      {% include 'banner.html' %} 
     5    </td> 
     6    <td align=right> 
     7      <span class="username">{{ username }}</span> 
     8 
     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 pub %} 
     14          <span class="vbar"></span><span class="usercontrol">Published</span> 
     15        {% else %} 
     16          <span class="vbar"></span><a title="Browse the published worksheets" class="usercontrol" href="/pub">Published</a> 
     17          <span class="vbar"></span><a title="View a log of recent computations" class="usercontrol" onClick="history_window()">Log</a> 
     18        {% endif %} 
     19 
     20        <span class="vbar"></span><a title="Documentation" class="usercontrol" onClick="help()">Help</a> 
     21        <span class="vbar"></span><a title="Change account settings including password" class="usercontrol" href="/settings">Settings</a> 
     22        <span class="vbar"></span><a title="Log out of the Sage notebook" class="usercontrol" href="/logout">Sign out</a> 
     23      {% endif %} 
     24    </td> 
     25  </tr> 
     26</table> 
     27<hr class="usercontrol"> 
  • /dev/null

    old new  
     1{% extends "base.html" %} 
     2 
     3{% if pub %} 
     4  {% set worksheet_heading='Published Worksheets' %} 
     5{% elif typ == 'trash' %} 
     6  {% set worksheet_heading='Deleted Worksheets' %} 
     7{% elif typ == 'active' %} 
     8  {% set worksheet_heading='Active Worksheets' %} 
     9{% else %} 
     10  {% set worksheet_heading='Archived and Active Worksheets' %} 
     11{% endif %}   
     12 
     13 
     14{% block title %} 
     15{{ worksheet_heading }} 
     16{% endblock %} 
     17 
     18{% block css %}main{% endblock %} 
     19 
     20{% block javascript %} 
     21  <script type="text/javascript" src="/javascript/main.js"></script> 
     22  {% if not pub %} 
     23    <script type="text/javascript"> 
     24    var worksheet_filenames = {{ worksheet_filenames }};  
     25    </script> 
     26  {% endif %} 
     27{% endblock %} 
     28 
     29{% block body %} 
     30 
     31{% if pub %} 
     32  {% include "list_top_public.html" %} 
     33{% else %} 
     34  {% include "list_top.html" %} 
     35{% endif %} 
     36 
     37<br><br> 
     38 
     39<table width="100%" border=0 cellspacing=0 cellpadding=0> 
     40  <tr class="greybox"><td colspan=4><div class="thinspace"></div></td></tr> 
     41  <tr class="greybox"> 
     42    {% if not pub %} 
     43    <td><input id="controlbox" onClick="set_worksheet_list_checks();" class="entry" type=checkbox></td> 
     44    {% else %} 
     45    <td><a class="listcontrol" href=".?sort=rating">Rating</a></td> 
     46    {% endif %} 
     47 
     48    <td> 
     49      <a class="listcontrol" href=".?typ={{ typ }}&sort=name{{ '' if sort != 'name' or reverse else '&reverse=True' }}"> 
     50      {{ worksheet_heading }} 
     51      </a> 
     52    </td> 
     53        
     54    <td> 
     55      <a class="listcontrol" href=".?typ={{ typ }}&sort=owner{{ '' if sort != 'owner' or reverse else '&reverse=True' }}"> 
     56      Owner {{ '' if pub else ' / Collaborators' }} 
     57      </a> 
     58    </td> 
     59 
     60    <td> 
     61      <a class="listcontrol" href=".?typ={{ typ }}&{{ '' if sort != 'last_edited' or reverse else 'reverse=True' }}"> 
     62      Last Edited 
     63      </a> 
     64    </td> 
     65  </tr> 
     66 
     67  <tr class="greybox"><td colspan=4><div class="thinspace"></div></td></tr> 
     68 
     69  {% if not worksheets %} 
     70    {% if pub %} 
     71    <tr> 
     72      <td colspan="5" style="padding:20px;text-align:center"> 
     73        There are no published worksheets. 
     74      </td> 
     75    </tr> 
     76    {% elif typ == 'active' %} 
     77    <tr> 
     78      <td colspan="5" style="padding:20px;text-align:center"> 
     79        Welcome to Sage! You can <a href="/new_worksheet">create a new worksheet</a>, 
     80        view <a href="/pub/">published worksheets</a>, or read the 
     81        <a href="/help" target="_new">documentation</a>. 
     82      </td> 
     83    </tr> 
     84    {% endif %} 
     85  {% else %} 
     86 
     87    {% for worksheet in worksheets %} 
     88    {% set name = worksheet.filename() %} 
     89    <tr> 
     90      <td class="entry"> 
     91        {% if pub %} 
     92         
     93        <a class="worksheet_edit" href="/home/{{ name }}/rating_info"> 
     94        {% if worksheet.rating() < 0 %} 
     95        ---- 
     96        {% else %} 
     97        {{ worksheet.rating() }} 
     98        {% endif %} 
     99        </a> 
     100         
     101        {% else %} 
     102         
     103        <input type=checkbox unchecked id="{{ name }}"> 
     104        <select onchange="go_option(this);" class="worksheet_edit"> 
     105          <option value="" title="File options" selected>File</option> 
     106          <option value="list_rename_worksheet('{{ name }}','{{ worksheet.name() }}');" title="Change the name of this worksheet."> 
     107            Rename... 
     108          </option>             
     109          <option value="list_edit_worksheet('{{ name }}');" title="Open this worksheet and edit it">Edit</option> 
     110          <option value="list_copy_worksheet('{{ name }}');" title="Copy this worksheet">Copy Worksheet</option> 
     111          <option value="list_share_worksheet('{{ name }}');" title="Share this worksheet with others">Collaborate</option> 
     112          <option value="list_publish_worksheet('{{ name }}');" title="Publish this worksheet on the internet">Publish</option> 
     113          <option value="list_revisions_of_worksheet('{{ name }}');" title="See all revisions of this worksheet">Revisions</option> 
     114        </select> 
     115         
     116        {% endif %} 
     117      </td> 
     118 
     119      {% if worksheet.is_active(username) %} 
     120      <td class="worksheet_link"> 
     121      {% else %} 
     122      <td class="archived_worksheet_link"> 
     123      {% endif %} 
     124        <a title="{{ worksheet_name }}" id="name/{{ name }}" class="worksheetname" href="/home/{{ name }}"> 
     125        {% if worksheet.compute_process_has_been_started() %}(running) {% endif %} 
     126        {{ worksheet.truncated_name(35) }} 
     127        </a> 
     128         
     129        {% if not pub and worksheet.is_published() %}(Published){% endif %} 
     130      </td> 
     131      <td class="owner_collab"> 
     132        {{ worksheet.owner() }} 
     133         
     134        {% if not pub and typ != 'trash' %} 
     135 
     136        {% set shared = False %} 
     137 
     138        {% if worksheet.collaborator_names() %} 
     139          / {{ worksheet.collaborator_names(5) }} 
     140          {% set shared = True %} 
     141        {% endif %} 
     142 
     143        {% if worksheet.viewer_names() %} 
     144          / {{ worksheet.viewer_names(5) }} 
     145          {% set shared = True %} 
     146        {% endif %} 
     147 
     148        {% if (worksheet.owner() != username) or username == 'admin' %} 
     149          {% set shared = False %} 
     150        {% endif %} 
     151         
     152        {% if shared %} 
     153        <a class="share" href="/home/{{ worksheet.filename() }}/share">Add or Delete</a> 
     154        {% else %} 
     155        <a class="share" href="/home/{{ worksheet.filename() }}/share">Share now</a> 
     156        {% endif %} 
     157 
     158        {% if worksheet.has_published_version() %} 
     159        <a href="/home/{{ worksheet.published_version().filename() }}"> 
     160        (published) 
     161        </a> 
     162        {% endif %} 
     163         
     164        {% endif %} 
     165      </td> 
     166      <td> 
     167        {{ worksheet.html_time_since_last_edited() }} 
     168      </td> 
     169    </tr> 
     170     
     171    <tr class="thingreybox"><td colspan=4><div class="ultrathinspace"></div></td></tr> 
     172    {% endfor %} 
     173  {% endif %} 
     174  </table> 
     175{% 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 
     
    11641165class Worksheet_rating_info(WorksheetResource, resource.Resource): 
    11651166    def render(self, ctx): 
    11661167        s = self.worksheet.html_ratings_info() 
    1167         return http.Response(stream=message(""" 
     1168        return http.Response(stream=message(''' 
    11681169        <h2 align=center>Ratings for %s</h2> 
    11691170        <h3 align=center><a href='/home/%s'>Go to the worksheet.</a> 
    11701171        <br><br> 
     
    11731174        %s 
    11741175        </table> 
    11751176        <br><br> 
    1176         """%(self.worksheet.name(), self.worksheet.filename(), s))) 
     1177        '''%(self.worksheet.name(), self.worksheet.filename(), s))) 
    11771178         
    11781179     
    11791180class Worksheet_rate(WorksheetResource, resource.Resource): 
     
    13071308                    return static.File(h) 
    13081309            return NotImplementedWorksheetOp(op, self.worksheet) 
    13091310 
     1311     
    13101312def render_worksheet_list(args, pub, username): 
    1311     if args.has_key('typ'): 
    1312         typ = args['typ'][0] 
     1313    """ 
     1314    Returns a rendered worksheet listing. 
     1315 
     1316    INPUT: 
     1317       args -- ctx.args where ctx is the dict passed into a 
     1318               resource's render method 
     1319       pub -- boolean, True if this is a listing of public 
     1320              worksheets 
     1321       username -- the user whose worksheets we are listing 
     1322 
     1323    OUTPUT: 
     1324       a string 
     1325    """ 
     1326    from sage.server.notebook.notebook import sort_worksheet_list 
     1327    typ = args['typ'][0] if 'typ' in args else 'active' 
     1328    search = args['search'][0] if 'search' in args else None 
     1329    sort = args['sort'][0] if 'sort' in args else 'last_edited' 
     1330    reverse = (args['reverse'][0] == 'True') if 'reverse' in args else False 
     1331     
     1332    if not pub: 
     1333        worksheets = notebook.worksheet_list_for_user(username, typ=typ, sort=sort, 
     1334                                                      search=search, reverse=reverse) 
     1335                                                   
    13131336    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 
    1327  
    1328     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 
     1337        worksheets = notebook.worksheet_list_for_public(username, sort=sort, 
     1338                                                        search=search, reverse=reverse) 
     1339         
     1340    worksheet_filenames = [x.filename() for x in worksheets] 
     1341                                                     
     1342    if pub and (not username or username == tuple([])): 
     1343        username = 'pub' 
     1344             
     1345    return template('worksheet_listing.html', **locals())  
    13391346 
    13401347 
    13411348class WorksheetsByUser(resource.Resource): 
     
    17121719            user.set_email_confirmation(True) 
    17131720        except KeyError: 
    17141721            return http.Response(stream=message(invalid_confirm_key, '/register')) 
    1715         success = """<h1>Hello, %s. Thank you for registering!</h1>""" % username 
     1722        success = """<h1>Email address confirmed for user %s</h1>""" % username 
    17161723        del waiting[key] 
    17171724        return http.Response(stream=message(success))  
    17181725 
     
    18881895                    missing[i] = True 
    18891896             
    18901897            if set(missing) == set([True]): 
    1891                 return http.Response(stream=template.registration(**template_dict)) 
     1898                return http.Response(stream=template('registration.html', **template_dict)) 
    18921899            elif set(missing) == set([False]): 
    18931900                for i, box in enumerate(input_boxes): 
    18941901                    filled_in[box] = request.args[box][0] 
     
    19141921         
    19151922        if template_dict and set(template_dict) != set(['email']): 
    19161923            errors_found() 
    1917             return http.Response(stream=template.registration(**template_dict)) 
     1924            return http.Response(stream=template('registration.html', **template_dict)) 
    19181925        else: 
    19191926            try: 
    19201927                e = filled_in['email'] if notebook.conf()['email'] else '' 
     
    19231930            except ValueError: 
    19241931                template_dict['username_taken'] = True 
    19251932                errors_found() 
    1926                 return http.Response(stream=template.registration(**template_dict)) 
     1933                return http.Response(stream=template('registration.html', **template_dict)) 
    19271934             
    19281935            if notebook.conf()['email']: 
    19291936                destaddr = filled_in['email'] 
     
    19441951                except ValueError: 
    19451952                    pass 
    19461953             
    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'])) 
     1954            template_dict = {'accounts': notebook.get_accounts(), 
     1955                             'default_user': notebook.default_user(), 
     1956                             'welcome': filled_in['username'], 
     1957                             'recovery': notebook.conf()['email']} 
     1958            return http.Response(stream=template('login.html', **template_dict)) 
    19501959     
    19511960class ForgotPassPage(resource.Resource): 
    19521961         
     
    19922001             
    19932002            return http.Response(stream=message("A new password has been sent to your e-mail address.", '/')) 
    19942003        else: 
    1995             s = template.account_recovery(
     2004            s = template('account_recovery.html'
    19962005        return http.Response(stream=s) 
    19972006 
    19982007class ListOfUsers(resource.Resource): 
     
    20032012            if user_type(self.username) != 'admin': 
    20042013                s = message('You must an admin to manage other users.') 
    20052014            else: 
    2006                 s = template.user_management(users=notebook.valid_login_names()
     2015                s = template('user_management.html', {'users':notebook.valid_login_names()}
    20072016            return http.Response(stream = s) 
    20082017 
    20092018class InvalidPage(resource.Resource): 
     
    20432052        self.username = username if username else 'guest' 
    20442053 
    20452054    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  
     2055        template_dict = {'accounts': notebook.get_accounts(), 
     2056                         'default_user': notebook.default_user(), 
     2057                         'recovery': notebook.conf()['email']} 
     2058        return http.Response(stream=template('login.html', **template_dict)) 
     2059     
    20482060    def userchildFactory(self, request, name): 
    20492061        return InvalidPage(msg = "unauthorized request", username = self.username) 
    20502062 
     
    20552067 
    20562068class LoginResourceClass(resource.Resource): 
    20572069    def render(self, ctx): 
    2058         return http.Response(stream =  template.login(accounts=notebook.get_accounts(), default_user=notebook.default_user(), recovery=notebook.conf()['email'])) 
     2070        template_dict = {'accounts': notebook.get_accounts(), 
     2071                         'default_user': notebook.default_user(), 
     2072                         'recovery': notebook.conf()['email']} 
     2073        return http.Response(stream=template('login.html', **template_dict)) 
    20592074     
    20602075    def childFactory(self, request, name): 
    20612076        return LoginResource 
     
    20902105    #child_login = LoginResource 
    20912106     
    20922107    def render(self, ctx): 
    2093         response = http.Response(stream =  template.login(accounts=notebook.get_accounts(), default_user=notebook.default_user(), recovery=notebook.conf()['email'])) 
     2108        template_dict = {'accounts': notebook.get_accounts(), 
     2109                         'default_user': notebook.default_user(), 
     2110                         'recovery': notebook.conf()['email']} 
     2111        response = http.Response(stream=template('login.html', **template_dict)) 
    20942112        response.headers.setHeader("set-cookie", [http_headers.Cookie('cookie_test', 'cookie_test')]) 
    20952113        return response 
    20962114 
     
    21052123        # worksheets and ratings, this gives no new information way. 
    21062124        # If published pages were disabled, then this should be disabled too. 
    21072125        if self.problem == 'username': 
    2108             return http.Response(stream = template.login(accounts=notebook.get_accounts(), default_user='', username_error=True, recovery=notebook.conf()['email'])) 
     2126            template_dict = {'accounts': notebook.get_accounts(), 
     2127                             'default_user': notebook.default_user(), 
     2128                             'username_error': True, 
     2129                             'recovery': notebook.conf()['email']} 
     2130            return http.Response(stream=template('login.html', **template_dict)) 
    21092131        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'])) 
     2132            template_dict = {'accounts': notebook.get_accounts(), 
     2133                             'default_user': self.username, 
     2134                             'password_error': True, 
     2135                             'recovery': notebook.conf()['email']} 
     2136            return http.Response(stream=template('login.html', **template_dict)) 
    21112137        else: 
    21122138            return http.Response(stream = message("Please enable cookies and try again.")) 
    21132139 
  • 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 collaborator_names(self, max=None): 
     393        """ 
     394        Returns a string of the non-owner collaborators on this worksheet. 
     395 
     396        INPUT: 
     397            max -- an integer. If this is specified, then only max number of 
     398                   collaborators are shown. 
     399 
     400        EXAMPLES: 
     401            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir()) 
     402            sage: W = nb.create_new_worksheet('test1', '