mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-17 23:46:09 +00:00
Preliminary port of introweb to t.w.template.
It doesn't do JSON yet, so this is more of a proof of a concept than anything usable yet.
This commit is contained in:
parent
0723a2f4d2
commit
ae1f41af98
@ -2,7 +2,7 @@
|
||||
import time
|
||||
import json
|
||||
|
||||
from twisted.web import http, server, resource
|
||||
from twisted.web import http, server, resource, template
|
||||
from twisted.python import log
|
||||
from twisted.python.failure import Failure
|
||||
from zope.interface import Interface
|
||||
@ -461,6 +461,32 @@ class MultiFormatPage(Page):
|
||||
|
||||
|
||||
|
||||
class SlotsSequenceElement(template.Element):
|
||||
def __init__(self, tag, seq):
|
||||
self.loader = template.TagLoader(tag)
|
||||
self.seq = seq
|
||||
|
||||
@template.renderer
|
||||
def header(self, request, tag):
|
||||
if len(self.seq) > 0:
|
||||
return tag
|
||||
else:
|
||||
return ''
|
||||
|
||||
@template.renderer
|
||||
def item(self, request, tag):
|
||||
for item in self.seq:
|
||||
yield tag().fillSlots(**item)
|
||||
@template.renderer
|
||||
|
||||
def empty(self, request, tag):
|
||||
if len(self.seq) > 0:
|
||||
return ''
|
||||
else:
|
||||
return tag
|
||||
|
||||
|
||||
|
||||
class TokenOnlyWebApi(resource.Resource, object):
|
||||
"""
|
||||
I provide a rend.Page implementation that only accepts POST calls,
|
||||
|
@ -1,4 +1,4 @@
|
||||
<html xmlns:n="http://nevow.com/ns/nevow/0.1"><head>
|
||||
<html xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1"><head>
|
||||
<title>Tahoe-LAFS - Introducer Status</title>
|
||||
<link href="/tahoe.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/icon.png" rel="shortcut icon" />
|
||||
@ -10,23 +10,23 @@
|
||||
<div class="section" id="this-client">
|
||||
<h2>This Introducer</h2>
|
||||
|
||||
<table class="node-info table-headings-left">
|
||||
<tr><th>My nodeid:</th> <td class="nodeid mine data-chars" n:render="string" n:data="my_nodeid" /></tr>
|
||||
<tr><th>My versions:</th> <td n:render="string" n:data="version" /></tr>
|
||||
<tr><th>Tahoe-LAFS code imported from:</th> <td n:render="data" n:data="import_path" /></tr>
|
||||
<table class="node-info table-headings-left" t:render="node_data">
|
||||
<tr><th>My nodeid:</th> <td class="nodeid mine data-chars"><t:slot name="my_nodeid" /></td></tr>
|
||||
<tr><th>My versions:</th> <td><t:slot name="version" /></td></tr>
|
||||
<tr><th>Tahoe-LAFS code imported from:</th> <td><t:slot name="import_path" /></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>Announcement Summary: <span n:render="announcement_summary" /></div>
|
||||
<div>Subscription Summary: <span n:render="client_summary" /></div>
|
||||
<div>Announcement Summary: <span t:render="announcement_summary" /></div>
|
||||
<div>Subscription Summary: <span t:render="client_summary" /></div>
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
<div class="section">
|
||||
<h2>Service Announcements</h2>
|
||||
<table class="services table-headings-top" n:render="sequence" n:data="services">
|
||||
<tr n:pattern="header">
|
||||
<table class="services table-headings-top" t:render="services">
|
||||
<tr t:render="header">
|
||||
<th class="nickname-and-peerid">
|
||||
<div class="service-nickname">Nickname</div>
|
||||
<div class="nodeid data-chars">ServerID</div></th>
|
||||
@ -34,23 +34,23 @@
|
||||
<th>Version</th>
|
||||
<th>Service Name</th>
|
||||
</tr>
|
||||
<tr n:pattern="item" n:render="service_row">
|
||||
<tr t:render="item">
|
||||
<td class="nickname-and-peerid">
|
||||
<div class="nickname"><n:slot name="nickname"/></div>
|
||||
<div class="nodeid data-chars"><n:slot name="serverid"/></div></td>
|
||||
<td class="service-announced"><n:attr name="title"><n:slot name="connection-hints"/></n:attr><n:slot name="announced"/></td>
|
||||
<td class="service-version"><n:slot name="version"/></td>
|
||||
<td class="service-service-name"><n:slot name="service_name"/></td>
|
||||
<div class="nickname"><t:slot name="nickname"/></div>
|
||||
<div class="nodeid data-chars"><t:slot name="serverid"/></div></td>
|
||||
<td class="service-announced"><t:attr name="title"><t:slot name="connection-hints"/></t:attr><t:slot name="announced"/></td>
|
||||
<td class="service-version"><t:slot name="version"/></td>
|
||||
<td class="service-service-name"><t:slot name="service_name"/></td>
|
||||
</tr>
|
||||
<tr n:pattern="empty"><td>no peers!</td></tr>
|
||||
<tr t:render="empty"><td>no peers!</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<h2>Subscribed Clients</h2>
|
||||
<table class="services table-headings-top" n:render="sequence" n:data="subscribers">
|
||||
<tr n:pattern="header">
|
||||
<table class="services table-headings-top" t:render="subscribers">
|
||||
<tr t:render="header">
|
||||
<th class="nickname-and-peerid">
|
||||
<div class="service-nickname">Nickname</div>
|
||||
<div class="nodeid data-chars">Tub ID</div></th>
|
||||
@ -59,20 +59,20 @@
|
||||
<th>Version</th>
|
||||
<th>Subscribed To</th>
|
||||
</tr>
|
||||
<tr n:pattern="item" n:render="subscriber_row">
|
||||
<tr t:render="item">
|
||||
<td class="nickname-and-peerid">
|
||||
<div class="nickname"><n:slot name="nickname"/></div>
|
||||
<div class="nodeid data-chars"><n:slot name="tubid"/></div></td>
|
||||
<td><n:slot name="connected"/></td>
|
||||
<td class="service-since"><n:slot name="since"/></td>
|
||||
<td class="service-version"><n:slot name="version"/></td>
|
||||
<td class="service-service-name"><n:slot name="service_name"/></td>
|
||||
<div class="nickname"><t:slot name="nickname"/></div>
|
||||
<div class="nodeid data-chars"><t:slot name="tubid"/></div></td>
|
||||
<td><t:slot name="connected"/></td>
|
||||
<td class="service-since"><t:slot name="since"/></td>
|
||||
<td class="service-version"><t:slot name="version"/></td>
|
||||
<td class="service-service-name"><t:slot name="service_name"/></td>
|
||||
</tr>
|
||||
<tr n:pattern="empty"><td>no subscribers!</td></tr>
|
||||
<tr t:render="empty"><td>no subscribers!</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p class="minutia">Page rendered at <span n:render="data" n:data="rendered_at" /></p>
|
||||
<p class="minutia" t:render="node_data">Page rendered at <span><t:slot name="rendered_at" /></span></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -3,6 +3,9 @@ import time, os
|
||||
from nevow import rend
|
||||
from nevow.static import File as nevow_File
|
||||
from nevow.util import resource_filename
|
||||
from twisted.web.template import Element, renderer, renderElement, XMLFile
|
||||
from twisted.python.filepath import FilePath
|
||||
from twisted.web import resource
|
||||
import allmydata
|
||||
import json
|
||||
from allmydata.version_checks import get_package_versions_string
|
||||
@ -11,24 +14,27 @@ from allmydata.web.common import (
|
||||
getxmlfile,
|
||||
render_time,
|
||||
MultiFormatPage,
|
||||
SlotsSequenceElement,
|
||||
)
|
||||
|
||||
|
||||
class IntroducerRoot(MultiFormatPage):
|
||||
|
||||
addSlash = True
|
||||
docFactory = getxmlfile("introducer.xhtml")
|
||||
|
||||
child_operations = None
|
||||
|
||||
class IntroducerRoot(resource.Resource):
|
||||
def __init__(self, introducer_node):
|
||||
resource.Resource.__init__(self)
|
||||
# probably should fix this.. Resource isn't new-style in py2
|
||||
#super(IntroducerRoot, self).__init__()
|
||||
self.introducer_node = introducer_node
|
||||
self.introducer_service = introducer_node.getServiceNamed("introducer")
|
||||
rend.Page.__init__(self, introducer_node)
|
||||
# necessary as a root Resource
|
||||
self.putChild('', self)
|
||||
static_dir = resource_filename("allmydata.web", "static")
|
||||
for filen in os.listdir(static_dir):
|
||||
self.putChild(filen, nevow_File(os.path.join(static_dir, filen)))
|
||||
|
||||
def render(self, request):
|
||||
return renderElement(request, IntroducerRootElement(
|
||||
self.introducer_node, self.introducer_service))
|
||||
|
||||
def render_JSON(self, req):
|
||||
res = {}
|
||||
|
||||
@ -49,17 +55,38 @@ class IntroducerRoot(MultiFormatPage):
|
||||
|
||||
return json.dumps(res, indent=1) + "\n"
|
||||
|
||||
|
||||
class IntroducerRootElement(Element):
|
||||
|
||||
loader = XMLFile(FilePath(__file__).sibling("introducer.xhtml"))
|
||||
|
||||
def __init__(self, introducer_node, introducer_service):
|
||||
super(IntroducerRootElement, self).__init__()
|
||||
self.introducer_node = introducer_node
|
||||
self.introducer_service = introducer_service
|
||||
self.node_data_dict = {
|
||||
'my_nodeid': idlib.nodeid_b2a(self.introducer_node.nodeid),
|
||||
'version': get_package_versions_string(),
|
||||
'import_path': str(allmydata).replace("/", "/ "), # XXX kludge for wrapping
|
||||
'rendered_at': render_time(time.time()),
|
||||
}
|
||||
|
||||
@renderer
|
||||
def node_data(self, req, tag):
|
||||
return tag.fillSlots(**self.node_data_dict)
|
||||
|
||||
# FIXME: This code is duplicated in root.py and introweb.py.
|
||||
def data_rendered_at(self, ctx, data):
|
||||
return render_time(time.time())
|
||||
def data_version(self, ctx, data):
|
||||
return get_package_versions_string()
|
||||
def data_import_path(self, ctx, data):
|
||||
return str(allmydata).replace("/", "/ ") # XXX kludge for wrapping
|
||||
return str(allmydata).replace("/", "/ ")
|
||||
def data_my_nodeid(self, ctx, data):
|
||||
return idlib.nodeid_b2a(self.introducer_node.nodeid)
|
||||
|
||||
def render_announcement_summary(self, ctx, data):
|
||||
@renderer
|
||||
def announcement_summary(self, req, data):
|
||||
services = {}
|
||||
for ad in self.introducer_service.get_announcements():
|
||||
if ad.service_name not in services:
|
||||
@ -70,7 +97,8 @@ class IntroducerRoot(MultiFormatPage):
|
||||
return ", ".join(["%s: %d" % (service_name, services[service_name])
|
||||
for service_name in service_names])
|
||||
|
||||
def render_client_summary(self, ctx, data):
|
||||
@renderer
|
||||
def client_summary(self, req, data):
|
||||
counts = {}
|
||||
for s in self.introducer_service.get_subscribers():
|
||||
if s.service_name not in counts:
|
||||
@ -79,32 +107,30 @@ class IntroducerRoot(MultiFormatPage):
|
||||
return ", ".join([ "%s: %d" % (name, counts[name])
|
||||
for name in sorted(counts.keys()) ] )
|
||||
|
||||
def data_services(self, ctx, data):
|
||||
@renderer
|
||||
def services(self, req, tag):
|
||||
services = self.introducer_service.get_announcements()
|
||||
services.sort(key=lambda ad: (ad.service_name, ad.nickname))
|
||||
return services
|
||||
services = [{
|
||||
"serverid": ad.serverid,
|
||||
"nickname": ad.nickname,
|
||||
"connection-hints":
|
||||
"connection hints: " + " ".join(ad.connection_hints),
|
||||
"connected": "?",
|
||||
"announced": render_time(ad.when),
|
||||
"version": ad.version,
|
||||
"service_name": ad.service_name,
|
||||
} for ad in services]
|
||||
return SlotsSequenceElement(tag, services)
|
||||
|
||||
def render_service_row(self, ctx, ad):
|
||||
ctx.fillSlots("serverid", ad.serverid)
|
||||
ctx.fillSlots("nickname", ad.nickname)
|
||||
ctx.fillSlots("connection-hints",
|
||||
"connection hints: " + " ".join(ad.connection_hints))
|
||||
ctx.fillSlots("connected", "?")
|
||||
when_s = render_time(ad.when)
|
||||
ctx.fillSlots("announced", when_s)
|
||||
ctx.fillSlots("version", ad.version)
|
||||
ctx.fillSlots("service_name", ad.service_name)
|
||||
return ctx.tag
|
||||
|
||||
def data_subscribers(self, ctx, data):
|
||||
return self.introducer_service.get_subscribers()
|
||||
|
||||
def render_subscriber_row(self, ctx, s):
|
||||
ctx.fillSlots("nickname", s.nickname)
|
||||
ctx.fillSlots("tubid", s.tubid)
|
||||
ctx.fillSlots("connected", s.remote_address)
|
||||
since_s = render_time(s.when)
|
||||
ctx.fillSlots("since", since_s)
|
||||
ctx.fillSlots("version", s.version)
|
||||
ctx.fillSlots("service_name", s.service_name)
|
||||
return ctx.tag
|
||||
@renderer
|
||||
def subscribers(self, ctx, tag):
|
||||
subscribers = [{
|
||||
"nickname": s.nickname,
|
||||
"tubid": s.tubid,
|
||||
"connected": s.remote_address,
|
||||
"since": render_time(s.when),
|
||||
"version": s.version,
|
||||
"service_name": s.service_name,
|
||||
} for s in self.introducer_service.get_subscribers()]
|
||||
return SlotsSequenceElement(tag, subscribers)
|
||||
|
Loading…
x
Reference in New Issue
Block a user