support for delayed opening. css changes
This commit is contained in:
22
abot.py
22
abot.py
@@ -43,12 +43,14 @@ def preview(key):
|
||||
return render_template('blank.html', message = "Error creating form")
|
||||
if not is_draft(form):
|
||||
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(
|
||||
'preview.html',
|
||||
key = key,
|
||||
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")
|
||||
if is_draft(form):
|
||||
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 not is_voter(key, token):
|
||||
return render_template('blank.html', message = "Token invalid")
|
||||
if has_voted(key, token):
|
||||
return render_template('blank.html', message = "Token already used")
|
||||
valid_for = time_to_expiry(form)
|
||||
form['can_submit'] = False
|
||||
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(
|
||||
'vote.html',
|
||||
@@ -98,6 +105,9 @@ def save_vote():
|
||||
return render_template('blank.html', message = "Token invalid")
|
||||
if has_voted(key, token):
|
||||
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.
|
||||
tokens = False
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
title: My Vote
|
||||
# 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
|
||||
opens: 2010-12-12 21:20 +0200
|
||||
|
||||
# if "draft: true" voting is not possible. you can preview the form with address "/preview/example"
|
||||
draft: false
|
||||
|
||||
BIN
static/favicon.png
Normal file
BIN
static/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
static/hk-grotesk.regular.ttf
Normal file
BIN
static/hk-grotesk.regular.ttf
Normal file
Binary file not shown.
@@ -1,12 +1,28 @@
|
||||
body { font-family: sans-serif; background: #eee; }
|
||||
a, h1, h2 { color: #227b64; }
|
||||
h1, h2 { font-family: 'Georgia', serif; margin: 0; margin-top: 0.9em; }
|
||||
h1 { border-bottom: 2px solid #eee; }
|
||||
h2 { font-size: 1.2em; }
|
||||
input { margin-top: 0.5em; border: 1px solid gray;}
|
||||
@font-face {
|
||||
font-family: HK Grotesk;
|
||||
src: url('hk-grotesk.regular.ttf');
|
||||
}
|
||||
|
||||
.page { margin: 2em auto; width: 90%; border: 3px solid #ccc;
|
||||
padding: 0.8em; background: white; }
|
||||
body { font-family: 'HK Grotesk', sans-serif; background: #eee; }
|
||||
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 {
|
||||
margin-top: 1em;
|
||||
}
|
||||
@@ -18,7 +34,7 @@ input { margin-top: 0.5em; border: 1px solid gray;}
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
.autoformat {
|
||||
border-bottom: 1px solid gray;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.warning {
|
||||
font-size: small;
|
||||
@@ -29,6 +45,13 @@ input { margin-top: 0.5em; border: 1px solid gray;}
|
||||
color: red;
|
||||
margin-top: 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 {
|
||||
@@ -72,3 +95,6 @@ textarea {
|
||||
text-align: center;
|
||||
padding: 3px;
|
||||
}
|
||||
.submit {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<head>
|
||||
<title>aBot // {{ g.title|safe }}</title>
|
||||
<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') }}">
|
||||
<script src="{{ url_for('static', filename='script.js') }}" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div id="preview_header">
|
||||
<div id="preview_header" class=autoformat>
|
||||
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>
|
||||
|
||||
{% include "questions.html" %}
|
||||
|
||||
@@ -1,21 +1,33 @@
|
||||
{% extends "layout.html" %}
|
||||
{% 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>
|
||||
{% endif %}
|
||||
<form id="vote_form" action="{{ url_for('save_vote') }}" method=post >
|
||||
<input type=hidden value="{{ key|safe }}" name=key />
|
||||
<input type=hidden value="{{ token|safe }}" name=token />
|
||||
|
||||
{% include "questions.html" %}
|
||||
<p>
|
||||
<input type=submit name=submit value="Submit"/><br>
|
||||
{% if form.vote_style == 'closed' %}
|
||||
<div class = "warning">
|
||||
You can only vote once!
|
||||
<ul>
|
||||
<li>Votes can not be edited later</li>
|
||||
<li>Empty choices counts as empty, used vote</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% if form.can_submit %}
|
||||
<div class=submit>
|
||||
<input type=submit name=submit value="Submit"/>
|
||||
</div>
|
||||
{% if form.vote_style == 'closed' %}
|
||||
<div class = "warning">
|
||||
You can only vote once!
|
||||
<ul>
|
||||
<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 %}
|
||||
</p>
|
||||
</form>
|
||||
|
||||
35
utils.py
35
utils.py
@@ -131,10 +131,15 @@ def is_draft(form):
|
||||
def is_expired(form):
|
||||
if form['expires'] == None:
|
||||
return False
|
||||
|
||||
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):
|
||||
key = secure_filename(key)
|
||||
|
||||
@@ -171,11 +176,14 @@ def is_voter(key, token):
|
||||
def parse_form(key):
|
||||
form = {
|
||||
'expires': None,
|
||||
'opens': None,
|
||||
'draft': False,
|
||||
'vote_style': "closed",
|
||||
'show_results': False,
|
||||
'questions': [],
|
||||
'title': ""
|
||||
'title': "",
|
||||
'can_submit': True,
|
||||
'message': ''
|
||||
}
|
||||
key = secure_filename(key)
|
||||
try:
|
||||
@@ -194,6 +202,9 @@ def parse_form(key):
|
||||
if rowsl.startswith("expires: "):
|
||||
form['expires'] = parse_row_date(row)
|
||||
continue
|
||||
if rowsl.startswith("opens: "):
|
||||
form['opens'] = parse_row_date(row)
|
||||
continue
|
||||
if rowsl.startswith("draft: "):
|
||||
if rowsl == "draft: true":
|
||||
form['draft'] = True
|
||||
@@ -225,7 +236,7 @@ def parse_form(key):
|
||||
'choices': [],
|
||||
'multichoices': [],
|
||||
'index': current_question + 1,
|
||||
'name': row.strip().rstrip("_:").rstrip(),
|
||||
'name': row.strip().rstrip("_").rstrip(),
|
||||
'open_question': row.strip().endswith("___"),
|
||||
'autoformat': not rowsl.startswith("<")
|
||||
})
|
||||
@@ -237,7 +248,7 @@ def parse_form(key):
|
||||
|
||||
|
||||
def parse_row_date(row):
|
||||
row = row[9:].strip()
|
||||
row = " ".join(row.split(" ")[1:]).strip()
|
||||
if row.lower() == "none":
|
||||
return None
|
||||
try:
|
||||
@@ -304,12 +315,18 @@ def sort_summary(questions, answers):
|
||||
return questions, sorted_answer_list
|
||||
|
||||
|
||||
def time_to_expiry(form):
|
||||
if form['expires'] == None:
|
||||
return "Never"
|
||||
def time_to(what, form):
|
||||
if not what in ('expires','opens'):
|
||||
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.microseconds = 0
|
||||
return "%s (%s to go)"%( form['expires'], time_to_go )
|
||||
return "%s (%s to go)"%( form[what], time_to_go )
|
||||
|
||||
Reference in New Issue
Block a user