]> WPIA git - motion.git/commitdiff
add: cancel running motion (with comment)
authorFelix Dörre <felix@dogcraft.de>
Fri, 17 Nov 2017 11:07:27 +0000 (12:07 +0100)
committerFelix Dörre <felix@dogcraft.de>
Fri, 17 Nov 2017 11:07:27 +0000 (12:07 +0100)
motion.py
schema.sql
templates/motion.html
templates/single_motion.html

index b74438d3a92aaaa89f5ae7820f1fd145c729113a..15431c71396feda18540745f01bbaadbd69fa76e 100644 (file)
--- a/motion.py
+++ b/motion.py
@@ -35,19 +35,21 @@ def init_db():
 @app.route("/")
 def main():
     start=int(request.args.get("start", "-1"));
-    q = "SELECT *, motion.deadline > CURRENT_TIMESTAMP AS running FROM motion LEFT JOIN (SELECT motion_id, voter_id, "\
+    q = "SELECT motion.*, votes.*, poser.email AS poser, canceler.email AS canceler, (motion.deadline > CURRENT_TIMESTAMP AND canceled is NULL) AS running FROM motion LEFT JOIN (SELECT motion_id, voter_id, "\
                              + "COUNT(CASE WHEN result='yes' THEN 'yes' ELSE NULL END) as yes, "\
                              + "COUNT(CASE WHEN result='no' THEN 'no' ELSE NULL END) as no, "\
                              + "COUNT(CASE WHEN result='abstain' THEN 'abstain' ELSE NULL END) as abstain "\
-                             + "FROM vote GROUP BY motion_id, voter_id) as votes ON votes.motion_id=motion.id "
+                             + "FROM vote GROUP BY motion_id, voter_id) as votes ON votes.motion_id=motion.id "\
+                             + "LEFT JOIN voter poser ON poser.id = motion.posed_by "\
+                             + "LEFT JOIN voter canceler ON canceler.id = motion.canceled_by "
     prev=None
     if start == -1:
-        p = get_db().prepare(q + "ORDER BY id DESC LIMIT 11")
+        p = get_db().prepare(q + "ORDER BY motion.id DESC LIMIT 11")
         rv = p()
     else:
-        p = get_db().prepare(q + "WHERE id <= $1 ORDER BY id DESC LIMIT 11")
+        p = get_db().prepare(q + "WHERE motion.id <= $1 ORDER BY motion.id DESC LIMIT 11")
         rv = p(start)
-        rs = get_db().prepare("SELECT id FROM motion WHERE id > $1 ORDER BY id ASC LIMIT 10")(start)
+        rs = get_db().prepare("SELECT id FROM motion WHERE motion.id > $1 ORDER BY id ASC LIMIT 10")(start)
         if len(rs) == 10:
             prev = rs[9][0]
         else:
@@ -59,16 +61,33 @@ def put_motion():
     time = int(request.form.get("days", "3"));
     if time not in times:
         return "Error, invalid length"
-    p = get_db().prepare("INSERT INTO motion(\"name\", \"content\", \"deadline\") VALUES($1, $2, CURRENT_TIMESTAMP + $3 * interval '1 days')")
-    p(request.form.get("title", ""), request.form.get("content",""), time)
+    p = get_db().prepare("INSERT INTO motion(\"name\", \"content\", \"deadline\", \"posed_by\") VALUES($1, $2, CURRENT_TIMESTAMP + $3 * interval '1 days', $4)")
+    p(request.form.get("title", ""), request.form.get("content",""), time, voter)
     return redirect("/")
 
 voter=1
 
-@app.route("/motion/<int:id>")
-def show_motion(id):
-    p = get_db().prepare("SELECT motion.*, motion.deadline > CURRENT_TIMESTAMP AS running, vote.result FROM motion LEFT JOIN vote on vote.motion_id=motion.id AND vote.voter_id=$2 WHERE id=$1")
-    rv = p(id,voter)
+def motion_edited(motion):
+    return redirect("/?start=" + str(motion) + "#motion-" + str(motion))
+
+@app.route("/motion/<int:id>/cancel", methods=['POST'])
+def cancel_motion(id):
+    if request.form.get("reason", "none") == "none":
+        return "Error, form requires reason"
+    rv = get_db().prepare("UPDATE motion SET canceled=CURRENT_TIMESTAMP, cancelation_reason=$1, canceled_by=$2 WHERE id=$3 AND canceled is NULL")(request.form.get("reason", ""), voter, id)
+    print(rv)
+    return motion_edited(id)
+
+@app.route("/motion/<int:motion>")
+def show_motion(motion):
+    p = get_db().prepare("SELECT motion.*, poser.email AS poser, canceler.email AS canceler, (motion.deadline > CURRENT_TIMESTAMP AND canceled is NULL) AS running, vote.result FROM motion "\
+                         + "LEFT JOIN vote on vote.motion_id=motion.id AND vote.voter_id=$2 "\
+                         + "LEFT JOIN voter poser ON poser.id = motion.posed_by "\
+                         + "LEFT JOIN voter canceler ON canceler.id = motion.canceled_by "
+                         + "WHERE motion.id=$1")
+    rv = p(motion,voter)
+    if len(rv) == 0:
+        return "Error, motion not found" # TODO 404
     return render_template('single_motion.html', motion=rv[0])
 
 @app.route("/motion/<int:motion>/vote", methods=['POST'])
