Ticket #692: tahoe-style-2.dpatch

File tahoe-style-2.dpatch, 48.5 KB (added by kpreid, at 2009-05-26T23:29:32Z)

Revised version with matching test changes.

Line 
1Fri May  1 15:10:50 EDT 2009  Kevin Reid <kpreid@mac.com>
2  * Fix broken link from Provisioning to Reliability page.
3
4Sun May  3 16:25:33 EDT 2009  Kevin Reid <kpreid@mac.com>
5  * Link all Tahoe web pages to the /tahoe_css stylesheet which already exists.
6
7Sun May  3 16:31:42 EDT 2009  Kevin Reid <kpreid@mac.com>
8  * Add CSS styles to spiff up the Tahoe WUI's appearance, particularly the welcome page and directories.
9
10Sun May  3 16:34:42 EDT 2009  Kevin Reid <kpreid@mac.com>
11  * Comment on duplication of code/markup found during styling project.
12
13Tue May 26 19:24:14 EDT 2009  Kevin Reid <kpreid@mac.com>
14  * Tweak wording in directory page: not-read-only is "modifiable", mention creating a directory _in this directory_.
15
16Tue May 26 19:25:45 EDT 2009  Kevin Reid <kpreid@mac.com>
17  * Modify markup of Tahoe web pages to be more amenable to styling; some minor changes of wording.
18
19New patches:
20
21[Fix broken link from Provisioning to Reliability page.
22Kevin Reid <kpreid@mac.com>**20090501191050
23 Ignore-this: 56dc1a5e659b70cc02dc4df7b5d518cd
24] hunk ./src/allmydata/provisioning.py 714
25             from allmydata import reliability
26             # we import this just to test to see if the page is available
27             _hush_pyflakes = reliability
28-            f = [T.div[T.a(href="reliability.html")["Reliability Math"]], f]
29+            f = [T.div[T.a(href="../reliability")["Reliability Math"]], f]
30         except ImportError:
31             pass
32 
33[Link all Tahoe web pages to the /tahoe_css stylesheet which already exists.
34Kevin Reid <kpreid@mac.com>**20090503202533
35 Ignore-this: 2ea8d14d3168b9502cf39d5ea3f2f2a8
36] {
37hunk ./src/allmydata/web/check-and-repair-results.xhtml 4
38 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
39   <head>
40     <title>AllMyData - Tahoe - Check Results</title>
41-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
42-          rel="stylesheet" type="text/css"/> -->
43+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
44     <link href="/webform_css" rel="stylesheet" type="text/css"/>
45     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
46   </head>
47hunk ./src/allmydata/web/check-results.xhtml 4
48 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
49   <head>
50     <title>AllMyData - Tahoe - Check Results</title>
51-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
52-          rel="stylesheet" type="text/css"/> -->
53+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
54     <link href="/webform_css" rel="stylesheet" type="text/css"/>
55     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
56   </head>
57hunk ./src/allmydata/web/deep-check-and-repair-results.xhtml 4
58 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
59   <head>
60     <title>AllMyData - Tahoe - Deep Check Results</title>
61-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
62-          rel="stylesheet" type="text/css"/> -->
63+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
64     <link href="/webform_css" rel="stylesheet" type="text/css"/>
65     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
66     <meta n:render="refresh" />
67hunk ./src/allmydata/web/deep-check-results.xhtml 4
68 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
69   <head>
70     <title>AllMyData - Tahoe - Deep Check Results</title>
71-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
72-          rel="stylesheet" type="text/css"/> -->
73+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
74     <link href="/webform_css" rel="stylesheet" type="text/css"/>
75     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
76     <meta n:render="refresh" />
77hunk ./src/allmydata/web/directory.xhtml 1
78-<html xmlns:n="http://nevow.com/ns/nevow/0.1">
79-  <head>
80-    <title n:render="title"></title>
81-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
82-          rel="stylesheet" type="text/css"/> -->
83-    <link href="/webform_css" rel="stylesheet" type="text/css"/>
84-    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
85-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
86-  </head>
87-  <body>
88+<html xmlns:n="http://nevow.com/ns/nevow/0.1"><head>
89+  <title n:render="title"></title>
90+  <link href="/webform_css" rel="stylesheet" type="text/css"/>
91+  <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
92+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
93+</head><body class="tahoe-directory-page">
94 
95 <h2 n:render="header"></h2>
96 
97hunk ./src/allmydata/web/download-status.xhtml 4
98 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
99   <head>
100     <title>AllMyData - Tahoe - File Download Status</title>
101-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
102-          rel="stylesheet" type="text/css"/> -->
103+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
104     <link href="/webform_css" rel="stylesheet" type="text/css"/>
105     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
106   </head>
107hunk ./src/allmydata/web/helper.xhtml 4
108 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
109   <head>
110     <title>Helper Status - AllMyData Tahoe</title>
111-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
112-          rel="stylesheet" type="text/css"/> -->
113+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
114     <link href="/webform_css" rel="stylesheet" type="text/css"/>
115     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
116   </head>
117hunk ./src/allmydata/web/info.xhtml 1
118-<html xmlns:n="http://nevow.com/ns/nevow/0.1">
119-  <head>
120-    <title n:render="title"></title>
121-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
122-          rel="stylesheet" type="text/css"/> -->
123-    <link href="/webform_css" rel="stylesheet" type="text/css"/>
124-    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
125-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
126-  </head>
127-  <body>
128+<html xmlns:n="http://nevow.com/ns/nevow/0.1"><head>
129+  <title n:render="title"></title>
130+  <!-- <link href="http://www.allmydata.com/common/css/styles.css"
131+        rel="stylesheet" type="text/css"/> -->
132+  <link href="/webform_css" rel="stylesheet" type="text/css"/>
133+  <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
134+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
135 
136 <h2 n:render="header"></h2>
137 
138hunk ./src/allmydata/web/literal-check-results.xhtml 4
139 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
140   <head>
141     <title>AllMyData - Tahoe - Check Results</title>
142-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
143-          rel="stylesheet" type="text/css"/> -->
144+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
145     <link href="/webform_css" rel="stylesheet" type="text/css"/>
146     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
147   </head>
148hunk ./src/allmydata/web/manifest.xhtml 4
149 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
150   <head>
151     <title n:render="title"></title>
152-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
153-          rel="stylesheet" type="text/css"/> -->
154+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
155     <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
156     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
157     <meta n:render="refresh" />
158hunk ./src/allmydata/web/map-update-status.xhtml 4
159 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
160   <head>
161     <title>AllMyData - Tahoe - Mutable File Servermap Update Status</title>
162-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
163-          rel="stylesheet" type="text/css"/> -->
164+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
165     <link href="/webform_css" rel="stylesheet" type="text/css"/>
166     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
167   </head>
168hunk ./src/allmydata/web/provisioning.xhtml 4
169 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
170   <head>
171     <title>AllMyData - Tahoe - Provisioning Tool</title>
172-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
173-          rel="stylesheet" type="text/css"/> -->
174+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
175     <link href="/webform_css" rel="stylesheet" type="text/css"/>
176     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
177   </head>
178hunk ./src/allmydata/web/publish-status.xhtml 4
179 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
180   <head>
181     <title>AllMyData - Tahoe - Mutable File Publish Status</title>
182-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
183-          rel="stylesheet" type="text/css"/> -->
184+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
185     <link href="/webform_css" rel="stylesheet" type="text/css"/>
186     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
187   </head>
188hunk ./src/allmydata/web/reliability.xhtml 4
189 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
190   <head>
191     <title>AllMyData - Tahoe - Reliability Tool</title>
192-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
193-          rel="stylesheet" type="text/css"/> -->
194+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
195     <link href="/webform_css" rel="stylesheet" type="text/css"/>
196     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
197   </head>
198hunk ./src/allmydata/web/rename-form.xhtml 4
199 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
200   <head>
201     <title n:render="title"></title>
202-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
203-          rel="stylesheet" type="text/css"/> -->
204+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
205     <link href="/webform_css" rel="stylesheet" type="text/css"/>
206     <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
207     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
208hunk ./src/allmydata/web/retrieve-status.xhtml 4
209 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
210   <head>
211     <title>AllMyData - Tahoe - Mutable File Retrieve Status</title>
212-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
213-          rel="stylesheet" type="text/css"/> -->
214+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
215     <link href="/webform_css" rel="stylesheet" type="text/css"/>
216     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
217   </head>
218hunk ./src/allmydata/web/statistics.xhtml 4
219 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
220   <head>
221     <title>Stats - AllMyData Tahoe</title>
222-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
223-          rel="stylesheet" type="text/css"/> -->
224+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
225     <link href="/webform_css" rel="stylesheet" type="text/css"/>
226     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
227   </head>
228hunk ./src/allmydata/web/status.xhtml 4
229 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
230   <head>
231     <title>AllMyData - Tahoe - Current Uploads/Downloads</title>
232-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
233-          rel="stylesheet" type="text/css"/> -->
234     <link href="/webform_css" rel="stylesheet" type="text/css"/>
235hunk ./src/allmydata/web/status.xhtml 5
236+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
237     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
238   </head>
239   <body>
240hunk ./src/allmydata/web/upload-results.xhtml 4
241 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
242   <head>
243     <title>AllMyData - Tahoe - File Uploaded</title>
244-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
245-          rel="stylesheet" type="text/css"/> -->
246+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
247     <link href="/webform_css" rel="stylesheet" type="text/css"/>
248     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
249   </head>
250hunk ./src/allmydata/web/upload-status.xhtml 4
251 <html xmlns:n="http://nevow.com/ns/nevow/0.1">
252   <head>
253     <title>AllMyData - Tahoe - File Upload Status</title>
254-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
255-          rel="stylesheet" type="text/css"/> -->
256+    <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
257     <link href="/webform_css" rel="stylesheet" type="text/css"/>
258     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
259   </head>
260hunk ./src/allmydata/web/welcome.xhtml 1
261-<html xmlns:n="http://nevow.com/ns/nevow/0.1">
262-  <head>
263-    <title>AllMyData - Tahoe</title>
264-    <!-- <link href="http://www.allmydata.com/common/css/styles.css"
265-          rel="stylesheet" type="text/css"/> -->
266-    <link href="/webform_css" rel="stylesheet" type="text/css"/>
267-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
268-  </head>
269-  <body>
270+<html xmlns:n="http://nevow.com/ns/nevow/0.1"><head>
271+  <title>AllMyData - Tahoe - Welcome</title>
272+  <link href="/webform_css" rel="stylesheet" type="text/css"/>
273+  <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
274+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
275+</head><body>
276 
277 <h1>Welcome To AllMyData "Tahoe"!</h1>
278 
279}
280[Add CSS styles to spiff up the Tahoe WUI's appearance, particularly the welcome page and directories.
281Kevin Reid <kpreid@mac.com>**20090503203142
282 Ignore-this: 5c50af241c1a958b5180ef2b6a49f626
283] hunk ./src/allmydata/web/tahoe.css 9
284                padding: .25em;
285                overflow: auto;
286                }
287+               
288+/* ----------------------------------------------------------------------- */
289+
290+/* colors borrowed from the Allmydata logo */
291+
292+/* general style */
293+h1 {
294+  text-align: center;
295+}
296+table {
297+  margin: 1em auto;
298+  border: .2em solid #3289b4;
299+  border-spacing: 1px;
300+}
301+th {
302+  color: white;
303+  background-color: #58a1c3;
304+}
305+td { padding: .3em .3em; }
306+th { padding: .3em .3em; }
307+.table-headings-top th { text-align: center; }
308+.table-headings-left th { text-align: right; vertical-align: top; }
309+legend {
310+  font-weight: bold;
311+}
312+
313+.connected-yes, .connected-True {
314+  border: 1px solid #75d24a;
315+  background-color: #EFE;
316+}
317+.connected-no, .connected-False {
318+  border: 1px solid #F00;
319+  background-color: #FBB;
320+}
321+
322+.encoded, .nodeid {
323+  font-family: monospace;
324+  font-size: 80%;
325+}
326+
327+.empty-marker {
328+  background-color: white;
329+  color: gray;
330+}
331+table td.empty-marker {
332+  padding: 6em 10em;
333+  text-align: center;
334+  vertical-align: center;
335+}
336+
337+/* styles for server listings in tables (nickname above nodeid) */
338+th.nickname-and-peerid {
339+  text-align: left;
340+}
341+.nickname {
342+  font: inherit;
343+  font-family: sans-serif;
344+  font-weight: bold;
345+}
346+
347+
348+/* just in case, make sure floats don't stomp on big tables etc. */
349+#section { clear: both; }
350+
351+/* section-specific styles - turn this client info into a sidebar */
352+#this-client {
353+  font-size: 60%;
354+  border: .2em solid #3289b4;
355+  float: right;
356+  width: 40%;
357+  margin: 0 0 .5em .5em;
358+  padding: 3px;
359+}
360+#this-client .nodeid { font-size: inherit; }
361+#this-client h2 {
362+  text-align: center;
363+  background: #3289b4;
364+  color: white;
365+  margin: -2px -2px 0 -2px; /* matches padding */
366+  padding: .3em;
367+}
368+#this-client table {
369+  font-size: inherit;
370+  margin: 0 -3px -3px -3px; /* matches padding */
371+}
372+#this-client td > ul {
373+  list-style-type: outside;
374+  margin: 0 0 0 2.3em;
375+  padding-left: 0;
376+}
377+
378+
379+/* services table */
380+.services {
381+}
382+
383+/* --- Directory page styles --- */
384+
385+body.tahoe-directory-page {
386+  color: black;
387+  background: #c0d9e6;
388+  margin: 1em 0; /* zero margin so the table can be flush */
389+}
390+table.tahoe-directory {
391+  color: black;
392+  background: white;
393+  width: 100%;
394+  /*border-left-color: #D7E0E5;
395+  border-right-color: #D7E0E5;*/
396+  border-left: 0;
397+  border-right: 0;
398+}
399+.tahoe-directory-footer {
400+  color: black;
401+  background: #c0d9e6;
402+  margin: 0 1em; /* compensate for page 0 margin */
403+}
404+
405+/* directory-screen toolbar */
406+.toolbar {
407+  display: table;
408+  margin: .2em auto;
409+  /*width: 100%;*/
410+}
411+.toolbar .toolbar-item {
412+  display: table-cell;
413+  text-align: center;
414+  padding: 0 1em;
415+}
416[Comment on duplication of code/markup found during styling project.
417Kevin Reid <kpreid@mac.com>**20090503203442
418 Ignore-this: a4b7f9f0ab57d2c03be9ba761be8d854
419] {
420hunk ./src/allmydata/web/check_results.py 112
421         sharemap = []
422         servers = {}
423 
424+        # FIXME: The two tables below contain nickname-and-nodeid table column markup which is duplicated with each other, introducer.xhtml, and deep-check-results.xhtml. All of these (and any other presentations of nickname-and-nodeid) should be combined.
425+
426         for shareid in sorted(data["sharemap"].keys()):
427             serverids = data["sharemap"][shareid]
428             for i,serverid in enumerate(serverids):
429hunk ./src/allmydata/web/introweb.py 67
430 
431         return simplejson.dumps(res, indent=1) + "\n"
432 
433+    # FIXME: This code is duplicated in root.py and introweb.py.
434     def data_version(self, ctx, data):
435         return get_package_versions_string()
436     def data_import_path(self, ctx, data):
437hunk ./src/allmydata/web/root.py 180
438     child_report_incident = IncidentReporter()
439     #child_server # let's reserve this for storage-server-over-HTTP
440 
441+    # FIXME: This code is duplicated in root.py and introweb.py.
442     def data_version(self, ctx, data):
443         return get_package_versions_string()
444     def data_import_path(self, ctx, data):
445}
446[Tweak wording in directory page: not-read-only is "modifiable", mention creating a directory _in this directory_.
447Kevin Reid <kpreid@mac.com>**20090526232414
448 Ignore-this: f006ec52ba2051802e025a60bcface56
449] {
450hunk ./src/allmydata/test/test_web.py 916
451         d.addCallback(lambda res:
452                       self.GET(self.public_url + "/reedownlee", followRedirect=True))
453         def _check2(res):
454-            self.failUnless("(readonly)" in res, res)
455+            self.failUnless("(read-only)" in res, res)
456             self.failIf("Upload a file" in res, res)
457         d.addCallback(_check2)
458 
459hunk ./src/allmydata/test/test_web.py 932
460         d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty/"))
461         def _check4(res):
462             self.failUnless("directory is empty" in res, res)
463-            MKDIR_BUTTON_RE=re.compile('<input type="hidden" name="t" value="mkdir" />.*<legend class="freeform-form-label">Create a new directory</legend>.*<input type="submit" value="Create" />', re.I)
464+            MKDIR_BUTTON_RE=re.compile('<input type="hidden" name="t" value="mkdir" />.*<legend class="freeform-form-label">Create a new directory in this directory</legend>.*<input type="submit" value="Create" />', re.I)
465             self.failUnless(MKDIR_BUTTON_RE.search(res), res)
466         d.addCallback(_check4)
467 
468hunk ./src/allmydata/web/directory.py 527
469 
470     def render_title(self, ctx, data):
471         si_s = abbreviated_dirnode(self.node)
472-        header = ["Directory SI=%s" % si_s]
473+        header = ["AllMyData - Tahoe - Directory SI=%s" % si_s]
474+        if self.node.is_readonly():
475+            header.append(" (read-only)")
476+        else:
477+            header.append(" (modifiable)")
478         return ctx.tag[header]
479 
480     def render_header(self, ctx, data):
481hunk ./src/allmydata/web/directory.py 538
482         si_s = abbreviated_dirnode(self.node)
483         header = ["Directory SI=%s" % si_s]
484         if self.node.is_readonly():
485-            header.append(" (readonly)")
486+            header.append(" (read-only)")
487         return ctx.tag[header]
488 
489     def render_welcome(self, ctx, data):
490hunk ./src/allmydata/web/directory.py 681
491             T.fieldset[
492             T.input(type="hidden", name="t", value="mkdir"),
493             T.input(type="hidden", name="when_done", value="."),
494-            T.legend(class_="freeform-form-label")["Create a new directory"],
495+            T.legend(class_="freeform-form-label")["Create a new directory in this directory"],
496             "New directory name: ",
497             T.input(type="text", name="name"), " ",
498             T.input(type="submit", value="Create"),
499}
500[Modify markup of Tahoe web pages to be more amenable to styling; some minor changes of wording.
501Kevin Reid <kpreid@mac.com>**20090526232545
502 Ignore-this: 8845937f0df6c7ddc07abe3211428a6f
503] {
504hunk ./src/allmydata/test/test_checker.py 106
505         s = self.remove_tags(html)
506         self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
507         self.failUnlessIn("Not Recoverable! : rather dead", s)
508-        self.failUnlessIn("Corrupt shares: sh#2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (peer-0)", s)
509+        self.failUnlessIn("Corrupt shares: Share ID Nickname Node ID sh#2 peer-0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", s)
510 
511         html = self.render2(w)
512         s = self.remove_tags(html)
513hunk ./src/allmydata/test/test_system.py 1104
514         public = "uri/" + self._root_directory_uri
515         d = getPage(base)
516         def _got_welcome(page):
517-            expected = "Connected Storage Servers: <span>%d</span>" % (self.numclients)
518+            # XXX This test is oversensitive to formatting
519+            expected = "Connected to <span>%d</span>\n     of <span>%d</span> known storage servers:" % (self.numclients, self.numclients)
520             self.failUnless(expected in page,
521                             "I didn't see the right 'connected storage servers'"
522                             " message in: %s" % page
523hunk ./src/allmydata/test/test_system.py 1110
524                             )
525-            expected = "My nodeid: <span>%s</span>" % (b32encode(self.clients[0].nodeid).lower(),)
526+            expected = "<th>My nodeid:</th> <td class=\"nodeid mine data-chars\">%s</td>" % (b32encode(self.clients[0].nodeid).lower(),)
527             self.failUnless(expected in page,
528                             "I didn't see the right 'My nodeid' message "
529                             "in: %s" % page)
530hunk ./src/allmydata/test/test_web.py 882
531             # the FILE reference points to a URI, but it should end in bar.txt
532             bar_url = ("%s/file/%s/@@named=/bar.txt" %
533                        (ROOT, urllib.quote(self._bar_txt_uri)))
534-            get_bar = "".join([r'<td>',
535+            get_bar = "".join([r'<td>FILE</td>',
536+                               r'\s+<td>',
537                                r'<a href="%s">bar.txt</a>' % bar_url,
538                                r'</td>',
539hunk ./src/allmydata/test/test_web.py 886
540-                               r'\s+<td>FILE</td>',
541                                r'\s+<td>%d</td>' % len(self.BAR_CONTENTS),
542                                ])
543             self.failUnless(re.search(get_bar, res), res)
544hunk ./src/allmydata/test/test_web.py 907
545 
546             # the DIR reference just points to a URI
547             sub_url = ("%s/uri/%s/" % (ROOT, urllib.quote(self._sub_uri)))
548-            get_sub = ((r'<td><a href="%s">sub</a></td>' % sub_url)
549-                       + r'\s+<td>DIR</td>')
550+            get_sub = ((r'<td>DIR</td>')
551+                       +r'\s+<td><a href="%s">sub</a></td>' % sub_url)
552             self.failUnless(re.search(get_sub, res), res)
553         d.addCallback(_check)
554 
555hunk ./src/allmydata/test/test_web.py 924
556         d.addCallback(lambda res:
557                       self.GET(self.public_url, followRedirect=True))
558         def _check3(res):
559-            self.failUnless(re.search(r'<td><a href="[\.\/]+/uri/URI%3ADIR2-RO%3A[^"]+">reedownlee</a>'
560-                                      '</td>\s+<td>DIR-RO</td>', res))
561+            self.failUnless(re.search('<td>DIR-RO</td>'
562+                                      r'\s+<td><a href="[\.\/]+/uri/URI%3ADIR2-RO%3A[^"]+">reedownlee</a></td>', res), res)
563         d.addCallback(_check3)
564 
565         # and an empty directory
566hunk ./src/allmydata/test/test_web.py 1898
567         # Fetch the welcome page.
568         d = self.GET("/")
569         def _after_get_welcome_page(res):
570-            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)
571+            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)
572             mo = MKDIR_BUTTON_RE.search(res)
573             formaction = mo.group(1)
574             formt = mo.group(2)
575hunk ./src/allmydata/web/check_results.py 100
576             for (serverid, si, shnum) in data["list-corrupt-shares"]:
577                 nickname = c.get_nickname_for_peerid(serverid)
578                 badsharemap.append(T.tr[T.td["sh#%d" % shnum],
579-                                        T.td[T.tt[base32.b2a(serverid)],
580-                                             " (", nickname, ")"],
581+                                        T.td[T.div(class_="nickname")[nickname],
582+                                              T.div(class_="nodeid")[T.tt[base32.b2a(serverid)]]],
583                                         ])
584hunk ./src/allmydata/web/check_results.py 103
585-            add("Corrupt shares", T.table(border="1")[badsharemap])
586+            add("Corrupt shares", T.table()[
587+                T.tr[T.th["Share ID"],
588+                     T.th(class_="nickname-and-peerid")[T.div["Nickname"], T.div(class_="nodeid")["Node ID"]]],
589+                badsharemap])
590         else:
591             add("Corrupt shares", "none")
592 
593hunk ./src/allmydata/web/check_results.py 128
594                     shareid_s = shareid
595                 nickname = c.get_nickname_for_peerid(serverid)
596                 sharemap.append(T.tr[T.td[shareid_s],
597-                                     T.td[T.tt[base32.b2a(serverid)],
598-                                          " (", nickname, ")"],
599+                                     T.td[T.div(class_="nickname")[nickname],
600+                                          T.div(class_="nodeid")[T.tt[base32.b2a(serverid)]]]
601                                      ])
602         add("Good Shares (sorted in share order)",
603hunk ./src/allmydata/web/check_results.py 132
604-            T.table(border="1")[sharemap])
605+            T.table()[T.tr[T.th["Share ID"], T.th(class_="nickname-and-peerid")[T.div["Nickname"], T.div(class_="nodeid")["Node ID"]]],
606+                      sharemap])
607 
608 
609         add("Recoverable Versions", data["count-recoverable-versions"])
610hunk ./src/allmydata/web/check_results.py 152
611             shareids = servers.get(serverid, [])
612             shareids.reverse()
613             shareids_s = [ T.tt[shareid, " "] for shareid in sorted(shareids) ]
614-            servermap.append(T.tr[T.td[T.tt[base32.b2a(serverid)],
615-                                       " (", nickname, ")"],
616-                                  T.td[shareids_s] ])
617+            servermap.append(T.tr[T.td[T.div(class_="nickname")[nickname],
618+                                       T.div(class_="nodeid")[T.tt[base32.b2a(serverid)]]],
619+                                  T.td[shareids_s],
620+                                  ])
621             num_shares_left -= len(shareids)
622             if not num_shares_left:
623                 break
624hunk ./src/allmydata/web/check_results.py 160
625         add("Share Balancing (servers in permuted order)",
626-            T.table(border="1")[servermap])
627+            T.table()[T.tr[T.th(class_="nickname-and-peerid")[T.div["Nickname"], T.div(class_="nodeid")["Node ID"]], T.th["Share IDs"]],
628+                      servermap])
629 
630         return T.ul[r]
631 
632hunk ./src/allmydata/web/deep-check-and-repair-results.xhtml 72
633 <div n:render="return" />
634 
635 <div>
636-<table n:render="sequence" n:data="all_objects" border="1">
637+<table n:render="sequence" n:data="all_objects">
638   <tr n:pattern="header">
639     <td>Relative Path</td>
640     <td>Healthy Pre-Repair</td>
641hunk ./src/allmydata/web/deep-check-results.xhtml 46
642 <div n:render="corrupt_shares_p">
643 <h2>Corrupt Shares</h2>
644 <p>If repair fails, these shares need to be manually inspected and removed.</p>
645-<table n:render="sequence" n:data="corrupt_shares" border="1">
646+<table n:render="sequence" n:data="corrupt_shares">
647   <tr n:pattern="header">
648     <td>Server</td>
649     <td>Server Nickname</td>
650hunk ./src/allmydata/web/deep-check-results.xhtml 66
651 
652 <div>
653 <h2>All Results</h2>
654-<table n:render="sequence" n:data="all_objects" border="1">
655+<table n:render="sequence" n:data="all_objects">
656   <tr n:pattern="header">
657     <td>Relative Path</td>
658     <td>Healthy</td>
659hunk ./src/allmydata/web/directory.py 536
660 
661     def render_header(self, ctx, data):
662         si_s = abbreviated_dirnode(self.node)
663-        header = ["Directory SI=%s" % si_s]
664+        header = ["Directory SI=", T.span(class_="data-chars")[si_s]]
665         if self.node.is_readonly():
666             header.append(" (read-only)")
667         return ctx.tag[header]
668hunk ./src/allmydata/web/directory.xhtml 8
669   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
670 </head><body class="tahoe-directory-page">
671 
672-<h2 n:render="header"></h2>
673+<h1 n:render="header"></h1>
674 
675hunk ./src/allmydata/web/directory.xhtml 10
676-<div><a href=".">Refresh this view</a></div>
677-<div n:render="welcome" />
678+<div class="toolbar">
679+  <div class="toolbar-item" n:render="welcome" />
680+  <div class="toolbar-item"><a href=".">Refresh</a></div>
681 
682hunk ./src/allmydata/web/directory.xhtml 14
683-<div><a href="?t=info">More info on this directory</a></div>
684-<div n:render="show_readonly" />
685+  <div class="toolbar-item"><a href="?t=info">More info on this directory</a></div>
686+  <div class="toolbar-item" n:render="show_readonly" />
687+</div>
688 
689 <div n:render="try_children">
690hunk ./src/allmydata/web/directory.xhtml 19
691-<table n:render="sequence" n:data="children" border="1">
692-  <tr n:pattern="header">
693-    <td>Filename</td>
694-    <td>Type</td>
695-    <td>Size</td>
696-    <td>Times</td>
697-    <td></td>
698-    <td></td>
699-    <td></td>
700-  </tr>
701-  <tr n:pattern="item" n:render="row">
702-    <td><n:slot name="filename"/></td>
703-    <td><n:slot name="type"/></td>
704-    <td><n:slot name="size"/></td>
705-    <td><n:slot name="times"/></td>
706-    <td><n:slot name="delete"/></td>
707-    <td><n:slot name="rename"/></td>
708-    <td><n:slot name="info"/></td>
709-  </tr>
710+  <table class="tahoe-directory" n:render="sequence" n:data="children">
711+    <tr n:pattern="header">
712+      <th>Type</th>
713+      <th>Filename</th>
714+      <th>Size</th>
715+      <th>Times</th>
716+      <th></th>
717+      <th></th>
718+      <th></th>
719+    </tr>
720+    <tr n:pattern="item" n:render="row">
721+      <td><n:slot name="type"/></td>
722+      <td><n:slot name="filename"/></td>
723+      <td><n:slot name="size"/></td>
724+      <td><n:slot name="times"/></td>
725+      <td><n:slot name="delete"/></td>
726+      <td><n:slot name="rename"/></td>
727+      <td><n:slot name="info"/></td>
728+    </tr>
729 
730hunk ./src/allmydata/web/directory.xhtml 39
731-  <tr n:pattern="empty"><td>directory is empty</td></tr>
732+    <tr n:pattern="empty"><td colspan="9" class="empty-marker">This directory is empty.</td></tr>
733 
734hunk ./src/allmydata/web/directory.xhtml 41
735-</table>
736+  </table>
737 </div>
738 
739hunk ./src/allmydata/web/directory.xhtml 44
740+<div class="tahoe-directory-footer">
741+  <div n:render="forms"/>
742 
743hunk ./src/allmydata/web/directory.xhtml 47
744-<div n:render="forms"/>
745-
746-<div class="results" n:render="results"/>
747+  <div class="results" n:render="results"/>
748+</div>
749 
750hunk ./src/allmydata/web/directory.xhtml 50
751-  </body>
752-</html>
753+</body></html>
754hunk ./src/allmydata/web/info.xhtml 9
755   <link href="/tahoe_css" rel="stylesheet" type="text/css"/>
756   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
757 
758-<h2 n:render="header"></h2>
759+</head><body>
760+
761+<h1 n:render="header"></h1>
762 
763 <ul>
764   <li>Object Type: <span n:render="type" /></li>
765hunk ./src/allmydata/web/info.xhtml 17
766   <li>Storage Index: <tt n:render="si" /></li>
767   <li>Object Size: <span n:render="size" /></li>
768-  <li>Access Caps (URIs):
769-  <table border="1">
770+  <li>Access Caps (Tahoe-URIs):
771+  <table class="table-headings-left">
772     <span n:render="is_directory">
773     <tr>
774hunk ./src/allmydata/web/info.xhtml 21
775-      <td>Directory writecap</td>
776-      <td><tt n:render="directory_writecap" /></td>
777+      <th>Directory writecap</th>
778+      <td><tt class="data-chars" n:render="directory_writecap" /></td>
779     </tr>
780     <tr>
781hunk ./src/allmydata/web/info.xhtml 25
782-      <td>Directory readcap</td>
783-      <td><tt n:render="directory_readcap" /></td>
784+      <th>Directory readcap</th>
785+      <td><tt class="data-chars" n:render="directory_readcap" /></td>
786     </tr>
787     <tr>
788hunk ./src/allmydata/web/info.xhtml 29
789-      <td>Directory verifycap</td>
790-      <td><tt n:render="directory_verifycap" /></td>
791+      <th>Directory verifycap</th>
792+      <td><tt class="data-chars" n:render="directory_verifycap" /></td>
793     </tr>
794     </span>
795 
796hunk ./src/allmydata/web/info.xhtml 35
797     <tr>
798-      <td>File writecap</td>
799-      <td><tt n:render="file_writecap" /></td>
800+      <th>File writecap</th>
801+      <td><tt class="data-chars" n:render="file_writecap" /></td>
802     </tr>
803     <tr>
804hunk ./src/allmydata/web/info.xhtml 39
805-      <td>File readcap</td>
806-      <td><tt n:render="file_readcap" /></td>
807+      <th>File readcap</th>
808+      <td><tt class="data-chars" n:render="file_readcap" /></td>
809     </tr>
810     <tr>
811hunk ./src/allmydata/web/info.xhtml 43
812-      <td>File verifycap</td>
813-      <td><tt n:render="file_verifycap" /></td>
814+      <th>File verifycap</th>
815+      <td><tt class="data-chars" n:render="file_verifycap" /></td>
816     </tr>
817   </table></li>
818   <li><a href="?t=json">JSON</a></li>
819hunk ./src/allmydata/web/info.xhtml 69
820   <div n:render="manifest_form" />
821 </div>
822 
823-
824-  </body>
825-</html>
826+</body></html>
827hunk ./src/allmydata/web/introducer.xhtml 24
828 <h2>Service Announcements</h2>
829 
830 <div>
831-<table n:render="sequence" n:data="services" border="1">
832+<table n:render="sequence" n:data="services">
833   <tr n:pattern="header">
834     <td>PeerID / Nickname</td>
835     <td>Advertised IPs</td>
836hunk ./src/allmydata/web/introducer.xhtml 46
837 <h2>Subscribed Clients</h2>
838 
839 <div>
840-<table n:render="sequence" n:data="subscribers" border="1">
841+<table n:render="sequence" n:data="subscribers">
842   <tr n:pattern="header">
843     <td>PeerID / Nickname</td>
844     <td>Advertised IPs</td>
845hunk ./src/allmydata/web/introweb.py 71
846     def data_version(self, ctx, data):
847         return get_package_versions_string()
848     def data_import_path(self, ctx, data):
849-        return str(allmydata)
850+        return str(allmydata).replace("/", "/ ") # XXX kludge for wrapping
851     def data_my_nodeid(self, ctx, data):
852         return idlib.nodeid_b2a(self.introducer_node.nodeid)
853 
854hunk ./src/allmydata/web/manifest.xhtml 15
855 
856 <h2 n:render="reload" />
857 
858-<table n:render="sequence" n:data="items" border="1">
859+<table n:render="sequence" n:data="items">
860   <tr n:pattern="header">
861     <td>Path</td>
862     <td>cap</td>
863hunk ./src/allmydata/web/reliability.xhtml 45
864 </ul>
865 
866 <div>
867-<table n:render="sequence" n:data="simulation_table" border="1">
868+<table n:render="sequence" n:data="simulation_table">
869   <tr n:pattern="header">
870     <td>t</td>
871     <td>P_repair</td>
872hunk ./src/allmydata/web/root.py 279
873 
874         TIME_FORMAT = "%H:%M:%S %d-%b-%Y"
875         ctx.fillSlots("connected", connected)
876+        ctx.fillSlots("connected-bool", not not rsc.rref)
877         ctx.fillSlots("since", time.strftime(TIME_FORMAT, time.localtime(since)))
878         ctx.fillSlots("announced", time.strftime(TIME_FORMAT,
879                                                  time.localtime(rsc.announcement_time)))
880hunk ./src/allmydata/web/root.py 294
881                       enctype="multipart/form-data")[
882             T.fieldset[
883             T.legend(class_="freeform-form-label")["Download a file"],
884-            "URI to download: ",
885-            T.input(type="text", name="uri"), " ",
886-            "Filename to download as: ",
887-            T.input(type="text", name="filename"), " ",
888+            T.div["Tahoe-URI to download: ",
889+                  T.input(type="text", name="uri")],
890+            T.div["Filename to download as: ",
891+                  T.input(type="text", name="filename")],
892             T.input(type="submit", value="Download!"),
893             ]]
894         return T.div[form]
895hunk ./src/allmydata/web/root.py 309
896                       enctype="multipart/form-data")[
897             T.fieldset[
898             T.legend(class_="freeform-form-label")["View a file or directory"],
899-            "URI to view: ",
900+            "Tahoe-URI to view: ",
901             T.input(type="text", name="uri"), " ",
902             T.input(type="submit", value="View!"),
903             ]]
904hunk ./src/allmydata/web/root.py 321
905                       enctype="multipart/form-data")[
906             T.fieldset[
907             T.legend(class_="freeform-form-label")["Upload a file"],
908-            "Choose a file: ",
909-            T.input(type="file", name="file", class_="freeform-input-file"),
910+            T.div["Choose a file: ",
911+                  T.input(type="file", name="file", class_="freeform-input-file")],
912             T.input(type="hidden", name="t", value="upload"),
913hunk ./src/allmydata/web/root.py 324
914-            " Mutable?:", T.input(type="checkbox", name="mutable"),
915-            T.input(type="submit", value="Upload!"),
916+            T.div[T.input(type="checkbox", name="mutable"), T.label(for_="mutable")["Create mutable file"],
917+                  " ", T.input(type="submit", value="Upload!")],
918             ]]
919         return T.div[form]
920 
921hunk ./src/allmydata/web/root.py 334
922         form = T.form(action="uri", method="post",
923                       enctype="multipart/form-data")[
924             T.fieldset[
925-            T.legend(class_="freeform-form-label")["Create a directory."],
926+            T.legend(class_="freeform-form-label")["Create a directory"],
927             T.input(type="hidden", name="t", value="mkdir"),
928             T.input(type="hidden", name="redirect_to_result", value="true"),
929hunk ./src/allmydata/web/root.py 337
930-            T.input(type="submit", value="create directory"),
931+            T.input(type="submit", value="Create a directory"),
932             ]]
933         return T.div[form]
934 
935hunk ./src/allmydata/web/status.xhtml 14
936 
937 
938 <h2>Active Operations:</h2>
939-<table n:render="sequence" n:data="active_operations" border="1">
940+<table class="table-headings-top" n:render="sequence" n:data="active_operations">
941   <tr n:pattern="header">
942hunk ./src/allmydata/web/status.xhtml 16
943-    <td>Type</td>
944-    <td>Storage Index</td>
945-    <td>Helper?</td>
946-    <td>Total Size</td>
947-    <td>Progress</td>
948-    <td>Status</td>
949+    <th>Type</th>
950+    <th>Storage Index</th>
951+    <th>Helper?</th>
952+    <th>Total Size</th>
953+    <th>Progress</th>
954+    <th>Status</th>
955   </tr>
956   <tr n:pattern="item" n:render="row">
957     <td><n:slot name="type"/></td>
958hunk ./src/allmydata/web/status.xhtml 36
959 
960 
961 <h2>Recent Operations:</h2>
962-<table n:render="sequence" n:data="recent_operations" border="1">
963+<table class="table-headings-top" n:render="sequence" n:data="recent_operations">
964   <tr n:pattern="header">
965hunk ./src/allmydata/web/status.xhtml 38
966-    <td>Started</td>
967-    <td>Type</td>
968-    <td>Storage Index</td>
969-    <td>Helper?</td>
970-    <td>Total Size</td>
971-    <td>Progress</td>
972-    <td>Status</td>
973+    <th>Started</th>
974+    <th>Type</th>
975+    <th>Storage Index</th>
976+    <th>Helper?</th>
977+    <th>Total Size</th>
978+    <th>Progress</th>
979+    <th>Status</th>
980   </tr>
981   <tr n:pattern="item" n:render="row">
982     <td><n:slot name="started"/></td>
983hunk ./src/allmydata/web/welcome.xhtml 10
984 
985 <h1>Welcome To AllMyData "Tahoe"!</h1>
986 
987-<h2>Status of this Client</h2>
988+<div class="section" id="this-client">
989+  <h2>This Client</h2>
990 
991hunk ./src/allmydata/web/welcome.xhtml 13
992-<div>My nodeid: <span n:render="string" n:data="my_nodeid" /></div>
993-<div>My nickname: <span n:render="string" n:data="my_nickname" /></div>
994-<div>My versions: <span n:render="string" n:data="version" /></div>
995-<div>Tahoe code imported from: <span n:render="string" n:data="import_path" /></div>
996-<div n:render="services">Services Running:</div>
997+  <p>
998+    <a href="status/">Recent Uploads and Downloads</a>,
999+    <a href="statistics">Operational Statistics</a>
1000+  </p>
1001 
1002hunk ./src/allmydata/web/welcome.xhtml 18
1003-<div>
1004-  <a href="status/">Recent Uploads and Downloads</a>,
1005-  <a href="statistics">Operational Statistics</a>
1006-</div>
1007-
1008-<h2>The Controls</h2>
1009+  <table class="node-info table-headings-left">
1010+    <tr><th>My nickname:</th> <td class="nickname mine" n:render="string" n:data="my_nickname" /></tr>
1011+    <tr><th>My nodeid:</th> <td class="nodeid mine data-chars" n:render="string" n:data="my_nodeid" /></tr>
1012+    <tr><th>My versions:</th> <td n:render="string" n:data="version" /></tr>
1013+    <tr><th>Tahoe code imported from:</th> <td n:render="string" n:data="import_path" /></tr>
1014+    <tr><th>Services running:</th> <td n:render="services" /></tr>
1015+  </table>
1016
1017 
1018hunk ./src/allmydata/web/welcome.xhtml 27
1019-<div>There are also controls for each directory on that directory's page.</div>
1020+</div>
1021 
1022hunk ./src/allmydata/web/welcome.xhtml 29
1023-<div n:render="mkdir_form" />
1024-<div n:render="view_form" />
1025-<div n:render="upload_form" />
1026-<div n:render="download_form" />
1027+<div class="section" id="controls">
1028+<h2>Controls</h2>
1029 
1030hunk ./src/allmydata/web/welcome.xhtml 32
1031+  <p>There are also controls for each directory on that directory's page.</p>
1032 
1033hunk ./src/allmydata/web/welcome.xhtml 34
1034-<h2>Status of the Storage Grid</h2>
1035+  <div n:render="mkdir_form" />
1036+  <div n:render="view_form" />
1037+  <div n:render="upload_form" />
1038+  <div n:render="download_form" />
1039+</div>
1040 
1041hunk ./src/allmydata/web/welcome.xhtml 40
1042-<div>Introducer: <span n:render="string" n:data="introducer_furl" /></div>
1043-<div>Connected to introducer?: <span n:render="string" n:data="connected_to_introducer" /></div>
1044+<div class="section" id="grid">
1045+  <h2>Status of the Storage Grid</h2>
1046 
1047hunk ./src/allmydata/web/welcome.xhtml 43
1048-<div>Helper: <span n:render="string" n:data="helper_furl" /></div>
1049-<div>Connected to helper?: <span n:render="string" n:data="connected_to_helper" /></div>
1050+  <div>
1051+    <n:attr name="class">connected-<n:invisible n:render="string" n:data="connected_to_introducer" /></n:attr>
1052+    <div>Introducer: <span class="data-chars" n:render="string" n:data="introducer_furl" /></div>
1053+    <div>Connected to introducer?: <span n:render="string" n:data="connected_to_introducer" /></div>
1054+  </div>
1055 
1056hunk ./src/allmydata/web/welcome.xhtml 49
1057-<br />
1058+  <div>
1059+    <n:attr name="class">connected-<n:invisible n:render="string" n:data="connected_to_helper" /></n:attr>
1060+    <div>Helper: <span n:render="string" n:data="helper_furl" /></div>
1061+    <div>Connected to helper?: <span n:render="string" n:data="connected_to_helper" /></div>
1062+  </div>
1063 
1064hunk ./src/allmydata/web/welcome.xhtml 55
1065-<div>Known Storage Servers: <span n:render="string" n:data="known_storage_servers" /></div>
1066-<div>Connected Storage Servers: <span n:render="string" n:data="connected_storage_servers" /></div>
1067+  <p>Connected to <span n:render="string" n:data="connected_storage_servers" />
1068+     of <span n:render="string" n:data="known_storage_servers" /> known storage servers:</p>
1069 
1070hunk ./src/allmydata/web/welcome.xhtml 58
1071-<div>
1072-<table n:render="sequence" n:data="services" border="1">
1073-  <tr n:pattern="header">
1074-    <td>PeerID</td>
1075-    <td>Nickname</td>
1076-    <td>Connected?</td>
1077-    <td>Since</td>
1078-    <td>Announced</td>
1079-    <td>Version</td>
1080-    <td>Service Name</td>
1081-  </tr>
1082-  <tr n:pattern="item" n:render="service_row">
1083-    <td><tt><n:slot name="peerid"/></tt></td>
1084-    <td><b><n:slot name="nickname"/></b></td>
1085-    <td><tt><n:slot name="connected"/></tt></td>
1086-    <td><tt><n:slot name="since"/></tt></td>
1087-    <td><tt><n:slot name="announced"/></tt></td>
1088-    <td><tt><n:slot name="version"/></tt></td>
1089-    <td><tt><n:slot name="service_name"/></tt></td>
1090-  </tr>
1091-  <tr n:pattern="empty"><td>no peers!</td></tr>
1092-</table>
1093+  <div>
1094+    <table class="services table-headings-top" n:render="sequence" n:data="services">
1095+      <tr n:pattern="header">
1096+        <th>Service Name</th>
1097+        <th class="nickname-and-peerid">
1098+            <div class="service-nickname">Nickname</div>
1099+            <div class="nodeid data-chars">PeerID</div></th>
1100+        <th>Connected?</th>
1101+        <th>since</th>
1102+        <th>First Announced</th>
1103+        <th>Version</th>
1104+      </tr>
1105+      <tr n:pattern="item" n:render="service_row">
1106+        <td class="service-service-name"><n:slot name="service_name"/></td>
1107+        <td class="nickname-and-peerid">
1108+          <div class="nickname"><n:slot name="nickname"/></div>
1109+          <div class="nodeid data-chars"><n:slot name="peerid"/></div></td>
1110+        <td>   
1111+          <n:attr name="class">service-connected connected-<n:slot name="connected-bool"/></n:attr>
1112+          <n:slot name="connected"/>
1113+        </td>
1114+        <td class="service-since">       <n:slot name="since"/></td>
1115+        <td class="service-announced">   <n:slot name="announced"/></td>
1116+        <td class="service-version">     <n:slot name="version"/></td>
1117+      </tr>
1118+      <tr n:pattern="empty"><td>no peers!</td></tr>
1119+    </table>
1120+  </div>
1121 </div>
1122 
1123hunk ./src/allmydata/web/welcome.xhtml 88
1124-<h2>Other Resources</h2>
1125+<div class="section" id="other-resources">
1126+  <h2>Other Resources</h2>
1127 
1128hunk ./src/allmydata/web/welcome.xhtml 91
1129-<div>Please visit the <a href="http://allmydata.org">Tahoe home page</a> for
1130-code updates and bug reporting.</div>
1131+  <div>Please visit the <a href="http://allmydata.org">Tahoe home page</a> for
1132+  code updates and bug reporting.</div>
1133 
1134hunk ./src/allmydata/web/welcome.xhtml 94
1135-<div>The <a href="provisioning">provisioning tool</a> and <a
1136-href="reliability">reliability calculator</a> may also be useful.</div>
1137+  <div>The <a href="provisioning">provisioning tool</a> and <a
1138+  href="reliability">reliability calculator</a> may also be useful.</div>
1139 
1140hunk ./src/allmydata/web/welcome.xhtml 97
1141-<div n:render="incident_button" />
1142+  <div n:render="incident_button" />
1143+</div>
1144 
1145hunk ./src/allmydata/web/welcome.xhtml 100
1146-  </body>
1147-</html>
1148+</body></html>
1149}
1150
1151Context:
1152
1153[accounting-overview.txt: more edits
1154warner@lothar.com**20090523190359] 
1155[accounting-overview.txt: small edits
1156warner@lothar.com**20090523184011] 
1157[_auto_deps.py: require foolscap-0.4.1, which adds an important fix for py2.4
1158warner@lothar.com**20090523011103] 
1159[immutable/encode.py: tolerate immediate _remove_shareholder by copying the
1160warner@lothar.com**20090522184424
1161 landlord list before iterating over it. This can probably only happen in unit
1162 tests, but cleaning it up makes certain test failures easier to analyze.
1163] 
1164[switch to using RemoteException instead of 'wrapped' RemoteReferences. Should fix #653, the rref-EQ problem
1165warner@lothar.com**20090522004632] 
1166[switch all foolscap imports to use foolscap.api or foolscap.logging
1167warner@lothar.com**20090522003823] 
1168[_auto_deps.py: bump our foolscap dependency to 0.4.0, since I'm about to start using its new features
1169warner@lothar.com**20090522002100] 
1170[test_runner.py: fix minor typo
1171warner@lothar.com**20090520033620] 
1172[setup: fix bug (wrong import) in error message, as noticed by pyflakes
1173zooko@zooko.com**20090519195642
1174 Ignore-this: f1b9f8c00b46c1b5f2f20e5fc424f341
1175] 
1176[setup: fix trivial bug in recent patch to test base64.py at startup
1177zooko@zooko.com**20090519195129
1178 Ignore-this: f6be038f74b53ca69e7109fe34adfbc
1179] 
1180[setup: make Tahoe exit at startup with a useful error message if the base64.py module is buggy (fixes part of #710)
1181zooko@zooko.com**20090519194555
1182 Ignore-this: aa4d398235ddca8d417d61c9688e154
1183] 
1184[test_introducer.py: add a test for the python2.4.0/2.4.1 bug in base64.b32decode
1185warner@lothar.com**20090519034101] 
1186[immutable WriteBucketProxy: use pipeline to speed up uploads by overlapping roundtrips, for #392
1187warner@lothar.com**20090518234422] 
1188[util/pipeline.py: new utility class to manage size-limited work pipelines, for #392
1189warner@lothar.com**20090518234326] 
1190[docs: add a diagram that I'm about to show to the Boulder Linux Users Group: network-and-reliance-topology.svg
1191zooko@zooko.com**20090514232059
1192 Ignore-this: 2420c0a7c254c9f0f2349d9130490d33
1193] 
1194[tests: mark test_runner as coded in utf-8 instead of ascii
1195zooko@zooko.com**20090507223151
1196 Ignore-this: ccf1ba9e5a9b53602701a36f9fdb545e
1197] 
1198[tests: raise timeout on test_runner.RunNode.test_introducer from 120s to 240s, since it hit the 120s time-out on François Lenny-armv5tel
1199zooko@zooko.com**20090507215012
1200 Ignore-this: ba18fe6832ba255d4971e8f623ed7da5
1201] 
1202[setup: fix comment in setup.py
1203zooko@zooko.com**20090507215003
1204 Ignore-this: c46ef664630d52733138ef7fbc551c1c
1205] 
1206[docs: how_to_make_a_tahoe_release.txt: a couple of small edits
1207zooko@zooko.com**20090507214932
1208 Ignore-this: ae92aa835ad369f4b9e6e49d681957a3
1209] 
1210[.darcs-boringfile: also ignore .gitignore
1211warner@allmydata.com**20090415210550
1212 Ignore-this: d29db314a1e506f6240859559436b4c3
1213] 
1214[.darcs-boringfile: ignore .git, I'm starting to play around with it
1215warner@allmydata.com**20090415205929
1216 Ignore-this: 89234453516483c9586cd6e1351e88b5
1217] 
1218[fix quicktest: stop using setuptools, add misc/run-with-pythonpath.py, to make it run faster
1219warner@lothar.com**20090414201400] 
1220[TAG allmydata-tahoe-1.4.1
1221zooko@zooko.com**20090414025636
1222 Ignore-this: de78fc32364c83e9f4e26b5abcfdea4a
1223] 
1224Patch bundle hash:
12257ad24d0f65a6edc9460ed8780b24834733d4e0c4