s = self.remove_tags(html)
self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
self.failUnlessIn("Not Recoverable! : rather dead", s)
- self.failUnlessIn("Corrupt shares: sh#2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (peer-0)", s)
+ self.failUnlessIn("Corrupt shares: Share ID Nickname Node ID sh#2 peer-0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", s)
html = self.render2(w)
s = self.remove_tags(html)
public = "uri/" + self._root_directory_uri
d = getPage(base)
def _got_welcome(page):
- expected = "Connected Storage Servers: <span>%d</span>" % (self.numclients)
+ # XXX This test is oversensitive to formatting
+ expected = "Connected to <span>%d</span>\n of <span>%d</span> known storage servers:" % (self.numclients, self.numclients)
self.failUnless(expected in page,
"I didn't see the right 'connected storage servers'"
" message in: %s" % page
)
- expected = "My nodeid: <span>%s</span>" % (b32encode(self.clients[0].nodeid).lower(),)
+ expected = "<th>My nodeid:</th> <td class=\"nodeid mine data-chars\">%s</td>" % (b32encode(self.clients[0].nodeid).lower(),)
self.failUnless(expected in page,
"I didn't see the right 'My nodeid' message "
"in: %s" % page)
# the FILE reference points to a URI, but it should end in bar.txt
bar_url = ("%s/file/%s/@@named=/bar.txt" %
(ROOT, urllib.quote(self._bar_txt_uri)))
- get_bar = "".join([r'<td>',
+ get_bar = "".join([r'<td>FILE</td>',
+ r'\s+<td>',
r'<a href="%s">bar.txt</a>' % bar_url,
r'</td>',
- r'\s+<td>FILE</td>',
r'\s+<td>%d</td>' % len(self.BAR_CONTENTS),
])
self.failUnless(re.search(get_bar, res), res)
# the DIR reference just points to a URI
sub_url = ("%s/uri/%s/" % (ROOT, urllib.quote(self._sub_uri)))
- get_sub = ((r'<td><a href="%s">sub</a></td>' % sub_url)
- + r'\s+<td>DIR</td>')
+ get_sub = ((r'<td>DIR</td>')
+ +r'\s+<td><a href="%s">sub</a></td>' % sub_url)
self.failUnless(re.search(get_sub, res), res)
d.addCallback(_check)
d.addCallback(lambda res:
self.GET(self.public_url, followRedirect=True))
def _check3(res):
- self.failUnless(re.search(r'<td><a href="[\.\/]+/uri/URI%3ADIR2-RO%3A[^"]+">reedownlee</a>'
- '</td>\s+<td>DIR-RO</td>', res))
+ self.failUnless(re.search('<td>DIR-RO</td>'
+ r'\s+<td><a href="[\.\/]+/uri/URI%3ADIR2-RO%3A[^"]+">reedownlee</a></td>', res), res)
d.addCallback(_check3)
# and an empty directory
# Fetch the welcome page.
d = self.GET("/")
def _after_get_welcome_page(res):
- MKDIR_BUTTON_RE=re.compile('<form action="([^"]*)" method="post".*<input type="hidden" name="t" value="([^"]*)" /><input type="hidden" name="([^"]*)" value="([^"]*)" /><input type="submit" value="create directory" />', re.I)
+ MKDIR_BUTTON_RE=re.compile('<form action="([^"]*)" method="post".*?<input type="hidden" name="t" value="([^"]*)" /><input type="hidden" name="([^"]*)" value="([^"]*)" /><input type="submit" value="Create a directory" />', re.I)
mo = MKDIR_BUTTON_RE.search(res)
formaction = mo.group(1)
formt = mo.group(2)
for (serverid, si, shnum) in data["list-corrupt-shares"]:
nickname = c.get_nickname_for_peerid(serverid)
badsharemap.append(T.tr[T.td["sh#%d" % shnum],
- T.td[T.tt[base32.b2a(serverid)],
- " (", nickname, ")"],
+ T.td[T.div(class_="nickname")[nickname],
+ T.div(class_="nodeid")[T.tt[base32.b2a(serverid)]]],
])
- add("Corrupt shares", T.table(border="1")[badsharemap])
+ add("Corrupt shares", T.table()[
+ T.tr[T.th["Share ID"],
+ T.th(class_="nickname-and-peerid")[T.div["Nickname"], T.div(class_="nodeid")["Node ID"]]],
+ badsharemap])
else:
add("Corrupt shares", "none")
shareid_s = shareid
nickname = c.get_nickname_for_peerid(serverid)
sharemap.append(T.tr[T.td[shareid_s],
- T.td[T.tt[base32.b2a(serverid)],
- " (", nickname, ")"],
+ T.td[T.div(class_="nickname")[nickname],
+ T.div(class_="nodeid")[T.tt[base32.b2a(serverid)]]]
])
add("Good Shares (sorted in share order)",
- T.table(border="1")[sharemap])
+ T.table()[T.tr[T.th["Share ID"], T.th(class_="nickname-and-peerid")[T.div["Nickname"], T.div(class_="nodeid")["Node ID"]]],
+ sharemap])
add("Recoverable Versions", data["count-recoverable-versions"])
shareids = servers.get(serverid, [])
shareids.reverse()
shareids_s = [ T.tt[shareid, " "] for shareid in sorted(shareids) ]
- servermap.append(T.tr[T.td[T.tt[base32.b2a(serverid)],
- " (", nickname, ")"],
- T.td[shareids_s] ])
+ servermap.append(T.tr[T.td[T.div(class_="nickname")[nickname],
+ T.div(class_="nodeid")[T.tt[base32.b2a(serverid)]]],
+ T.td[shareids_s],
+ ])
num_shares_left -= len(shareids)
if not num_shares_left:
break
add("Share Balancing (servers in permuted order)",
- T.table(border="1")[servermap])
+ T.table()[T.tr[T.th(class_="nickname-and-peerid")[T.div["Nickname"], T.div(class_="nodeid")["Node ID"]], T.th["Share IDs"]],
+ servermap])
return T.ul[r]
<div n:render="return" />
<div>
-<table n:render="sequence" n:data="all_objects" border="1">
+<table n:render="sequence" n:data="all_objects">
<tr n:pattern="header">
<td>Relative Path</td>
<td>Healthy Pre-Repair</td>
<div n:render="corrupt_shares_p">
<h2>Corrupt Shares</h2>
<p>If repair fails, these shares need to be manually inspected and removed.</p>
-<table n:render="sequence" n:data="corrupt_shares" border="1">
+<table n:render="sequence" n:data="corrupt_shares">
<tr n:pattern="header">
<td>Server</td>
<td>Server Nickname</td>
<div>
<h2>All Results</h2>
-<table n:render="sequence" n:data="all_objects" border="1">
+<table n:render="sequence" n:data="all_objects">
<tr n:pattern="header">
<td>Relative Path</td>
<td>Healthy</td>
def render_header(self, ctx, data):
si_s = abbreviated_dirnode(self.node)
- header = ["Directory SI=%s" % si_s]
+ header = ["Directory SI=", T.span(class_="data-chars")[si_s]]
if self.node.is_readonly():
header.append(" (read-only)")
return ctx.tag[header]
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body class="tahoe-directory-page">
-<h2 n:render="header"></h2>
+<h1 n:render="header"></h1>
-<div><a href=".">Refresh this view</a></div>
-<div n:render="welcome" />
+<div class="toolbar">
+ <div class="toolbar-item" n:render="welcome" />
+ <div class="toolbar-item"><a href=".">Refresh</a></div>
-<div><a href="?t=info">More info on this directory</a></div>
-<div n:render="show_readonly" />
+ <div class="toolbar-item"><a href="?t=info">More info on this directory</a></div>
+ <div class="toolbar-item" n:render="show_readonly" />
+</div>
<div n:render="try_children">
-<table n:render="sequence" n:data="children" border="1">
- <tr n:pattern="header">
- <td>Filename</td>
- <td>Type</td>
- <td>Size</td>
- <td>Times</td>
- <td></td>
- <td></td>
- <td></td>
- </tr>
- <tr n:pattern="item" n:render="row">
- <td><n:slot name="filename"/></td>
- <td><n:slot name="type"/></td>
- <td><n:slot name="size"/></td>
- <td><n:slot name="times"/></td>
- <td><n:slot name="delete"/></td>
- <td><n:slot name="rename"/></td>
- <td><n:slot name="info"/></td>
- </tr>
-
- <tr n:pattern="empty"><td>directory is empty</td></tr>
-
-</table>
+ <table class="tahoe-directory" n:render="sequence" n:data="children">
+ <tr n:pattern="header">
+ <th>Type</th>
+ <th>Filename</th>
+ <th>Size</th>
+ <th>Times</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+ <tr n:pattern="item" n:render="row">
+ <td><n:slot name="type"/></td>
+ <td><n:slot name="filename"/></td>
+ <td><n:slot name="size"/></td>
+ <td><n:slot name="times"/></td>
+ <td><n:slot name="delete"/></td>
+ <td><n:slot name="rename"/></td>
+ <td><n:slot name="info"/></td>
+ </tr>
+
+ <tr n:pattern="empty"><td colspan="9" class="empty-marker">This directory is empty.</td></tr>
+
+ </table>
</div>
+<div class="tahoe-directory-footer">
+ <div n:render="forms"/>
-<div n:render="forms"/>
-
-<div class="results" n:render="results"/>
+ <div class="results" n:render="results"/>
+</div>
- </body>
-</html>
+</body></html>
<link href="/tahoe_css" rel="stylesheet" type="text/css"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<h2 n:render="header"></h2>
+</head><body>
+
+<h1 n:render="header"></h1>
<ul>
<li>Object Type: <span n:render="type" /></li>
<li>Storage Index: <tt n:render="si" /></li>
<li>Object Size: <span n:render="size" /></li>
- <li>Access Caps (URIs):
- <table border="1">
+ <li>Access Caps (Tahoe-URIs):
+ <table class="table-headings-left">
<span n:render="is_directory">
<tr>
- <td>Directory writecap</td>
- <td><tt n:render="directory_writecap" /></td>
+ <th>Directory writecap</th>
+ <td><tt class="data-chars" n:render="directory_writecap" /></td>
</tr>
<tr>
- <td>Directory readcap</td>
- <td><tt n:render="directory_readcap" /></td>
+ <th>Directory readcap</th>
+ <td><tt class="data-chars" n:render="directory_readcap" /></td>
</tr>
<tr>
- <td>Directory verifycap</td>
- <td><tt n:render="directory_verifycap" /></td>
+ <th>Directory verifycap</th>
+ <td><tt class="data-chars" n:render="directory_verifycap" /></td>
</tr>
</span>
<tr>
- <td>File writecap</td>
- <td><tt n:render="file_writecap" /></td>
+ <th>File writecap</th>
+ <td><tt class="data-chars" n:render="file_writecap" /></td>
</tr>
<tr>
- <td>File readcap</td>
- <td><tt n:render="file_readcap" /></td>
+ <th>File readcap</th>
+ <td><tt class="data-chars" n:render="file_readcap" /></td>
</tr>
<tr>
- <td>File verifycap</td>
- <td><tt n:render="file_verifycap" /></td>
+ <th>File verifycap</th>
+ <td><tt class="data-chars" n:render="file_verifycap" /></td>
</tr>
</table></li>
<li><a href="?t=json">JSON</a></li>
<div n:render="manifest_form" />
</div>
-
- </body>
-</html>
+</body></html>
<h2>Service Announcements</h2>
<div>
-<table n:render="sequence" n:data="services" border="1">
+<table n:render="sequence" n:data="services">
<tr n:pattern="header">
<td>PeerID / Nickname</td>
<td>Advertised IPs</td>
<h2>Subscribed Clients</h2>
<div>
-<table n:render="sequence" n:data="subscribers" border="1">
+<table n:render="sequence" n:data="subscribers">
<tr n:pattern="header">
<td>PeerID / Nickname</td>
<td>Advertised IPs</td>
def data_version(self, ctx, data):
return get_package_versions_string()
def data_import_path(self, ctx, data):
- return str(allmydata)
+ return str(allmydata).replace("/", "/ ") # XXX kludge for wrapping
def data_my_nodeid(self, ctx, data):
return idlib.nodeid_b2a(self.introducer_node.nodeid)
<h2 n:render="reload" />
-<table n:render="sequence" n:data="items" border="1">
+<table n:render="sequence" n:data="items">
<tr n:pattern="header">
<td>Path</td>
<td>cap</td>
</ul>
<div>
-<table n:render="sequence" n:data="simulation_table" border="1">
+<table n:render="sequence" n:data="simulation_table">
<tr n:pattern="header">
<td>t</td>
<td>P_repair</td>
TIME_FORMAT = "%H:%M:%S %d-%b-%Y"
ctx.fillSlots("connected", connected)
+ ctx.fillSlots("connected-bool", not not rsc.rref)
ctx.fillSlots("since", time.strftime(TIME_FORMAT, time.localtime(since)))
ctx.fillSlots("announced", time.strftime(TIME_FORMAT,
time.localtime(rsc.announcement_time)))
enctype="multipart/form-data")[
T.fieldset[
T.legend(class_="freeform-form-label")["Download a file"],
- "URI to download: ",
- T.input(type="text", name="uri"), " ",
- "Filename to download as: ",
- T.input(type="text", name="filename"), " ",
+ T.div["Tahoe-URI to download: ",
+ T.input(type="text", name="uri")],
+ T.div["Filename to download as: ",
+ T.input(type="text", name="filename")],
T.input(type="submit", value="Download!"),
]]
return T.div[form]
enctype="multipart/form-data")[
T.fieldset[
T.legend(class_="freeform-form-label")["View a file or directory"],
- "URI to view: ",
+ "Tahoe-URI to view: ",
T.input(type="text", name="uri"), " ",
T.input(type="submit", value="View!"),
]]
enctype="multipart/form-data")[
T.fieldset[
T.legend(class_="freeform-form-label")["Upload a file"],
- "Choose a file: ",
- T.input(type="file", name="file", class_="freeform-input-file"),
+ T.div["Choose a file: ",
+ T.input(type="file", name="file", class_="freeform-input-file")],
T.input(type="hidden", name="t", value="upload"),
- " Mutable?:", T.input(type="checkbox", name="mutable"),
- T.input(type="submit", value="Upload!"),
+ T.div[T.input(type="checkbox", name="mutable"), T.label(for_="mutable")["Create mutable file"],
+ " ", T.input(type="submit", value="Upload!")],
]]
return T.div[form]
form = T.form(action="uri", method="post",
enctype="multipart/form-data")[
T.fieldset[
- T.legend(class_="freeform-form-label")["Create a directory."],
+ T.legend(class_="freeform-form-label")["Create a directory"],
T.input(type="hidden", name="t", value="mkdir"),
T.input(type="hidden", name="redirect_to_result", value="true"),
- T.input(type="submit", value="create directory"),
+ T.input(type="submit", value="Create a directory"),
]]
return T.div[form]
<h2>Active Operations:</h2>
-<table n:render="sequence" n:data="active_operations" border="1">
+<table class="table-headings-top" n:render="sequence" n:data="active_operations">
<tr n:pattern="header">
- <td>Type</td>
- <td>Storage Index</td>
- <td>Helper?</td>
- <td>Total Size</td>
- <td>Progress</td>
- <td>Status</td>
+ <th>Type</th>
+ <th>Storage Index</th>
+ <th>Helper?</th>
+ <th>Total Size</th>
+ <th>Progress</th>
+ <th>Status</th>
</tr>
<tr n:pattern="item" n:render="row">
<td><n:slot name="type"/></td>
<h2>Recent Operations:</h2>
-<table n:render="sequence" n:data="recent_operations" border="1">
+<table class="table-headings-top" n:render="sequence" n:data="recent_operations">
<tr n:pattern="header">
- <td>Started</td>
- <td>Type</td>
- <td>Storage Index</td>
- <td>Helper?</td>
- <td>Total Size</td>
- <td>Progress</td>
- <td>Status</td>
+ <th>Started</th>
+ <th>Type</th>
+ <th>Storage Index</th>
+ <th>Helper?</th>
+ <th>Total Size</th>
+ <th>Progress</th>
+ <th>Status</th>
</tr>
<tr n:pattern="item" n:render="row">
<td><n:slot name="started"/></td>
<h1>Welcome To AllMyData "Tahoe"!</h1>
-<h2>Status of this Client</h2>
+<div class="section" id="this-client">
+ <h2>This Client</h2>
+
+ <p>
+ <a href="status/">Recent Uploads and Downloads</a>,
+ <a href="statistics">Operational Statistics</a>
+ </p>
+
+ <table class="node-info table-headings-left">
+ <tr><th>My nickname:</th> <td class="nickname mine" n:render="string" n:data="my_nickname" /></tr>
+ <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 code imported from:</th> <td n:render="string" n:data="import_path" /></tr>
+ <tr><th>Services running:</th> <td n:render="services" /></tr>
+ </table>
+
-<div>My nodeid: <span n:render="string" n:data="my_nodeid" /></div>
-<div>My nickname: <span n:render="string" n:data="my_nickname" /></div>
-<div>My versions: <span n:render="string" n:data="version" /></div>
-<div>Tahoe code imported from: <span n:render="string" n:data="import_path" /></div>
-<div n:render="services">Services Running:</div>
+</div>
+
+<div class="section" id="controls">
+<h2>Controls</h2>
-<div>
- <a href="status/">Recent Uploads and Downloads</a>,
- <a href="statistics">Operational Statistics</a>
+ <p>There are also controls for each directory on that directory's page.</p>
+
+ <div n:render="mkdir_form" />
+ <div n:render="view_form" />
+ <div n:render="upload_form" />
+ <div n:render="download_form" />
</div>
-<h2>The Controls</h2>
-
-<div>There are also controls for each directory on that directory's page.</div>
-
-<div n:render="mkdir_form" />
-<div n:render="view_form" />
-<div n:render="upload_form" />
-<div n:render="download_form" />
-
-
-<h2>Status of the Storage Grid</h2>
-
-<div>Introducer: <span n:render="string" n:data="introducer_furl" /></div>
-<div>Connected to introducer?: <span n:render="string" n:data="connected_to_introducer" /></div>
-
-<div>Helper: <span n:render="string" n:data="helper_furl" /></div>
-<div>Connected to helper?: <span n:render="string" n:data="connected_to_helper" /></div>
-
-<br />
-
-<div>Known Storage Servers: <span n:render="string" n:data="known_storage_servers" /></div>
-<div>Connected Storage Servers: <span n:render="string" n:data="connected_storage_servers" /></div>
-
-<div>
-<table n:render="sequence" n:data="services" border="1">
- <tr n:pattern="header">
- <td>PeerID</td>
- <td>Nickname</td>
- <td>Connected?</td>
- <td>Since</td>
- <td>Announced</td>
- <td>Version</td>
- <td>Service Name</td>
- </tr>
- <tr n:pattern="item" n:render="service_row">
- <td><tt><n:slot name="peerid"/></tt></td>
- <td><b><n:slot name="nickname"/></b></td>
- <td><tt><n:slot name="connected"/></tt></td>
- <td><tt><n:slot name="since"/></tt></td>
- <td><tt><n:slot name="announced"/></tt></td>
- <td><tt><n:slot name="version"/></tt></td>
- <td><tt><n:slot name="service_name"/></tt></td>
- </tr>
- <tr n:pattern="empty"><td>no peers!</td></tr>
-</table>
+<div class="section" id="grid">
+ <h2>Status of the Storage Grid</h2>
+
+ <div>
+ <n:attr name="class">connected-<n:invisible n:render="string" n:data="connected_to_introducer" /></n:attr>
+ <div>Introducer: <span class="data-chars" n:render="string" n:data="introducer_furl" /></div>
+ <div>Connected to introducer?: <span n:render="string" n:data="connected_to_introducer" /></div>
+ </div>
+
+ <div>
+ <n:attr name="class">connected-<n:invisible n:render="string" n:data="connected_to_helper" /></n:attr>
+ <div>Helper: <span n:render="string" n:data="helper_furl" /></div>
+ <div>Connected to helper?: <span n:render="string" n:data="connected_to_helper" /></div>
+ </div>
+
+ <p>Connected to <span n:render="string" n:data="connected_storage_servers" />
+ of <span n:render="string" n:data="known_storage_servers" /> known storage servers:</p>
+
+ <div>
+ <table class="services table-headings-top" n:render="sequence" n:data="services">
+ <tr n:pattern="header">
+ <th>Service Name</th>
+ <th class="nickname-and-peerid">
+ <div class="service-nickname">Nickname</div>
+ <div class="nodeid data-chars">PeerID</div></th>
+ <th>Connected?</th>
+ <th>since</th>
+ <th>First Announced</th>
+ <th>Version</th>
+ </tr>
+ <tr n:pattern="item" n:render="service_row">
+ <td class="service-service-name"><n:slot name="service_name"/></td>
+ <td class="nickname-and-peerid">
+ <div class="nickname"><n:slot name="nickname"/></div>
+ <div class="nodeid data-chars"><n:slot name="peerid"/></div></td>
+ <td>
+ <n:attr name="class">service-connected connected-<n:slot name="connected-bool"/></n:attr>
+ <n:slot name="connected"/>
+ </td>
+ <td class="service-since"> <n:slot name="since"/></td>
+ <td class="service-announced"> <n:slot name="announced"/></td>
+ <td class="service-version"> <n:slot name="version"/></td>
+ </tr>
+ <tr n:pattern="empty"><td>no peers!</td></tr>
+ </table>
+ </div>
</div>
-<h2>Other Resources</h2>
+<div class="section" id="other-resources">
+ <h2>Other Resources</h2>
-<div>Please visit the <a href="http://allmydata.org">Tahoe home page</a> for
-code updates and bug reporting.</div>
+ <div>Please visit the <a href="http://allmydata.org">Tahoe home page</a> for
+ code updates and bug reporting.</div>
-<div>The <a href="provisioning">provisioning tool</a> and <a
-href="reliability">reliability calculator</a> may also be useful.</div>
+ <div>The <a href="provisioning">provisioning tool</a> and <a
+ href="reliability">reliability calculator</a> may also be useful.</div>
-<div n:render="incident_button" />
+ <div n:render="incident_button" />
+</div>
- </body>
-</html>
+</body></html>