]> git.scottworley.com Git - voter/commitdiff
Eliminated candidates UI
authorScott Worley <scottworley@scottworley.com>
Sun, 7 Apr 2024 12:57:43 +0000 (05:57 -0700)
committerScott Worley <scottworley@scottworley.com>
Sun, 7 Apr 2024 13:13:09 +0000 (06:13 -0700)
src/main.rs

index 8c94be10909277a1c271c0ecd856e7f04b118730..1ec9d9c352d41d0d01e259cee2de52df43a70e22 100644 (file)
@@ -81,6 +81,14 @@ fn tally_votes(dir: &Path) -> std::io::Result<HashMap<String, HashSet<String>>>
     }
 }
 
     }
 }
 
+fn read_elim_list(dir: &Path) -> std::io::Result<HashSet<String>> {
+    match std::fs::File::open(dir.join("eliminated")) {
+        Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(HashSet::new()),
+        Err(e) => Err(e),
+        Ok(elimfile) => std::io::BufReader::new(elimfile).lines().collect(),
+    }
+}
+
 fn valid_id_char(c: u8) -> bool {
     c.is_ascii_alphanumeric()
 }
 fn valid_id_char(c: u8) -> bool {
     c.is_ascii_alphanumeric()
 }
@@ -121,6 +129,7 @@ const HTML_HEADER: &str = "<!DOCTYPE html>
     <style>
       th { font-size: 70%; text-align: left }
       input { transform: scale(1.5) }
     <style>
       th { font-size: 70%; text-align: left }
       input { transform: scale(1.5) }
+      .eliminated { text-decoration: line-through; }
       div { animation: 2s infinite linear spin }
       @keyframes spin {
         from { transform:rotate(0) }
       div { animation: 2s infinite linear spin }
       @keyframes spin {
         from { transform:rotate(0) }
@@ -130,6 +139,8 @@ const HTML_HEADER: &str = "<!DOCTYPE html>
     <script>
       window.onload = function() {
         for (cb of document.getElementsByTagName('input')) {
     <script>
       window.onload = function() {
         for (cb of document.getElementsByTagName('input')) {
+          if (cb.parentElement.parentElement.classList.contains('eliminated'))
+            continue;
           cb.addEventListener('click', (function(cb) {
             return function() {
               cb.style.display = 'none'
           cb.addEventListener('click', (function(cb) {
             return function() {
               cb.style.display = 'none'
@@ -207,6 +218,8 @@ fn prompt_for_vote(dir: &Path, request: &cgi::Request) -> Result<cgi::Response,
         None
     };
     let tally = tally_votes(dir).map_err(|_| cgi::text_response(503, "Couldn't tally votes"))?;
         None
     };
     let tally = tally_votes(dir).map_err(|_| cgi::text_response(503, "Couldn't tally votes"))?;
+    let elim =
+        read_elim_list(dir).map_err(|_| cgi::text_response(503, "Couldn't read eliminations"))?;
     let cfile = std::fs::File::open(dir.join("candidates"))
         .map_err(|_| cgi::text_response(503, "No candidates"))?;
     let mut response = cgi::html_response(
     let cfile = std::fs::File::open(dir.join("candidates"))
         .map_err(|_| cgi::text_response(503, "No candidates"))?;
     let mut response = cgi::html_response(
@@ -220,8 +233,9 @@ fn prompt_for_vote(dir: &Path, request: &cgi::Request) -> Result<cgi::Response,
                     } else {
                         ""
                     };
                     } else {
                         ""
                     };
+                    let class = if elim.contains(&c) { "eliminated" } else { "" };
                     format!(
                     format!(
-                        "<tr>
+                        "<tr class=\"{class}\">
                         <td>{count}</td>
                         <td><input type=\"checkbox\" autocomplete=\"off\" {checked} disabled></td>
                         <td>{c}</td>
                         <td>{count}</td>
                         <td><input type=\"checkbox\" autocomplete=\"off\" {checked} disabled></td>
                         <td>{c}</td>