@@ -82,10 +101,10 @@ def vote(motion):
         p = db.prepare("SELECT * FROM vote WHERE motion_id = $1 AND voter_id = $2")
         rv = p(motion, voter)
         if len(rv) == 0:
-            db.prepare("INSERT INTO vote (motion_id, voter_id, result) VALUES($1,$2,$3)")(motion,voter,v)
+            db.prepare("INSERT INTO vote(motion_id, voter_id, result) VALUES($1,$2,$3)")(motion,voter,v)
         else:
             db.prepare("UPDATE vote SET result=$3, entered=CURRENT_TIMESTAMP WHERE motion_id=$1 AND voter_id = $2")(motion,voter,v)
-    return redirect("/?start=" + str(motion) + "#motion-" + str(motion))
+    return motion_edited(motion)
 
-# TODO cancel running motion (with comment)
 # TODO authentication/user management
+# TODO load config with flask mechanism
index 6fa7a673a500179d7ecfef850adf040b4701575b..b3a6eaff4fc108db7b00420cbf0949859a8cd8aa 100644 (file)
@@ -1,5 +1,5 @@
 DROP TABLE IF EXISTS voter;
-CREATE TABLE voter (id serial NOT NULL, name VARCHAR(10) NOT NULL, PRIMARY KEY(id));
+CREATE TABLE voter (id serial NOT NULL, email VARCHAR(255) NOT NULL, PRIMARY KEY(id));
 
 
 DROP TABLE IF EXISTS motion;
@@ -7,9 +7,14 @@ CREATE TABLE motion (id serial NOT NULL,
                    name VARCHAR(250) NOT NULL,
                    content text NOT NULL,
                    posed timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+                   posed_by int NOT NULL,
                    deadline timestamp NOT NULL DEFAULT (CURRENT_TIMESTAMP + interval '3 days'),
+                   canceled timestamp NULL DEFAULT NULL,
+                   cancelation_reason text NULL DEFAULT NULL,
+                   canceled_by int NULL DEFAULT NULL,
                    PRIMARY KEY(id));
 
+
 DROP TABLE IF EXISTS vote;
 DROP TYPE IF EXISTS "vote_type";
 CREATE TYPE "vote_type" AS ENUM ('yes', 'no', 'abstain');
index 6609d20920c455f4323e9cbd3213781d97eb6666..f0d28bd27b1d86250b4a584f4255f0745955dd8c 100644 (file)
@@ -1,10 +1,14 @@
 <div class="motion panel panel-default" id="motion-{{motion.id}}">
   <div class="motion-title panel-heading">
     <a href="/motion/{{motion.id}}" class="anchor">#</a>
-    <span class="title-text">{{motion.name}}</span> ({{ 'Running' if motion.running else 'Finished' }})
+    <span class="title-text">{{motion.name}}</span> ({{ 'Running' if motion.running else ('Canceled' if motion.canceled != None else 'Finished') }})
     <div class="date">
-      <div>Posed: {{motion.posed|timestamp}}</div>
+      <div>Posed: {{motion.posed|timestamp}} by {{motion.poser}}</div>
+{%- if motion.canceled != None %}
+      <div>Canceled: {{motion.canceled|timestamp}} by {{motion.canceler}}</div></div>
+{%- else %}
       <div>Votes until: {{motion.deadline|timestamp}}</div></div>
+{%- endif %}
   </div>
   <div class="panel-body">
     <p>{{motion.content}}</p>
@@ -14,6 +18,9 @@
 {{vote|capitalize}} <span class="badge">{{motion[vote]}}</span><br>
 {%- endfor %}
     </p>
+{%- endif %}
+{%- if motion.canceled != None %}
+    <p>Cancelation reason: {{motion.cancelation_reason}}</p>
 {%- endif %}
   </div>
 {%- block content %}{% endblock %}
index 1078343cb72198a4cb8bfb783cbce51b797d5068..cf5c94e0ea2e9a8b4dc4593400c697b284bb83cd 100644 (file)
@@ -10,5 +10,9 @@ Motion: {{motion.name}}
 <button type="submit" class="btn btn-{{ 'success' if vote == motion.result else 'primary' }}" name="vote" value="{{vote}}" id="vote-{{vote}}">{{vote}}</button>
 {%- endfor %}
 </form>
+<form action="/motion/{{motion.id}}/cancel" method="POST">
+<input type="text" name="reason" required="yes">
+<button type="submit">Cancel</button>
+</form>
 {%- endif %}
 {%- endblock %}