From 1d013c84d69b37de7958e3a8318b3ceedaf0c6f8 Mon Sep 17 00:00:00 2001
From: Ben Adida <ben@adida.net>
Date: Sat, 23 Apr 2016 17:53:28 +0000
Subject: [PATCH] add ability to enter a more-info URL for each election answer

---
 helios/media/static_templates/question.html | 19 ++++++-------------
 helios/models.py                            | 16 ++++++++++++++++
 helios/templates/election_build.html        |  2 +-
 helios/templates/election_questions.html    | 11 ++++++++---
 helios/views.py                             |  3 ++-
 5 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/helios/media/static_templates/question.html b/helios/media/static_templates/question.html
index dd5b8c8..21efdc5 100644
--- a/helios/media/static_templates/question.html
+++ b/helios/media/static_templates/question.html
@@ -7,7 +7,11 @@
 <a href="javascript:question_remove({$T.question$index})">x</a>] [<a href="javascript:question_edit({$T.question$index})">edit</a>] {#/if}{$T.question$index + 1}. {$T.question.question} ({$T.question.choice_type}, select between {$T.question.min} and {#if $T.question.max != null}{$T.question.max}{#else}unlimited{#/if} answers, result type {$T.question.result_type}.)</h4>
 <ul>
 {#foreach $T.question.answers as answer}
-<li> {$T.answer}</li>
+<li> {$T.answer}
+{#if $T.question.answer_urls[$T.answer$index]}
+  [<a target="_new" href="{$T.question.answer_urls[$T.answer$index]}">more</a>]
+{#/if}
+</li>
 {#/for}
 </ul>
 </div>
@@ -179,21 +183,10 @@ Result Type:&nbsp;
 
 </p>
 
-<table id="answer_table">
+<table id="answer_table" style="width:100%;">
   <tbody>
     <tr><th colspan="2">Question:</th><td><input type="text" name="question" size="70" /></td></tr>
     <tr><th>&nbsp;</th><th>&nbsp;</th><th>&nbsp;</th></tr>
-<!--
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #1:</th><td><input type="text" name="answer_1" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #2:</th><td><input type="text" name="answer_2" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #3:</th><td><input type="text" name="answer_3" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #4:</th><td><input type="text" name="answer_4" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #5:</th><td><input type="text" name="answer_5" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #6:</th><td><input type="text" name="answer_6" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #7:</th><td><input type="text" name="answer_7" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #8:</th><td><input type="text" name="answer_8" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #9:</th><td><input type="text" name="answer_9" size="70" /></td></tr>
-    <tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #10:</th><td><input type="text" name="answer_10" size="70" /></td></tr> -->
   </tbody>
   <tfoot>
     <tr><th colspan="2"></th><th><a href="javascript:add_answers($('#answer_table'), 5)">add 5 more answers</a></th></tr>
diff --git a/helios/models.py b/helios/models.py
index 80d12ba..6a0f18f 100644
--- a/helios/models.py
+++ b/helios/models.py
@@ -244,6 +244,22 @@ class Election(HeliosModel):
       return cls.objects.get(short_name=short_name)
     except cls.DoesNotExist:
       return None
+    
+  def save_questions_safely(self, questions):
+    """
+    Because Django doesn't let us override properties in a Pythonic way... doing the brute-force thing.
+    """
+    # verify all the answer_urls
+    for q in questions:
+      for answer_url in q['answer_urls']:
+        if not answer_url or answer_url == "":
+          continue
+          
+        # abort saving if bad URL
+        if not (answer_url.startsWith("http://") or answer_url.startsWith("https://")):
+          return
+    
+    self.questions = questions
 
   def add_voters_file(self, uploaded_file):
     """
diff --git a/helios/templates/election_build.html b/helios/templates/election_build.html
index 5488c2d..4526d6a 100644
--- a/helios/templates/election_build.html
+++ b/helios/templates/election_build.html
@@ -40,7 +40,7 @@
           if (!form['answer_' + i] || !form['answer_' + i].value)
             break;
           new_q.answers[i-1] = form['answer_' + i].value;
-          new_q.answer_urls[i-1] = null;
+          new_q.answer_urls[i-1] = form['answer_urls_' + i].value;
       }
       
       QUESTIONS.push(new_q);
diff --git a/helios/templates/election_questions.html b/helios/templates/election_questions.html
index 030b24f..d2262c4 100644
--- a/helios/templates/election_questions.html
+++ b/helios/templates/election_questions.html
@@ -42,7 +42,7 @@
           if (!form['answer_' + i] || !form['answer_' + i].value)
             break;
           new_q.answers[i-1] = form['answer_' + i].value;
-          new_q.answer_urls[i-1] = null;
+          new_q.answer_urls[i-1] = form['answer_url_' +i].value;
       }
       
      return new_q;
@@ -83,7 +83,12 @@
     $(q_data.answers).each(function(i, a) {
      form[0]['answer_' + (i+1)].value = a;
     });
-  }
+
+    // URLs
+    $(q_data.answer_urls).each(function(i, a) {
+     form[0]['answer_url_' + (i+1)].value = a;
+    });
+}
 
   function question_edit_cancel(q_num) {
     $('#q_edit_'+q_num).hide();
@@ -101,7 +106,7 @@
   function add_answer(el) {
     el = $(el);
     var num_answers = el.find('input.answer').length + 1;
-    el.find('tbody').append('<tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #' + num_answers + '</th><td><input type="text" class="answer" name="answer_' + num_answers + '" size="70" /></td></tr>');
+    el.find('tbody').append('<tr><th>&nbsp;&nbsp;&nbsp;</th><th>Answer #' + num_answers + '</th><td><input type="text" class="answer" name="answer_' + num_answers + '" size="70" /><br /><nobr>Link (optional): <input type="text" name="answer_url_' + num_answers + '" width="50%" /></nobr></td></tr>');
   }
 
   function add_answers(el, num) {
diff --git a/helios/views.py b/helios/views.py
index 0aaaaa5..17969db 100644
--- a/helios/views.py
+++ b/helios/views.py
@@ -940,7 +940,8 @@ def one_election_register(request, election):
 def one_election_save_questions(request, election):
   check_csrf(request)
   
-  election.questions = utils.from_json(request.POST['questions_json'])
+  questions = utils.from_json(request.POST['questions_json'])
+  election.save_questions_safely(questions)
   election.save()
 
   # always a machine API
-- 
GitLab