From e499d84755fef9c540feb66558ee7a94fc32c34f Mon Sep 17 00:00:00 2001
From: Nathan Wilcox <nejucomo@gmail.com>
Date: Tue, 20 Jan 2015 16:31:56 -0800
Subject: [PATCH] Introduce icons with distinct shape for connection status
 display on the front wui page...

This replaces the status display which was only distinct by color which is a usability issue for color-blind users.  This commit includes test coverage by way of pattern matching on rendered templates.  The PNG icons are conversions of original SVG source which I've included and placed in the public domain.
---
 src/allmydata/test/test_system.py             |   2 +-
 src/allmydata/test/test_web.py                |  12 ++++-----
 src/allmydata/web/root.py                     |  13 ++++++++++
 src/allmydata/web/static/img/connected-no.png | Bin 0 -> 213 bytes
 src/allmydata/web/static/img/connected-no.svg |  22 +++++++++++++++++
 .../static/img/connected-not-configured.png   | Bin 0 -> 427 bytes
 .../static/img/connected-not-configured.svg   |  23 ++++++++++++++++++
 .../web/static/img/connected-yes.png          | Bin 0 -> 307 bytes
 .../web/static/img/connected-yes.svg          |  22 +++++++++++++++++
 src/allmydata/web/welcome.xhtml               |   6 ++---
 10 files changed, 90 insertions(+), 10 deletions(-)
 create mode 100644 src/allmydata/web/static/img/connected-no.png
 create mode 100644 src/allmydata/web/static/img/connected-no.svg
 create mode 100644 src/allmydata/web/static/img/connected-not-configured.png
 create mode 100644 src/allmydata/web/static/img/connected-not-configured.svg
 create mode 100644 src/allmydata/web/static/img/connected-yes.png
 create mode 100644 src/allmydata/web/static/img/connected-yes.svg

diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py
index 957c14c3..3b23b2f6 100644
--- a/src/allmydata/test/test_system.py
+++ b/src/allmydata/test/test_system.py
@@ -1114,7 +1114,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
         d.addCallback(lambda res: getPage(self.helper_webish_url))
         def _got_welcome_helper(page):
             html = page.replace('\n', ' ')
-            self.failUnless(re.search(r'<div class="status-indicator connected-yes"></div>\s*<div>Helper</div>', html), page)
+            self.failUnless(re.search('<img src="img/connected-yes.png" alt="Connected" />', html), page)
             self.failUnlessIn("Not running helper", page)
         d.addCallback(_got_welcome_helper)
 
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 8c5ead4b..1f46cbf9 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -649,7 +649,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             html = res.replace('\n', ' ')
             self.failUnlessIn('<div class="furl">pb://someIntroducer/[censored]</div>', html)
             self.failIfIn('pb://someIntroducer/secret', html)
-            self.failUnless(re.search('<div class="status-indicator connected-no"></div>[ ]*<div>Introducer not connected</div>', html), res)
+            self.failUnless(re.search('<img src="img/connected-no.png" alt="Disconnected" />', html), res)
         d.addCallback(_check_introducer_not_connected_unguessable)
 
         # introducer connected, unguessable furl
@@ -662,7 +662,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             html = res.replace('\n', ' ')
             self.failUnlessIn('<div class="furl">pb://someIntroducer/[censored]</div>', html)
             self.failIfIn('pb://someIntroducer/secret', html)
-            self.failUnless(re.search('<div class="status-indicator connected-yes"></div>[ ]*<div>Introducer</div>', html), res)
+            self.failUnless(re.search('<img src="img/connected-yes.png" alt="Connected" />', html), res)
         d.addCallback(_check_introducer_connected_unguessable)
 
         # introducer connected, guessable furl
@@ -674,7 +674,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         def _check_introducer_connected_guessable(res):
             html = res.replace('\n', ' ')
             self.failUnlessIn('<div class="furl">pb://someIntroducer/introducer</div>', html)
