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