support for delayed opening. css changes

This commit is contained in:
Ville Rantanen
2018-12-15 16:16:13 +02:00
parent 5c50eb4670
commit a996edbc65
9 changed files with 107 additions and 36 deletions

22
abot.py
View File

@@ -43,12 +43,14 @@ def preview(key):
return render_template('blank.html', message = "Error creating form") return render_template('blank.html', message = "Error creating form")
if not is_draft(form): if not is_draft(form):
return render_template('blank.html', message = "Preview not enabled") return render_template('blank.html', message = "Preview not enabled")
valid_for = time_to_expiry(form) valid_for = time_to('expires', form)
opens = time_to('opens', form)
return render_template( return render_template(
'preview.html', 'preview.html',
key = key, key = key,
form = form, form = form,
valid_for = valid_for valid_for = valid_for,
opens = opens
) )
@@ -62,14 +64,19 @@ def vote(key, token = None):
return render_template('blank.html', message = "Error creating form") return render_template('blank.html', message = "Error creating form")
if is_draft(form): if is_draft(form):
return render_template('blank.html', message = "Not published") return render_template('blank.html', message = "Not published")
if is_expired(form):
return render_template('blank.html', message = "Voting has closed")
if is_closed_vote(form): if is_closed_vote(form):
if not is_voter(key, token): if not is_voter(key, token):
return render_template('blank.html', message = "Token invalid") return render_template('blank.html', message = "Token invalid")
if has_voted(key, token): if has_voted(key, token):
return render_template('blank.html', message = "Token already used") form['can_submit'] = False
valid_for = time_to_expiry(form) form['message'] = 'Token used. Can not submit anymore'
if not is_opened(form):
return render_template('blank.html', message = "Voting is not open yet. Opens at " + time_to('opens', form))
if is_expired(form):
form['can_submit'] = False
form['message'] = 'Voting has closed. Can not submit anymore'
valid_for = time_to('expires', form)
return render_template( return render_template(
'vote.html', 'vote.html',
@@ -98,6 +105,9 @@ def save_vote():
return render_template('blank.html', message = "Token invalid") return render_template('blank.html', message = "Token invalid")
if has_voted(key, token): if has_voted(key, token):
return render_template('blank.html', message = "Token already used") return render_template('blank.html', message = "Token already used")
if not is_opened(form):
return render_template('blank.html', message = "Voting is not open yet. Opens at " + time_to('opens', form))
write_vote(key, token, request.form, form) # using request. write_vote(key, token, request.form, form) # using request.
tokens = False tokens = False

View File

@@ -1,6 +1,8 @@
title: My Vote
# expiry format: YYYY-MM-DD HH:MM +z # expiry format: YYYY-MM-DD HH:MM +z
# z is the difference to UTC in HHMM, +0000, -0700, etc.. # z is the difference to UTC in HHMM, +0000, -0700, etc..
expires: 2028-12-12 21:20 +0200 expires: 2028-12-12 21:20 +0200
opens: 2010-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 draft: false

BIN
static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

View File

@@ -1,12 +1,28 @@
body { font-family: sans-serif; background: #eee; } @font-face {
a, h1, h2 { color: #227b64; } font-family: HK Grotesk;
h1, h2 { font-family: 'Georgia', serif; margin: 0; margin-top: 0.9em; } src: url('hk-grotesk.regular.ttf');
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: 3px solid #ccc; body { font-family: 'HK Grotesk', sans-serif; background: #eee; }
padding: 0.8em; background: white; } a, h1, h2 { color: #227b64; }
h1, h2 { font-family: 'HK Grotesk', sans-serif; margin: 0; margin-top: 0.9em; }
h1 { border-bottom: 2px solid #eee; text-align: center; }
h2 { font-size: 1.2em; }
input {
margin-top: 0.8em;
}
input[type=submit] {
border: 1px solid #333;
border-radius: 2px;
font-size: 1.0em;
padding: 8px;
}
.page {
margin: 2em auto; width: 90%; border: 1px solid #ccc;
padding: 0.8em; background: white;
}
.index { .index {
margin-top: 1em; margin-top: 1em;
} }
@@ -18,7 +34,7 @@ input { margin-top: 0.5em; border: 1px solid gray;}
padding-bottom: 0.5em; padding-bottom: 0.5em;
} }
.autoformat { .autoformat {
border-bottom: 1px solid gray; border-bottom: 1px solid #ccc;
} }
.warning { .warning {
font-size: small; font-size: small;
@@ -29,6 +45,13 @@ input { margin-top: 0.5em; border: 1px solid gray;}
color: red; color: red;
margin-top: 1em; margin-top: 1em;
margin-bottom: 1em; margin-bottom: 1em;
width: 100%;
background-color: #eee;
text-align: center;
padding: 8px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
} }
textarea { textarea {
@@ -72,3 +95,6 @@ textarea {
text-align: center; text-align: center;
padding: 3px; padding: 3px;
} }
.submit {
text-align: center;
}

View File

@@ -2,8 +2,8 @@
<head> <head>
<title>aBot // {{ g.title|safe }}</title> <title>aBot // {{ g.title|safe }}</title>
<meta name="viewport" content="width=440" /> <meta name="viewport" content="width=440" />
<link rel="icon" href="{{ url_for('static', filename='favicon.png') }}">
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}"> <link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<script src="{{ url_for('static', filename='script.js') }}" type="text/javascript"></script>
</head> </head>
<body> <body>

View File

@@ -1,8 +1,12 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block body %} {% block body %}
<div id="preview_header"> <div id="preview_header" class=autoformat>
Preview for: {{ key|safe }}<br> Preview for: {{ key|safe }}<br>
Expires: {{ valid_for }}<br> Voting ends at: {{ valid_for }}<br>
Voting starts at: {{ opens }}<br>
Style (open/closed): {{ form.vote_style }}<br>
Show results after voting: {{ form.show_results }}<br>
Title: {{ form.title }}<br>
</div> </div>
{% include "questions.html" %} {% include "questions.html" %}

View File

@@ -1,21 +1,33 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block body %} {% block body %}
{% if not form.can_submit %}
<div class=message>{{ form.message }}</div>
{% endif %}
{% if valid_for != 'Never' %}
<div id="vote_header">Voting ends at: {{ valid_for }}</div> <div id="vote_header">Voting ends at: {{ valid_for }}</div>
{% endif %}
<form id="vote_form" action="{{ url_for('save_vote') }}" method=post > <form id="vote_form" action="{{ url_for('save_vote') }}" method=post >
<input type=hidden value="{{ key|safe }}" name=key /> <input type=hidden value="{{ key|safe }}" name=key />
<input type=hidden value="{{ token|safe }}" name=token /> <input type=hidden value="{{ token|safe }}" name=token />
{% include "questions.html" %} {% include "questions.html" %}
<p> <p>
<input type=submit name=submit value="Submit"/><br> {% if form.can_submit %}
{% if form.vote_style == 'closed' %} <div class=submit>
<div class = "warning"> <input type=submit name=submit value="Submit"/>
You can only vote once! </div>
<ul> {% if form.vote_style == 'closed' %}
<li>Votes can not be edited later</li> <div class = "warning">
<li>Empty choices counts as empty, used vote</li> You can only vote once!
</ul> <ul>
</div> <li>Votes can not be edited later</li>
<li>Empty choices counts as empty, used vote</li>
</ul>
</div>
{% endif %}
{% else %}
<div class=message>{{ form.message }}</div>
{% endif %} {% endif %}
</p> </p>
</form> </form>

View File

@@ -131,10 +131,15 @@ def is_draft(form):
def is_expired(form): def is_expired(form):
if form['expires'] == None: if form['expires'] == None:
return False return False
return datetime.now(timezone.utc) > form['expires'] return datetime.now(timezone.utc) > form['expires']
def is_opened(form):
if form['opens'] == None:
return True
return datetime.now(timezone.utc) > form['opens']
def is_key(key, cli_opts = False): def is_key(key, cli_opts = False):
key = secure_filename(key) key = secure_filename(key)
@@ -171,11 +176,14 @@ def is_voter(key, token):
def parse_form(key): def parse_form(key):
form = { form = {
'expires': None, 'expires': None,
'opens': None,
'draft': False, 'draft': False,
'vote_style': "closed", 'vote_style': "closed",
'show_results': False, 'show_results': False,
'questions': [], 'questions': [],
'title': "" 'title': "",
'can_submit': True,
'message': ''
} }
key = secure_filename(key) key = secure_filename(key)
try: try:
@@ -194,6 +202,9 @@ def parse_form(key):
if rowsl.startswith("expires: "): if rowsl.startswith("expires: "):
form['expires'] = parse_row_date(row) form['expires'] = parse_row_date(row)
continue continue
if rowsl.startswith("opens: "):
form['opens'] = parse_row_date(row)
continue
if rowsl.startswith("draft: "): if rowsl.startswith("draft: "):
if rowsl == "draft: true": if rowsl == "draft: true":
form['draft'] = True form['draft'] = True
@@ -225,7 +236,7 @@ def parse_form(key):
'choices': [], 'choices': [],
'multichoices': [], 'multichoices': [],
'index': current_question + 1, 'index': current_question + 1,
'name': row.strip().rstrip("_:").rstrip(), 'name': row.strip().rstrip("_").rstrip(),
'open_question': row.strip().endswith("___"), 'open_question': row.strip().endswith("___"),
'autoformat': not rowsl.startswith("<") 'autoformat': not rowsl.startswith("<")
}) })
@@ -237,7 +248,7 @@ def parse_form(key):
def parse_row_date(row): def parse_row_date(row):
row = row[9:].strip() row = " ".join(row.split(" ")[1:]).strip()
if row.lower() == "none": if row.lower() == "none":
return None return None
try: try:
@@ -304,12 +315,18 @@ def sort_summary(questions, answers):
return questions, sorted_answer_list return questions, sorted_answer_list
def time_to_expiry(form): def time_to(what, form):
if form['expires'] == None: if not what in ('expires','opens'):
return "Never" raise AttributeError("Dont know that attribute")
time_to_go = form['expires'] - datetime.now(timezone.utc) if form[what] == None:
if what == 'expires':
return "Never"
if what == 'opens':
return "None"
time_to_go = form[what] - datetime.now(timezone.utc)
time_to_go = ".".join(str(time_to_go).split('.')[0:-1])[0:-3] time_to_go = ".".join(str(time_to_go).split('.')[0:-1])[0:-3]
#time_to_go.microseconds = 0 #time_to_go.microseconds = 0
return "%s (%s to go)"%( form['expires'], time_to_go ) return "%s (%s to go)"%( form[what], time_to_go )