-            self.failUnless(re.search('<div class="status-indicator connected-yes"></div>[ ]*<div>Introducer</div>', html), res)
+            self.failUnless(re.search('<img src="img/connected-yes.png" alt="Connected" />', html), res)
         d.addCallback(_check_introducer_connected_guessable)
         return d
 
@@ -688,7 +688,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(_set_no_helper)
         def _check_no_helper(res):
             html = res.replace('\n', ' ')
-            self.failUnless(re.search('<div class="status-indicator connected-not-configured"></div>[ ]*<div>Helper</div>', html), res)
+            self.failUnless(re.search('<img src="img/connected-not-configured.png" alt="Not Configured" />', html), res)
         d.addCallback(_check_no_helper)
 
         # enable helper, not connected
@@ -701,7 +701,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             html = res.replace('\n', ' ')
             self.failUnlessIn('<div class="furl">pb://someHelper/[censored]</div>', html)
             self.failIfIn('pb://someHelper/secret', html)
-            self.failUnless(re.search('<div class="status-indicator connected-no"></div>[ ]*<div>Helper not connected</div>', html), res)
+            self.failUnless(re.search('<img src="img/connected-no.png" alt="Disconnected" />', html), res)
         d.addCallback(_check_helper_not_connected)
 
         # enable helper, connected
@@ -714,7 +714,7 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             html = res.replace('\n', ' ')
             self.failUnlessIn('<div class="furl">pb://someHelper/[censored]</div>', html)
             self.failIfIn('pb://someHelper/secret', html)
-            self.failUnless(re.search('<div class="status-indicator connected-yes"></div>[ ]*<div>Helper</div>', html), res)
+            self.failUnless(re.search('<img src="img/connected-yes.png" alt="Connected" />', html), res)
         d.addCallback(_check_helper_connected)
         return d
 
diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py
index 5f1d2367..8a9969c6 100644
--- a/src/allmydata/web/root.py
+++ b/src/allmydata/web/root.py
@@ -132,6 +132,12 @@ class Root(rend.Page):
     addSlash = True
     docFactory = getxmlfile("welcome.xhtml")
 
+    _connectedalts = {
+        "not-configured": "Not Configured",
+        "yes": "Connected",
+        "no": "Disconnected",
+        }
+
     def __init__(self, client, clock=None):
         rend.Page.__init__(self, client)
         self.client = client
@@ -222,6 +228,9 @@ class Root(rend.Page):
             return "yes"
         return "no"
 
+    def data_connected_to_introducer_alt(self, ctx, data):
+        return self._connectedalts[self.data_connected_to_introducer(ctx, data)]
+
     def data_helper_furl_prefix(self, ctx, data):
         try:
             uploader = self.client.getServiceNamed("uploader")
@@ -252,6 +261,9 @@ class Root(rend.Page):
             return "yes"
         return "no"
 
+    def data_connected_to_helper_alt(self, ctx, data):
+        return self._connectedalts[self.data_connected_to_helper(ctx, data)]
+
     def data_known_storage_servers(self, ctx, data):
         sb = self.client.get_storage_broker()
         return len(sb.get_all_serverids())
@@ -295,6 +307,7 @@ class Root(rend.Page):
             available_space = abbreviate_size(available_space)
         ctx.fillSlots("address", addr)
         ctx.fillSlots("connected", connected)
+        ctx.fillSlots("connected_alt", self._connectedalts[connected])
         ctx.fillSlots("connected-bool", bool(rhost))
         ctx.fillSlots("since", time.strftime(TIME_FORMAT,
                                              time.localtime(since)))
diff --git a/src/allmydata/web/static/img/connected-no.png b/src/allmydata/web/static/img/connected-no.png
new file mode 100644
index 0000000000000000000000000000000000000000..ca32a8e22eb05fede5446e024b951d0a6bc05fb6
GIT binary patch
literal 213
zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE<r98VX=5R2ZmQ#bOpD)6|Tf8g-P
zKi&6_LfYvUE=iA;KTPUT{LwJo`x5J|-~~?)aXL4s9(Z-|qNU9ahU|u?EsV`K74C|a
zOGGDH_pp5wwcmX3%dCtxv4qTKPJX@k6^`Bp%|BvpPIu<K_2%}Y8<TfPUEp2q(0_YZ
z_jm4J@;c4Wc6+h8oBQxhk&BEH$-M0$9sTRelSc~E^@F+B{NmohU>R-55nWyI1n5o%
MPgg&ebxsLQ0G*aptpET3

literal 0
HcmV?d00001

diff --git a/src/allmydata/web/static/img/connected-no.svg b/src/allmydata/web/static/img/connected-no.svg
new file mode 100644
index 00000000..f310eed5
--- /dev/null
+++ b/src/allmydata/web/static/img/connected-no.svg
@@ -0,0 +1,22 @@
+<svg version="1.1"
+     baseProfile="full"
+     width="20" height="20"
+     xmlns="http://www.w3.org/2000/svg">
+
+  <!-- Made by Nathan Wilcox on 2015-01-20.
+       This file is hereby placed into the public domain.
+  -->
+
+  <style>
+    /* <![CDATA[ */
+    line {
+    stroke: #aa0000;
+    stroke-width: 3.2;
+    stroke-linecap: round;
+    }
+    /* ]]> */
+  </style>
+
+  <line x1="2" y1="2" x2="18" y2="18" />
+  <line x1="18" y1="2" x2="2" y2="18" />
+</svg>
diff --git a/src/allmydata/web/static/img/connected-not-configured.png b/src/allmydata/web/static/img/connected-not-configured.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c66e6f20d1683594ff6dffb1016605df28875c5
GIT binary patch
literal 427
zcmV;c0aX5pP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%0004UNkl<ZIE|H+
zJx&8L5QTjJ^3x!W5T&L<RwO&`jU^v|zn+j>0Eq;`r63%GKn)T-fi7(l8auK!-t1;1
zH};!vW_HG2r7FyO-z3>3+0|M%s`Obi#<WG`iR1^#O}YTQ1DG0P+O=RJa!vBD2+FJl
zfXgb_gycFntVzC*9FQ~sEXmujmul{_FaTGH@XI-OS{68fR}s3CsWGOVl=<nsKQ4m-
z=#g9oZG<jJwo=hFM%$NJ0k#y8QBu`oT0-pRb6psKUhtiTy}43qJ7*h`8xgrV1QyPQ
z(O+xbP}bT`+;GnI4}mGAl!zeuTWdRefmN_9FfEzn;1F20<Xltg!a|0xLHCwM*^Z5f
z4C}%GoW-#bk;(ReWQ*i)VOXnRCjh>K_Q!kQEDF-Aw-S-jzRVKXT13vvgyX`+p8*&;
z=lagMerUj~pt&mx9Lv85ceC>OD$T5D;jwriInRLR0LDAttgdOT8w|eyW6V*N{vV24
VNLNEa?>ztj002ovPDHLkV1oHDz2*P_

literal 0
HcmV?d00001

diff --git a/src/allmydata/web/static/img/connected-not-configured.svg b/src/allmydata/web/static/img/connected-not-configured.svg
new file mode 100644
index 00000000..77ccb028
--- /dev/null
+++ b/src/allmydata/web/static/img/connected-not-configured.svg
@@ -0,0 +1,23 @@
+<svg version="1.1"
+     baseProfile="full"
+     width="20" height="20"
+     xmlns="http://www.w3.org/2000/svg">
+
+  <!-- Made by Nathan Wilcox on 2015-01-20.
+       This file is hereby placed into the public domain.
+  -->
+
+  <style>
+    /* <![CDATA[ */
+    line, circle {
+    stroke: #444444;
+    stroke-width: 2.4;
+    stroke-linecap: round;
+    }
+    /* ]]> */
+  </style>
+
+  <circle cx="10" cy="10" r="8" fill="transparent" />
+
+  <line x1="15" y1="5" x2="5" y2="15" />
+</svg>
diff --git a/src/allmydata/web/static/img/connected-yes.png b/src/allmydata/web/static/img/connected-yes.png
new file mode 100644
index 0000000000000000000000000000000000000000..e3fe59783b81b24e4398a82cc50d716042f222a8
GIT binary patch
literal 307
zcmV-30nGl1P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%0002`Nkl<ZIE|&!
zJqp4=5QgCw3@8>JAqTMcBAy@@5JOHP-axQ$XAwccHr5uFo**|6!9vl(A12ul;_g7I
z-FcRod=Oef2g?LYN=_8)A<Ph-pKlt5tr#KP6`1*BIT6B1VFgPD{-BU4?1^O@g2f0I
z1#bPZH@H>U1tIpwEaTFs&X356u%xYWv}Ax#DD33+2-DvM!=e#1%oTQL#i(wCv@$|c
zi&ZmcnAg9$qmOV_;1yw5y7PDDgy9GJHk{efSLYs?6OvNXcb`F-Gc25a24&9O=dC$&
zZOYweL+09}Nd<e<XYQXe92Iy7!vJ!62pcSG_H^5}y#Uy+!UNvfMYaF{002ovPDHLk
FV1k@ofL8zj

literal 0
HcmV?d00001

diff --git a/src/allmydata/web/static/img/connected-yes.svg b/src/allmydata/web/static/img/connected-yes.svg
new file mode 100644
index 00000000..fa1fd666
--- /dev/null
+++ b/src/allmydata/web/static/img/connected-yes.svg
@@ -0,0 +1,22 @@
+<svg version="1.1"
+     baseProfile="full"
+     width="20" height="20"
+     xmlns="http://www.w3.org/2000/svg">
+
+  <!-- Made by Nathan Wilcox on 2015-01-20.
+       This file is hereby placed into the public domain.
+  -->
+
+  <style>
+    /* <![CDATA[ */
+    line {
+    stroke: #00aa00;
+    stroke-width: 3.2;
+    stroke-linecap: round;
+    }
+    /* ]]> */
+  </style>
+
+  <line x1="2" y1="10" x2="8" y2="18" />
+  <line x1="18" y1="2" x2="8" y2="18" />
+</svg>
diff --git a/src/allmydata/web/welcome.xhtml b/src/allmydata/web/welcome.xhtml
index 72a2be16..c4774c81 100644
--- a/src/allmydata/web/welcome.xhtml
+++ b/src/allmydata/web/welcome.xhtml
@@ -137,14 +137,14 @@
               <div class="span6">
                 <div>
                   <h3>
-                    <div><n:attr name="class">status-indicator connected-<n:invisible n:render="string" n:data="connected_to_introducer" /></n:attr></div>
+                    <img><n:attr name="src">img/connected-<n:invisible n:render="string" n:data="connected_to_introducer" />.png</n:attr><n:attr name="alt"><n:invisible n:render="string" n:data="connected_to_introducer_alt" /></n:attr></img>
                     <div n:render="string" n:data="introducer_description" />
                   </h3>
                   <div class="furl" n:render="string" n:data="introducer_furl_prefix" />
                 </div>
                 <div>
                   <h3>
-                    <div><n:attr name="class">status-indicator connected-<n:invisible n:render="string" n:data="connected_to_helper" /></n:attr></div>
+                    <img><n:attr name="src">img/connected-<n:invisible n:render="string" n:data="connected_to_helper" />.png</n:attr><n:attr name="alt"><n:invisible n:render="string" n:data="connected_to_helper_alt" /></n:attr></img>
                     <div n:render="string" n:data="helper_description" />
                   </h3>
                   <div class="furl" n:render="string" n:data="helper_furl_prefix" />
@@ -178,7 +178,7 @@
             </thead>
             <tr n:pattern="item" n:render="service_row">
               <td class="nickname-and-peerid">
-              <div><n:attr name="class">status-indicator connected-<n:slot name="connected"/></n:attr></div>
+              <img><n:attr name="src">img/connected-<n:slot name="connected" />.png</n:attr><n:attr name="alt"><n:slot name="connected_alt" /></n:attr></img>
                 <div class="nickname"><n:slot name="nickname"/></div>
                 <div class="nodeid"><n:slot name="peerid"/></div>
               </td>
-- 
2.45.2