inline HTML, result viewer

This commit is contained in:
Ville Rantanen
2018-12-04 20:58:24 +02:00
parent 1a8cc70914
commit 2910cc2186
10 changed files with 185 additions and 101 deletions

17
abot.py
View File

@@ -89,11 +89,22 @@ def save_vote():
create_result_table(key)
write_vote(key, token, request.form, form) # using request.
summary = ''
tokens = False
summary = False
questions = []
answers = []
if is_show_results(form):
summary = get_html_summary(key)
summary = True
questions, answers = get_summary(g.db, key)
tokens = get_token_counts(g.db, key)
return render_template('thank_you.html', summary = summary)
return render_template(
'thank_you.html',
summary = summary,
tokens = tokens,
questions = questions,
answers = answers
)
if __name__ == "__main__":
manager.main(DATABASE, QUESTIONS)

View File

@@ -135,77 +135,17 @@ def list_question_sets(options):
def summary(options):
print(get_summary(options))
def get_summary(options):
if not is_key(options.name, options):
raise Exception("%s does not exist, or is not a valid question set name"%( options.name, ))
db = open_db(options.db)
cur = db.cursor()
questions, answers = get_summary(db, options.name)
tokens = get_token_counts(db, options.name)
cur.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?;",
( options.name, )
)
matching_tables = cur.fetchall()
if len(matching_tables) == 0:
return "No votes yet"
token_table = get_voter_table_name(options.name)
cur.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?;",
( token_table, )
)
matching_tables = cur.fetchall()
if len(matching_tables) == 0:
used_tokens = 0
unused_tokens = 0
if options.tsv:
out = summary_tsv(questions, answers, tokens)
else:
cur.execute(
"SELECT count(*) FROM `%s` WHERE answered = 'true'"%(
token_table,
)
)
used_tokens = cur.fetchall()[0][0]
cur.execute(
"SELECT count(*) FROM `%s` WHERE answered = 'false'"%(
token_table,
)
)
unused_tokens = cur.fetchall()[0][0]
tokens = {
'unused': unused_tokens,
'used': used_tokens,
'total': used_tokens + unused_tokens
}
questions = []
answers = {}
cur.execute(
"SELECT question, answer, answer_type FROM `%s`"%(
options.name,
)
)
for row in cur:
if row[0] not in answers.keys():
questions.append(row[0])
answers[row[0]] = {
'answers': {},
'answer_type': row[2]
}
if row[1] not in answers[row[0]]['answers'].keys():
answers[row[0]]['answers'][row[1]] = 0
answers[row[0]]['answers'][row[1]] += 1
try:
if options.tsv:
return summary_tsv(questions, answers, tokens)
else:
return summary_list(questions, answers, tokens)
except AttributeError:
return summary_list(questions, answers, tokens)
out = summary_list(questions, answers, tokens)
print(out)
def summary_list(questions, answers, tokens):
s = """# Tokens for this question set:

View File

@@ -1,17 +1,30 @@
# expiry format: YYYY-MM-DD HH:MM +z
# z is the difference to UTC in HHMM, +0000, -0700, etc..
expires: 2028-12-12 21:20 +0200
# if "draft: true" voting is not possible. you can preview the form with address /preview/example
# if "draft: true" voting is not possible. you can preview the form with address "/preview/example"
draft: false
# "open" vote style is open for anyone without tokens. "closed" requires tokens to be generated
# Create tokens with `./manager token multi_question`
vote_style: closed
# By default voters can not see the results
show_results: false
# HTML can be added inline. The line needs to begin with "<"
# HTML added like this is technically a question without answer choices
<H1>Title of vote page</H1>
<img src="https://upload.wikimedia.org/wikipedia/en/thumb/7/7d/Lenna_%28test_image%29.png/220px-Lenna_%28test_image%29.png"/>
# - character is single choice question
It works?
- yes
- no
# If a question is in HTML tags, it's not formatted
<p>Fruits</p>
# + character is multi choice question
Fruits
+ banana
+ orange
+ tomato

View File

@@ -1,8 +1,14 @@
# if "true" voting is not possible. you can preview the form in address /preview/example
draft: false
# "open" vote style is open for anyone without tokens. "closed" requires tokens to be generated
vote_style: open
# By default voters can not see the results
show_results: true
# Questions are any line that doesnt match configuration commands
It works?
# single choice answers are denoted with dashes
- yes
- no

View File

@@ -1,18 +1,12 @@
body { font-family: sans-serif; background: #eee; }
a, h1, h2 { color: #377ba8; }
h1, h2 { font-family: 'Georgia', serif; margin: 0; }
h1, h2 { font-family: 'Georgia', serif; margin: 0; margin-top: 0.2em; }
h1 { border-bottom: 2px solid #eee; }
h2 { font-size: 1.2em; }
input { margin-top: 0.5em; border: 1px solid gray;}
.page { margin: 2em auto; width: 90%; border: 5px solid #ccc;
padding: 0.8em; background: white; }
.entries { list-style: none; margin: 0; padding: 0; }
.entries li { margin: 0.8em 1.2em; }
.entries li h2 { margin-left: -1em; }
table.entriesall { border-collapse: collapse; }
.entriesall td, .entriesall th { border: 1px solid black;
padding: 0.5em; }
.index {
margin-top: 1em;
}
@@ -21,16 +15,27 @@ table.entriesall { border-collapse: collapse; }
margin-top: 1em;
}
.question {
border-bottom: 1px solid gray;
padding-bottom: 0.5em;
}
.autoformat {
border-bottom: 1px solid gray;
}
.warning {
font-size: small;
color: red;
}
.message {
font-size: large;
color: red;
margin-top: 1em;
margin-bottom: 1em;
}
textarea {
width: 90%;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.header {
@@ -38,7 +43,23 @@ textarea {
font-size: small;
}
.footer {
margin-top: 2em;
text-align: left;
font-size: small;
}
.summary_single {
list-style-type: disk;
}
.summary_multiple {
list-style-type: square;
}
.summary_open {
list-style-type: circle;
font-style: italic;
}
.thankyou {
font-size: large;
margin-top: 1em;
margin-bottom: 1em;
}

View File

@@ -1,4 +1,4 @@
{% extends "layout.html" %}
{% block body %}
{{ message }}
<div class=message>{{ message }}</div>
{% endblock %}

View File

@@ -9,17 +9,19 @@
<div class=page>
<div class=header>
Read more about me at the <a href="#bottom">bottom!</a>
</div>
<div class=header>
<a href="#bottom">About</a>
</div>
{% block body %}{% endblock %}
<hr>
</div>
<div class=page>
<div class=footer>
About aBot
<ul>
<li>This voting machine does not store information about you.</li>
<li>The token given to you is stored separately to the answers you give.</li>
<li>If you were given the token via email or any other such means, this voting machine does not know the connection between your contact information and the vote token.</li>
<li>Source code at <a href="https://bitbucket.org/MoonQ/aBot/">Bitbucket</a></li>
<li>This voting machine does not store information about you.</li>
<li>The token given to you is stored separately to the answers you give.</li>
<li>If you were given the token via email or any other such means, this voting machine does not know the connection between your contact information and the vote token.</li>
<li>Source code at <a href="https://bitbucket.org/MoonQ/aBot/">Bitbucket</a></li>
</ul>
<a id="bottom"></a>
</div>

View File

@@ -1,8 +1,13 @@
<div id="questions">
{% for question in form.questions %}
<div class = "question">
<h2>{{ question.name|safe }}</h2>
{% if question.autoformat %}
<div class = "question autoformat">
<h2>{{ question.name|safe }}</h2>
{% else %}
<div class = "question">
{{ question.name|safe }}
{% endif %}
{% for choice in question.choices %}
<div>
<input type="radio" name="QC{{ question.index }}" value="{{ choice|safe }}" />

View File

@@ -1,9 +1,35 @@
{% extends "layout.html" %}
{% block body %}
<h1>aBot!</h1>
<div class=thankyou>
Thank you for the vote!
</div>
{% if summary %}
<h3>Current report</h3>
{{ summary|safe }}
<div id="questions">
{% for question in questions %}
<div class = "question autoformat">
<h2>{{ question|safe }}</h2>
<ul>
{% for choice in answers[question].answers %}
{% if answers[question].answer_type == "single" %}
<li class = "summary_single">{{ choice }}: {{ answers[question].answers[choice] }}
{% endif %}
{% if answers[question].answer_type == "multiple" %}
<li class = "summary_multiple">{{ choice }}: {{ answers[question].answers[choice] }}
{% endif %}
{% if answers[question].answer_type == "open" %}
<li class = "summary_open">"{{ choice }}"
{% endif %}
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
{% endif %}
{% endblock %}

View File

@@ -38,10 +38,69 @@ def get_voter_table_name(key):
def get_result_table_name(key):
return key
def get_token_counts(db, key):
cur = db.cursor()
token_table = get_voter_table_name(key)
cur.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?;",
( token_table, )
)
matching_tables = cur.fetchall()
if len(matching_tables) == 0:
used_tokens = 0
unused_tokens = 0
else:
cur.execute(
"SELECT count(*) FROM `%s` WHERE answered = 'true'"%(
token_table,
)
)
used_tokens = cur.fetchall()[0][0]
cur.execute(
"SELECT count(*) FROM `%s` WHERE answered = 'false'"%(
token_table,
)
)
unused_tokens = cur.fetchall()[0][0]
tokens = {
'unused': unused_tokens,
'used': used_tokens,
'total': used_tokens + unused_tokens
}
return tokens
def get_html_summary(key):
# TODO
return ''
def get_summary(db, key):
""" returns summary for a vote event """
questions = []
answers = {}
cur = db.cursor()
cur.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name=?;",
( key, )
)
matching_tables = cur.fetchall()
if len(matching_tables) == 0:
return questions, answers
cur.execute(
"SELECT question, answer, answer_type FROM `%s`"%(
key,
)
)
for row in cur:
if row[0] not in answers.keys():
questions.append(row[0])
answers[row[0]] = {
'answers': {},
'answer_type': row[2]
}
if row[1] not in answers[row[0]]['answers'].keys():
answers[row[0]]['answers'][row[1]] = 0
answers[row[0]]['answers'][row[1]] += 1
return questions, answers
def has_voted(key, token):
@@ -104,7 +163,7 @@ def parse_form(key):
}
key = secure_filename(key)
try:
current_question = None
current_question = 0
with open(os.path.join(app.config['QUESTIONS'], key + ".txt"), "rt") as fp:
for row in fp:
if row.strip() == "":
@@ -145,9 +204,10 @@ def parse_form(key):
form['questions'].append({
'choices': [],
'multichoices': [],
'index': len(form['questions']) + 1,
'index': current_question + 1,
'name': row.strip().rstrip("_:").rstrip(),
'open_question': row.strip().endswith("___")
'open_question': row.strip().endswith("___"),
'autoformat': not rowsl.startswith("<")
})
return form
except Exception as err: