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 94 94 # This must happen after twist.notebook is set. 95 95 self.save() 96 96 97 98 97 def _migrate_worksheets(self): 99 98 v = [] 100 99 for key, W in self.__worksheets.iteritems(): … … 1260 1259 s += '\n</body>\n' 1261 1260 return s 1262 1261 1262 1263 1263 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): 1266 1265 W = [x for x in self.__worksheets.itervalues() if x.is_published() and not x.is_trashed(user)] 1267 1266 1268 1267 if search: 1269 1268 W = [x for x in W if x.satisfies_search(search)] 1270 1269 1271 1270 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 1288 1272 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): 1297 1274 X = self.get_worksheets_with_viewer(user) 1298 1275 if typ == "trash": 1299 worksheet_heading = "Trash"1300 1276 W = [x for x in X if x.is_trashed(user)] 1301 1277 elif typ == "active": 1302 worksheet_heading = "Active Worksheets"1303 1278 W = [x for x in X if x.is_active(user)] 1304 1279 else: # typ must be archived or "all" 1305 worksheet_heading = "Archived and Active"1306 1280 W = [x for x in X if not x.is_trashed(user)] 1307 1281 if search: 1308 1282 W = [x for x in W if x.satisfies_search(search)] 1309 1310 1283 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 1329 1285 1330 1286 def html_topbar(self, user, pub=False): 1331 1287 s = '' … … 1336 1292 else: 1337 1293 entries.append(('/home/%s'%user, 'Home', 'Back to your personal worksheet list')) 1338 1294 entries.append(('/pub', 'Published', 'Browse the published worksheets')) 1339 #entries.append(('/settings', 'Settings', 'Change user settings')) # TODO -- settings1340 1295 entries.append(('help()', 'Help', 'Documentation')) 1341 1296 1342 1297 ## TODO -- settings … … 1398 1353 """%ver 1399 1354 return s 1400 1355 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 1407 </span>1408 """%(typ, '' if search is None else search.replace('"',"'"), typ)1409 return s1410 1411 def html_new_or_upload(self):1412 s = """1413 <a class="boldusercontrol" href="/new_worksheet">New Worksheet</a>\n1414 <a class="boldusercontrol" href="/upload">Upload</a>\n1415 """1416 return s1417 1356 1418 1357 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 ## """1432 1358 s = '' 1433 1359 1434 1360 if not self.user_is_guest(user): … … 1457 1383 s += '</span>' 1458 1384 return s 1459 1385 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> <input id="controlbox" onClick="set_worksheet_list_checks();" class="entry" type=checkbox></td>'1471 else:1472 s += '<td> <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'%name1492 if w.is_active(user):1493 k += '<td class="worksheet_link">%s</td>'%name1494 else:1495 k += '<td class="archived_worksheet_link">%s</td>'%name1496 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 can1505 <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 s1509 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"%rating1518 if not self.user_is_guest(user) and not worksheet.is_rater(user):1519 r = '<i>%s</i>'%r1520 if r != '----':1521 r = '<a class="worksheet_edit" href="/home/%s/rating_info">%s</a>'%(name,r)1522 return r1523 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 += ' '*41540 k += doc_options(worksheet.filename())1541 k += ' '*41542 return k1543 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 = False1556 if owner == 'pub':1557 pub = True1558 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_ver1580 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]) + ' ' + share1587 1588 return s1589 1590 1386 1591 1387 ########################################################## 1592 1388 # Revision history for a worksheet … … 2612 2408 def sort_worksheet_list(v, sort, reverse): 2613 2409 """ 2614 2410 INPUT: 2615 sort -- 'last_edited', 'owner', or 'name'2411 sort -- 'last_edited', 'owner', 'rating', or 'name' 2616 2412 reverse -- if True, reverse the order of the sort. 2617 2413 """ 2618 2414 f = None … … 2635 2431 else: 2636 2432 raise ValueError, "invalid sort key '%s'"%sort 2637 2433 v.sort(cmp = f, reverse=reverse) 2638 2639 2640 -
a/sage/server/notebook/template.py
old new 1 """nodoctest2 1 """ 2 HTML templating for the notebook 3 3 4 AUTHORS: 5 -- Bobby Moretti (2007-07-18): initial version 6 -- Timothy Clemans and Mike Hansen (2008-10-27): major update 7 8 """ 4 9 ############################################################################# 5 10 # Copyright (C) 2007 William Stein <wstein@gmail.com> 6 11 # Distributed under the terms of the GNU General Public License (GPL) 7 12 # The full text of the GPL is available at: 8 13 # http://www.gnu.org/licenses/ 9 14 ############################################################################# 15 import jinja 16 import sage.misc.misc 17 from sage.version import version 10 18 11 """ 12 HTML templating for the notebook 19 TEMPLATE_PATH = sage.misc.misc.SAGE_ROOT + '/devel/sage/sage/server/notebook/templates' 20 env = jinja.Environment(loader=jinja.FileSystemLoader(TEMPLATE_PATH)) 13 21 14 AUTHORS: 15 -- Bobby Moretti 16 -- Timothy Clemans 17 """ 22 def 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. 18 27 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 40 env.tests['contained_in'] = contained_in 23 41 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 45 default_context = {'sitename': 'Sage Notebook', 46 'sage_version': version} 25 47 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)) 48 def template(filename, **user_context): 49 """ 50 Returns a rendered template as a string. 32 51 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 1 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> 2 2 <html lang="en"> 3 3 <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 %} 6 7 </head> 7 8 <body> 8 9 {% 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 31 31 ############################################################ 32 32 33 33 import os, shutil, time 34 34 from sage.version import version 35 35 import bz2 36 36 37 37 from twisted.web2 import server, http, resource, channel … … 41 41 42 42 import notebook as _notebook 43 43 44 import sage.server.notebook.template astemplate44 from sage.server.notebook.template import template 45 45 46 46 HISTORY_MAX_OUTPUT = 92*5 47 47 HISTORY_NCOLS = 90 … … 118 118 # An error message 119 119 ############################ 120 120 def 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) 122 123 123 124 ############################ 124 125 # Create a Sage worksheet from a latex2html'd file … … 930 931 if template_dict['email']: 931 932 template_dict['email_address'] = 'None' if not notebook.user(self.username)._User__email else notebook.user(self.username)._User__email 932 933 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)) 934 935 935 936 ######################################################## 936 937 # Set output type of a cell … … 1164 1165 class Worksheet_rating_info(WorksheetResource, resource.Resource): 1165 1166 def render(self, ctx): 1166 1167 s = self.worksheet.html_ratings_info() 1167 return http.Response(stream=message( """1168 return http.Response(stream=message(''' 1168 1169 <h2 align=center>Ratings for %s</h2> 1169 1170 <h3 align=center><a href='/home/%s'>Go to the worksheet.</a> 1170 1171 <br><br> … … 1173 1174 %s 1174 1175 </table> 1175 1176 <br><br> 1176 """%(self.worksheet.name(), self.worksheet.filename(), s)))1177 '''%(self.worksheet.name(), self.worksheet.filename(), s))) 1177 1178 1178 1179 1179 1180 class Worksheet_rate(WorksheetResource, resource.Resource): … … 1307 1308 return static.File(h) 1308 1309 return NotImplementedWorksheetOp(op, self.worksheet) 1309 1310 1311 1310 1312 def 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 1313 1336 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()) 1339 1346 1340 1347 1341 1348 class WorksheetsByUser(resource.Resource): … … 1712 1719 user.set_email_confirmation(True) 1713 1720 except KeyError: 1714 1721 return http.Response(stream=message(invalid_confirm_key, '/register')) 1715 success = """<h1> Hello, %s. Thank you for registering!</h1>""" % username1722 success = """<h1>Email address confirmed for user %s</h1>""" % username 1716 1723 del waiting[key] 1717 1724 return http.Response(stream=message(success)) 1718 1725 … … 1888 1895 missing[i] = True 1889 1896 1890 1897 if set(missing) == set([True]): 1891 return http.Response(stream=template .registration(**template_dict))1898 return http.Response(stream=template('registration.html', **template_dict)) 1892 1899 elif set(missing) == set([False]): 1893 1900 for i, box in enumerate(input_boxes): 1894 1901 filled_in[box] = request.args[box][0] … … 1914 1921 1915 1922 if template_dict and set(template_dict) != set(['email']): 1916 1923 errors_found() 1917 return http.Response(stream=template .registration(**template_dict))1924 return http.Response(stream=template('registration.html', **template_dict)) 1918 1925 else: 1919 1926 try: 1920 1927 e = filled_in['email'] if notebook.conf()['email'] else '' … … 1923 1930 except ValueError: 1924 1931 template_dict['username_taken'] = True 1925 1932 errors_found() 1926 return http.Response(stream=template .registration(**template_dict))1933 return http.Response(stream=template('registration.html', **template_dict)) 1927 1934 1928 1935 if notebook.conf()['email']: 1929 1936 destaddr = filled_in['email'] … … 1944 1951 except ValueError: 1945 1952 pass 1946 1953 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)) 1950 1959 1951 1960 class ForgotPassPage(resource.Resource): 1952 1961 … … 1992 2001 1993 2002 return http.Response(stream=message("A new password has been sent to your e-mail address.", '/')) 1994 2003 else: 1995 s = template .account_recovery()2004 s = template('account_recovery.html') 1996 2005 return http.Response(stream=s) 1997 2006 1998 2007 class ListOfUsers(resource.Resource): … … 2003 2012 if user_type(self.username) != 'admin': 2004 2013 s = message('You must an admin to manage other users.') 2005 2014 else: 2006 s = template .user_management(users=notebook.valid_login_names())2015 s = template('user_management.html', {'users':notebook.valid_login_names()}) 2007 2016 return http.Response(stream = s) 2008 2017 2009 2018 class InvalidPage(resource.Resource): … … 2043 2052 self.username = username if username else 'guest' 2044 2053 2045 2054 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 2048 2060 def userchildFactory(self, request, name): 2049 2061 return InvalidPage(msg = "unauthorized request", username = self.username) 2050 2062 … … 2055 2067 2056 2068 class LoginResourceClass(resource.Resource): 2057 2069 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)) 2059 2074 2060 2075 def childFactory(self, request, name): 2061 2076 return LoginResource … … 2090 2105 #child_login = LoginResource 2091 2106 2092 2107 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)) 2094 2112 response.headers.setHeader("set-cookie", [http_headers.Cookie('cookie_test', 'cookie_test')]) 2095 2113 return response 2096 2114 … … 2105 2123 # worksheets and ratings, this gives no new information way. 2106 2124 # If published pages were disabled, then this should be disabled too. 2107 2125 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)) 2109 2131 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)) 2111 2137 else: 2112 2138 return http.Response(stream = message("Please enable cookies and try again.")) 2113 2139 -
a/sage/server/notebook/worksheet.py
old new 387 387 return self.__collaborators 388 388 except AttributeError: 389 389 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', '