From a4b6c53fcfb5759e928c0b80be76780ff8be454d Mon Sep 17 00:00:00 2001
From: Robin Sonnabend <robin@fsmpi.rwth-aachen.de>
Date: Sun, 8 Nov 2015 13:30:06 +0100
Subject: [PATCH] Benutzeransicht

---
 migrations/versions/3c75c74bb94_.py |  26 +++++
 models/database.py                  |  12 ++-
 modules/speech.py                   | 151 +++++-----------------------
 templates/content_index.html        |  31 +++---
 templates/layout.html               |   5 +-
 templates/speech_content_index.html |  37 +++++++
 templates/speech_content_show.html  |  21 ----
 templates/speech_index.html         |  57 +----------
 templates/speech_show.html          |  10 --
 9 files changed, 111 insertions(+), 239 deletions(-)
 create mode 100644 migrations/versions/3c75c74bb94_.py
 create mode 100644 templates/speech_content_index.html
 delete mode 100644 templates/speech_content_show.html
 delete mode 100644 templates/speech_show.html

diff --git a/migrations/versions/3c75c74bb94_.py b/migrations/versions/3c75c74bb94_.py
new file mode 100644
index 0000000..783756c
--- /dev/null
+++ b/migrations/versions/3c75c74bb94_.py
@@ -0,0 +1,26 @@
+"""empty message
+
+Revision ID: 3c75c74bb94
+Revises: 256d9df3492
+Create Date: 2015-11-08 13:06:23.520483
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '3c75c74bb94'
+down_revision = '256d9df3492'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.drop_constraint('events_current_topic_id_fkey', 'events', type_='foreignkey')
+    ### end Alembic commands ###
+
+
+def downgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.create_foreign_key('events_current_topic_id_fkey', 'events', 'topics', ['current_topic_id'], ['id'])
+    ### end Alembic commands ###
diff --git a/models/database.py b/models/database.py
index 7346687..453e893 100644
--- a/models/database.py
+++ b/models/database.py
@@ -41,15 +41,13 @@ class Event(db.Model):
     name = db.Column(db.String, unique=True)
     paused = db.Column(db.Boolean)
     paused_until = db.Column(db.DateTime)
-    current_topic_id = db.Column(db.Integer, db.ForeignKey("topics.id"))
-    
-    current_topic = relationship("Topic", foreign_keys=[current_topic_id])
+    current_topic_id = db.Column(db.Integer)
     
     def __init__(self, name, paused=False, current_topic_id=None):
         self.name = name
         self.paused = paused
         self.paused_until = datetime(1970, 1, 1)
-        self.current_topic_id = current_topic_id or 0
+        self.current_topic_id = current_topic_id or -1
     
     def __repr__(self):
         return "<Event(id={}, name={}, paused={}, paused_until={})>".format(
@@ -61,6 +59,12 @@ class Event(db.Model):
     
     def sorted_topics(self):
         return sorted(self.topics, key=lambda tp: tp.get_index())
+    
+    def get_current_topic(self):
+        candidates = [topic for topic in self.topics if topic.id == self.current_topic_id]
+        if len(candidates) < 1:
+            return None
+        return candidates[0]
 
 class Topic(db.Model):
     __tablename__ = "topics"
diff --git a/modules/speech.py b/modules/speech.py
index 1670d00..b205f2c 100644
--- a/modules/speech.py
+++ b/modules/speech.py
@@ -1,7 +1,7 @@
 from flask import Blueprint, redirect, url_for, request, flash, abort, send_file, Response
 from flask.ext.login import login_required
 
-from models.database import User, Statement, Speaker, Topic
+from models.database import User, Statement, Speaker, Topic, Event
 from models.forms import AddStatementForm
 
 from shared import db, admin_permission, user_permission
@@ -14,142 +14,37 @@ import config
 
 speech = Blueprint("speech", __name__)
 
-"""
-def query_statements(mode, topic_id):
-    statements = db.session.query(Statement).filter_by(topic_id=topic_id).all()
-    speakers = db.session.query(Speaker).filter_by(topic_id=topic_id).all()
-    if mode == "balanced" or mode == "pending":
-        count = { speaker.id: 0 for speaker in speakers }
-        for statement in statements:
-            if statement.speaker in count:
-                count[statement.speaker] += 1
-            else:
-                count[statement.speaker] = 1
-        sorted_speakers = sorted(speakers, key=lambda sp: count[sp.id])
-        result = []
-        for speaker in sorted_speakers:
-            pending_statements = [statement for statement in statements if statement.speaker == speaker.id and not statement.executed]
-            if len(pending_statements) > 0:
-                result.append((pending_statements[0], speaker, count[speaker.id]))
-        return result
-    
-    if mode == "fifo":
-        speaker_by_id = { speaker.id: speaker for speaker in speakers }
-        result = [(statement, speaker_by_id[statement.speaker], 0) for statement in statements if not statement.executed]
-        return result
-    
-    print("unknown querying mode {}".format(mode))
-"""
 
 @speech.route("/")
 def index():
-    topic_id = request.args.get("topic", None) 
-    mode = request.args.get("mode", None)
-    meta = []
-    if topic_id is not None and topic_id != "-1":
-        topic = Topic.query.filter_by(id=topic_id).first()
-        form = AddStatementForm()
-        form.topic.data = topic.id
-        meta.append((query_statements(mode if mode is not None else topic.mode, topic_id), form, topic))
-    else:
-        for topic in Topic.query.all():
-            form = AddStatementForm()
-            form.topic.data = topic.id
-            meta.append((query_statements(mode if mode is not None else topic.mode, topic.id), form, topic))
-        topic_id = -1
-    return render_layout("speech_index.html", meta=meta, topic_id=topic_id, mode=mode)
-
-@speech.route("/show")
-def show():
-    topic_id = request.args.get("topic", None)
-    mode = request.args.get("mode", None) 
-    meta = []
-    if topic_id is not None and topic_id is not "-1":
-        topic = Topic.query.filter_by(id=topic_id).first()
-        meta.append((query_statements(mode if mode is not None else topic.mode, topic_id), topic))
+    event_id = request.args.get("event", None)
+    events = []
+    if event_id is not None and event_id.isnumeric() and int(event_id) > -1:
+        event = Event.query.filter_by(id=event_id).first()
+        if event is not None:
+            events.append(event)
     else:
-        for topic in Topic.query.all():
-            meta.append((query_statements(mode if mode is not None else topic.mode, topic.id), topic))
-    return render_layout("speech_show.html", mode=mode, meta=meta, topic_id=topic_id)
+        events = Event.query.all()
+    return render_layout("speech_index.html", events=events, event=-1 if len(events) != 1 else events[0].id)
 
 @speech.route("/update")
 def update():
-    topic_id = request.args.get("topic", None)
-    mode = request.args.get("mode", None) 
-    meta = []
-    if topic_id is not None and topic_id != "-1":
-        topic = Topic.query.filter_by(id=topic_id).first()
-        meta.append((query_statements(mode if mode is not None else topic.mode, topic_id), topic))
-    else:
-        for topic in Topic.query.all():
-            meta.append((query_statements(mode if mode is not None else topic.mode, topic.id), topic))
-    return render_layout("speech_content_show.html", mode=mode, meta=meta)
-
-
-@speech.route("/add", methods=["GET", "POST"])
-@user_permission.require()
-def add():
-    speaker_name = request.args.get("speaker", None)
-    add_form = AddStatementForm()
-    if add_form.validate_on_submit():
-        speaker_name = add_form["speaker_name"].data
-        topic_id = add_form["topic"].data
-    if speaker_name is None or topic_id is None:
-        flash("Missing data", "alert-error")
-        return redirect(url_for(".index"))
-    speaker = Speaker.query.filter_by(name=speaker_name).filter_by(topic=topic_id).first()
-    if not speaker:
-        speaker = Speaker(speaker_name, topic_id)
-        db.session.add(speaker)
-        db.session.commit()
-    if Statement.query.filter_by(speaker=speaker.id).filter_by(topic=topic_id).filter_by(executed=False).count() > 0:
-        flash("Speaker already listet", "alert-error")
-        return redirect(url_for(request.args.get("next") or ".show"))
-    statement = Statement(speaker.id, topic_id)
-    db.session.add(statement)
-    db.session.commit()
-    mode = request.args.get("mode", None)
-    topic_id = request.args.get("topic", None)
-    return redirect(url_for(request.args.get("next") or ".index", mode=mode, topic=topic_id))
-
-
-@speech.route("/cancel")
-@user_permission.require()
-def cancel():
-    statement_id = request.args.get("statement", None)
-    topic_id = request.args.get("topic", -1)
-    if not statement_id:
-        flash("Missing statement id", "alert-error")
-        return redirect(url_for(request.args.get("next") or ".index"))
-    statement = Statement.query.filter_by(id=statement_id).first()
-    db.session.delete(statement)
-    db.session.commit()
-    flash("Statement canceled", "alert-success")
-    mode = request.args.get("mode", None)
-    return redirect(url_for(request.args.get("next") or ".index", mode=mode, topic=topic_id))
-
-@speech.route("/done")
-@user_permission.require()
-def done():
-    statement_id = request.args.get("statement", None)
-    topic_id = request.args.get("topic", -1)
-    if not statement_id:
-        flash("Missing statement id", "alert-error")
-        return redirect(url_for(request.args.get("next") or ".index"))
-    statement = Statement.query.filter_by(id=statement_id).first()
-    if statement.done():
-        db.session.commit()
+    event_id = request.args.get("event", None)
+    events = []
+    if event_id is not None and event_id.isnumeric() and int(event_id) > -1:
+        event = Event.query.filter_by(id=event_id).first()
+        if event is not None:
+            events.append(event)
     else:
-        flash("Statement already done", "alert-error")
-    mode = request.args.get("mode", None)
-    return redirect(url_for(request.args.get("next") or ".index", mode=mode, topic=topic_id))
+        events = Event.query.all()
+    return render_layout("speech_content_index.html", events=events)
 
-@speech.route("/update_show.js")
-def update_show_js():
-    update_interval = config.UPDATE_SHOW_INTERVAL or 1
+@speech.route("/update_index.js")
+def update_index_js():
+    update_interval = config.UPDATE_INDEX_INTERVAL or 1
     div = "rede-content-div"
     mode = request.args.get("mode", None)
-    topic_id = request.args.get("topic", -1)
-    target_url = url_for(".update", mode=mode, topic=topic_id)
-    return render_layout("update.js", update_interval=update_interval, div=div, target_url=target_url, prefix="update_show_")
+    event_id = request.args.get("event", -1)
+    target_url = url_for(".update", event=event_id)
+    return render_layout("update.js", update_interval=update_interval, div=div, target_url=target_url, prefix="update_index_")
 
diff --git a/templates/content_index.html b/templates/content_index.html
index 97f49dc..966d8ed 100644
--- a/templates/content_index.html
+++ b/templates/content_index.html
@@ -1,21 +1,18 @@
-    {% for (statement, speaker, count), topic in meta %}
     <div class="mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--4-col-phone mdl-card">
+    {% if event.current_topic_id != -1 %}
         <div class="mdl-card__title">
-            <h3 class="mdl-card__title-text">{{ topic.name }}: {{ speaker.name }}</h3>
-        </div>
-        <div class="mdl-card__actions">
-            {% if current_user.is_authenticated and "user" in current_user.roles %}
-            <a href="{{ url_for("speech.index", event=event.id) }}">
-                <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
-                    <i class="material-icons" role="presentation">build</i>
-                </button>
-            </a>
-            {% endif %}
-            <a href="{{ url_for("speech.show", topic=event.id) }}">
-                <button type="button" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
-                    <i class="material-icons" role="presentation">list</i>
-                </button>
-            </a>
+            <h3 class="mdl-card__title-text">{{ event.current_topic.name }}: {{ event.current_topic.sorted_statements()[0].speaker.name }}</h3>
         </div>
+        {% if event.get_current_topic() %}
+        <table class="mdl-data-table mdl-js-table">
+        {% for statement in event.get_current_topic().sorted_statements() %}
+            <tr>
+                <td>statement.speaker.name</td>
+            </tr>
+        {% endfor %}
+        </table>
+        {% endif %}
+    {% else %}
+        No topic selected
+    {% endif %}
     </div>
-    {% endfor %}
diff --git a/templates/layout.html b/templates/layout.html
index ee9b659..f71a307 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -79,10 +79,7 @@
             </div>
         </header>
         <nav class="rede-navigation mdl-navigation mdl-color--blue-grey-800">
-            {% if current_user.is_authenticated and "user" in current_user.roles %}
-            <a class="mdl-navigation__link" href="{{ url_for("speech.index") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">build</i>Handle speakers</a>
-            {% endif %}
-            <a class="mdl-navigation__link" href="{{ url_for("speech.show") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">announcement</i>Pending speakers</a>
+            <a class="mdl-navigation__link" href="{{ url_for("speech.index") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">announcement</i>Pending speakers</a>
             {% if current_user.is_authenticated and "admin" in current_user.roles %}
             <a class="mdl-navigation__link" href="{{ url_for("admin.index") }}"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">computer</i>Administration</a>
             {% block additional_sidelinks %}
diff --git a/templates/speech_content_index.html b/templates/speech_content_index.html
new file mode 100644
index 0000000..a0a8ac4
--- /dev/null
+++ b/templates/speech_content_index.html
@@ -0,0 +1,37 @@
+{% for event in events %}    
+    <div class="mdl-cell mdl-cell--6-col mdl-cell--8-col-tablet mdl-cell--4-col-phone mdl-card mdl-shadow--2dp">
+    {% if not event.paused %}
+        {% if event.current_topic_id != -1 and event.get_current_topic() %}
+            <div class="mdl-card__title">
+                {{ event.name }}: {{ event.get_current_topic().name }}
+            </div>
+            <table class="mdl-data-table mdl-js-table" style="min-width: 100%">
+                <thead>
+                    <tr>
+                        <th class="mdl-data-table__cell--non-numeric">Speaker</th>
+                        <th class="mdl-data-table__cell">Count</th>
+                    </tr>
+                </thead>
+                <tbody>
+                {% for statement in event.get_current_topic().sorted_statements() %}
+                    <tr>
+                        <td class="mdl-data-table__cell--non-numeric">{{ statement.speaker.identifier() }}</td>
+                        <td class="mdl-data-table__cell">{{ statement.speaker.count(event.current_topic) }}</td>
+                    </tr>
+                {% endfor %}
+                </tbody>
+            </table>
+        {% else %}
+            <div class="mdl-card__title">
+                {{ event.name }}: No topic set
+            </div>
+        {% endif %}
+    {% else %}
+        <div class="mdl-card__title rede-paused-title">
+            <h4 class="mdl-card__title-text rede-paused-title-text">
+                {{ event.name}}: Paused until {{ event.paused_until.strftime("%H:%M") }}
+            </h4>
+        </div>
+    {% endif %}
+    </div>
+{% endfor %}
diff --git a/templates/speech_content_show.html b/templates/speech_content_show.html
deleted file mode 100644
index dc0fbd3..0000000
--- a/templates/speech_content_show.html
+++ /dev/null
@@ -1,21 +0,0 @@
-{% from "macros.html" import render_form %}
-    {% for statements, topic in meta %}
-        <table class="mdl-data-table mdl-js-table mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-cell--8-col-tablet mdl-cell--4-col-phone">
-            <thead>
-                <tr>
-                    <th class="mdl-data-table__cell--non-numeric">Speaker for {{ topic.name }}</th>
-                </tr>
-            </thead>
-            <tbody>
-            {% for statement, speaker, count in statements %}
-                {% if not statement.executed %}
-                    <tr>
-                        <td class="mdl-data-table__cell--non-numeric">
-                            <h5>{{ speaker.name }}</h5>
-                        </td>
-                    </tr>
-                {% endif %}
-            {% endfor %}
-            </tbody>
-        </table>
-    {% endfor %}
diff --git a/templates/speech_index.html b/templates/speech_index.html
index 7ae308a..948f7d0 100644
--- a/templates/speech_index.html
+++ b/templates/speech_index.html
@@ -1,63 +1,10 @@
 {% extends "layout.html" %}
 {% from "macros.html" import render_form %}
 {% block title %}Statements{% endblock %}
-
 {% block additional_js %}
-<script src="{{ url_for('static', filename='js/nextbutton.js') }}" async></script>
-{% endblock %}
-
-{% block additional_sidelinks %}
-<a href="#" class="mdl-navigation__link" onclick="setkeyhash()"><i class="mdl-colo-text--blue-grey-400 material-icons" role="presentation">keyboard</i>Set Next Key</a>
+    <script src="{{ url_for(".update_index_js", event=event) }}" async></script>
 {% endblock %}
 
 {% block content %}
-    {% for statements, add_form, topic in meta %}
-        <table id="next-speaker-table" class="mdl-data-table mdl-js-table mdl-shadow--2dp mdl-cell mdl-cell--6-col mdl-cell--4-col-tablet mdl-cell--4-col-phone sortable">
-            <thead>
-                <tr>
-                    <th class="mdl-data-table__cell--non-numeric">Speaker</th>
-                    {% if (mode is not none and mode == "balanced") or (mode is none and topic.mode == "balanced") %}
-                    <th>Count</th>
-                    {% endif %}
-                    {% if "user" in current_user.roles %}
-                    <th class="mdl-data-table__cell--non-numeric">Done</th>
-                    <th class="mdl-data-table__cell--non-numeric">Cancel</th>
-                    {% endif %}
-                </tr>
-            </thead>
-            <tbody>
-            {% for statement, speaker, count in statements %}
-                <tr>
-                    <td class="mdl-data-table__cell--non-numeric">
-                        <h5>{{ speaker.name }}</h5>
-                    </td>
-                    {% if (mode is not none and mode == "balanced") or (mode is none and topic.mode == "balanced") %}
-                    <td>
-                        <h5>{{ count }}</h5>
-                    </td>
-                    {% endif %}
-                    {% if "user" in current_user.roles %}
-                    <td class="mdl-data-table__cell--non-numeric">
-                        <a href="{{ url_for(".done", statement=statement.id, next=".index", topic=event_id) }}">
-                            <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored">
-                                <i class="material-icons">done</i>
-                            </button>
-                        </a>
-                    </td>
-                    <td class="mdl-data-table__cell--non-numeric">
-                        <a href="{{ url_for(".cancel", statement=statement.id, next=".index", topic=event_id) }}">
-                            <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab">
-                                <i class="material-icons">delete</i>
-                            </button>
-                        </a>
-                    </td>
-                    {% endif %}
-                </tr>
-            {% endfor %}
-            </tbody>
-        </table>
-        {% if current_user.is_authenticated and "user" in current_user.roles %}
-            {{ render_form(add_form, action_url=url_for('.add', next=".index", event=event_id), action_text="Add", title="Add Speaker to {}".format(event.name)) }}
-        {% endif %}
-    {% endfor %}
+    {% include "speech_content_index.html" %}
 {% endblock %}
diff --git a/templates/speech_show.html b/templates/speech_show.html
deleted file mode 100644
index 82d4eb5..0000000
--- a/templates/speech_show.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% extends "layout.html" %}
-{% from "macros.html" import render_form %}
-{% block title %}Statements{% endblock %}
-{% block additional_js %}
-    <script src="{{ url_for(".update_show_js", mode=mode, topic=event_id) }}" async></script>
-{% endblock %}
-
-{% block content %}
-    {% include "speech_content_show.html" %}
-{% endblock %}
-- 
GitLab