diff --git a/migrations/versions/497c76393f9_.py b/migrations/versions/497c76393f9_.py new file mode 100644 index 0000000000000000000000000000000000000000..b9573f06f6e1a8ca04b54cb067d60ebb372b7556 --- /dev/null +++ b/migrations/versions/497c76393f9_.py @@ -0,0 +1,26 @@ +"""empty message + +Revision ID: 497c76393f9 +Revises: c14363cf9b +Create Date: 2015-11-07 21:39:34.419696 + +""" + +# revision identifiers, used by Alembic. +revision = '497c76393f9' +down_revision = 'c14363cf9b' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('topics_index_key', 'topics', type_='unique') + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.create_unique_constraint('topics_index_key', 'topics', ['index']) + ### end Alembic commands ### diff --git a/migrations/versions/c14363cf9b_.py b/migrations/versions/c14363cf9b_.py new file mode 100644 index 0000000000000000000000000000000000000000..b3469e39b7d0c4f2dc7c887fb5d2a290942cd66d --- /dev/null +++ b/migrations/versions/c14363cf9b_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: c14363cf9b +Revises: 201dda3f23e +Create Date: 2015-11-07 20:59:17.755968 + +""" + +# revision identifiers, used by Alembic. +revision = 'c14363cf9b' +down_revision = '201dda3f23e' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('topics', sa.Column('index', sa.Integer(), nullable=True)) + op.create_unique_constraint(None, 'topics', ['index']) + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'topics', type_='unique') + op.drop_column('topics', 'index') + ### end Alembic commands ### diff --git a/models/database.py b/models/database.py index adafb0156d02ec34d186a0c68a03ed658fbd5c21..b3cfe076593c61a97d620d23167e719d49e0cd08 100644 --- a/models/database.py +++ b/models/database.py @@ -45,6 +45,9 @@ class Event(db.Model): def __repr__(self): return "<Event(id={}, name={})>".format(self.id, self.name) + + def sorted_topics(self): + return sorted(self.topics, key=lambda tp: tp.get_index()) class Topic(db.Model): __tablename__ = "topics" @@ -52,19 +55,23 @@ class Topic(db.Model): name = db.Column(db.String, unique=True) mode = db.Column(db.String) event_id = db.Column(db.Integer, db.ForeignKey("events.id"), nullable=False) + index = db.Column(db.Integer) + event = relationship("Event", backref=backref("topics",order_by=id)) def __init__(self, name, mode, event_id): self.name = name self.mode = mode self.event_id = event_id + self.index = None def __repr__(self): - return "<Topic(id={}, name='{}', mode='{}', event_id={})>".format( + return "<Topic(id={}, name='{}', mode='{}', event_id={}, index={})>".format( self.id, self.name, self.mode, - self.event_id + self.event_id, + self.index ) def sorted_statements(self): @@ -76,6 +83,20 @@ class Topic(db.Model): else: return statements + def swap_topics(self, other): + other.index, self.index = self.get_index(), other.get_index() + + def get_index(self): + if self.index == None: + return self.id + return self.index + + def get_next_index(self): + topics = self.event.sorted_topics() + i = topics.index(self) + 1 + if i >= len(topics): + i = -1 + return topics[i].id class Speaker(db.Model): __tablename__ = "speakers" diff --git a/modules/admin.py b/modules/admin.py index f5792e68ab968be246d7de194db0994bce068c67..a18f4e7a82cb1e0ea312985edd5d2bb3b4475073 100644 --- a/modules/admin.py +++ b/modules/admin.py @@ -144,7 +144,8 @@ def topic_show(): form = AddStatementForm() form.topic.data = topic.id statements = topic.sorted_statements() - return render_layout("admin_topic_show.html", topic=topic, form=form, statements=statements) + topics = topic.event.sorted_topics() + return render_layout("admin_topic_show.html", topic=topic, form=form, statements=statements, topics=topics) return redirect(url_for(".index")) @@ -160,7 +161,7 @@ def topic_new(): topic = Topic(form.name.data, form.mode.data, form.event_id.data) db.session.add(topic) db.session.commit() - return redirect(url_for(".topic")) + return redirect(url_for(".event", id=topic.event.id)) event_id = request.args.get("event_id", None) if event_id is None: return redirect(url_for(".index")) @@ -203,6 +204,37 @@ def topic(): topics = Topic.query.all() return render_layout("admin_topic_index.html", topics=topics) +@admin.route("/topic/swap/up") +@login_required +@admin_permission.require() +def topic_swap_up(): + topic_id = request.args.get("id", None) + original_id = request.args.get("original", None) + if topic_id is not None: + topic = Topic.query.filter_by(id=topic_id).first() + topics = topic.event.sorted_topics() + index = topics.index(topic) + if index != 0: + topic.swap_topics(topics[index-1]) + db.session.commit() + return redirect(url_for(".topic_show", id=original_id)) + return redirect(url_for(".index")) + +@admin.route("/topic/swap/down") +@login_required +@admin_permission.require() +def topic_swap_down(): + topic_id = request.args.get("id", None) + original_id = request.args.get("original", None) + if topic_id is not None: + topic = Topic.query.filter_by(id=topic_id).first() + topics = topic.event.sorted_topics() + index = topics.index(topic) + if index != len(topics) - 1: + topic.swap_topics(topics[index+1]) + db.session.commit() + return redirect(url_for(".topic_show", id=original_id)) + return redirect(url_for(".index")) @admin.route("/speaker/rename", methods=["GET", "POST"]) @login_required @@ -286,7 +318,10 @@ def statement_delete(): @login_required @admin_permission.require() def statement_undo(): - statement = Statement.query.filter_by(executed=True).order_by(db.desc(Statement.execution_time)).first() - statement.undo() - db.session.commit() - return redirect(url_for(".topic_show", id=statement.topic.id)) + topic_id = request.args.get("topic_id", None) + if statement_id is not None: + statement = Statement.query.filter_by(executed=True).order_by(db.desc(Statement.execution_time)).first() + statement.undo() + db.session.commit() + return redirect(url_for(".topic_show", id=topic_id)) + diff --git a/static/css/style.css b/static/css/style.css index 488019bce73a3891d5a415233da94276fa3a50fe..e83d82b42755302705c069e2f18a275c962506fc 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -109,3 +109,25 @@ text-decoration: none; vertical-align: text-top; } + +th.rede-large-text { + font-size: 18pt; +} + +th.rede-medium-text { + font-size: 18pt; + color: darkred; +} + +.rede-list-no-bullet { + list-style-type: none; + padding-left: 1pc; +} + +.rede-list-point-big { + font-weight: bold; +} + +.rede-list-point-normal { + font-weight: normal; +} diff --git a/templates/admin_event_index.html b/templates/admin_event_index.html index 42782b69572b489fd450a322908555366b7eb0ad..d6660b99f9c2930b2a3c78a0cf6d2cb0500d8704 100644 --- a/templates/admin_event_index.html +++ b/templates/admin_event_index.html @@ -7,7 +7,6 @@ <thead> <tr> <th class="mdl-data-table__cell--non-numeric">Name</th> - <th class="mdl-data-table__cell--non-numeric">Mode</th> <th class="mdl-data-table__cell--non-numeric">Edit</th> <th class="mdl-data-table__cell--non-numeric">Delete</th> </tr> diff --git a/templates/admin_topic_show.html b/templates/admin_topic_show.html index 03e453f6123550fc6299c92a7b08db6991704bfa..cc6c429f532f0f86bdbd859c6e6e39f60997202e 100644 --- a/templates/admin_topic_show.html +++ b/templates/admin_topic_show.html @@ -6,10 +6,14 @@ <div class="mdl-cell mdl-cell--6-col mdl-cell--5-col-tablet mdl-cell--4-col-phone mdl-grid mdl-grid--no-spacing"> <table class="mdl-data-table mdl-js-table mdl-shadow--2dp mdl-cell mdl-cell--12-col"> <thead> + <tr> + <th class="mdl-data-table__cell-non-numeric rede-large-text">{{ topic.name }}</th> + <th class="mdl-data-table__cell-non-numeric rede-medium-text" colspan=2>{{ topic.mode }}</th> + <th class="mdl-data-table__cell-non-numeric rede-medium-text"><a href="{{ url_for(".topic_edit", id=topic.id) }}"><i class="material-icons">edit</i></a></th> + </tr> <tr> <th class="mdl-data-table__cell--non-numeric">Speaker</th> - <th class="mdl-data-table__cell--non-numeric">Topic</th> - <th class="mdl-data-table__cell--non-numeric">Count</th> + <th class="mdl-data-table__cell">Count</th> <th class="mdl-data-table__cell--non-numeric">Done</th> <th class="mdl-data-table__cell--non-numeric">Edit</th> <th class="mdl-data-table__cell--non-numeric">Remove</th> @@ -19,8 +23,7 @@ {% for statement in topic.sorted_statements() %} <tr> <td class="mdl-data-table__cell--non-numeric">{{ statement.speaker.identifier() }}</td> - <td class="mdl-data-table__cell--non-numeric">{{ statement.topic.name }}</td> - <td class="mdl-data-table__cell--non-numeric">{{ statement.speaker.count(statement.topic) }}</td> + <td class="mdl-data-table__cell">{{ statement.speaker.count(statement.topic) }}</td> <td class="mdl-data-table__cell--non-numeric"> <a href="{{ url_for(".statement_done", id=statement.id, topic_id=topic.id) }}"> <i class="material-icons">done</i> @@ -46,14 +49,39 @@ <div class="mdl-cell mdl-cell--3-col mdl-cell--3-col-tablet mdl-cell--4-col-phone mdl-grid mdl-grid--no-spacing"> {{ render_form(form, action_url=url_for(".statement_new"), action_text="Add", title="Add Statement", class_="mdl-card mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-cell--8-col-tablet mdl-cell--4-col-phone", btn_list=[("","Add Statement","add_statement"), ("redl-btn-meta","Add Meta","add_meta_statement")] ) }} <div class="mdl-cell mdl-card mdl-shadow--2dp mdl-cell--12-col mdl-cell--8-col-tablet mdl-cell--4-col-phone"> - <ul> + <ul class="rede-list-no-bullet"> {% if topic.sorted_statements()|length() > 0 %} <li> <a href="{{ url_for(".statement_done", id=topic.sorted_statements()[0].id, topic_id=topic.id) }}" class="rede-href"><i class="material-icons" role="presentation">redo</i> Next</a> </li> {% endif %} <li><a href="{{ url_for(".statement_undo") }}" class="rede-href"><i class="material-icons" role="presentation">undo</i> Previous</a></li> + <li><a href="{{ url_for(".topic_show", id=topic.get_next_index()) }}"><i class="material-icons">arrow_forward</i> Next Topic</a></li> </ul> </div> </div> + <div class="mdl-cell mdl-cell--3-col mdl-cell--3-col-tablet mdl-cell--4-col-phone mdl-card mdl-shadow--2dp"> + <div class="mdl-card__title"> + <h4 class="mdl-card__title-text">Topics</h4> + </div> + <table> + {% for t in topics %} + <tr class="{% if t == topic %}rede-list-point-big{% else %}rede-list-point-normal{% endif %}"> + <td> + {% if t != topics[0] %} + <a href="{{ url_for(".topic_swap_up", id=t.id, original=topic.id) }}"><i class="material-icons">keyboard_arrow_up</i></a> + {% endif %} + </td> + <td> + {{ t.name }} + </td> + <td> + {% if t != topics[-1] %} + <a href="{{ url_for(".topic_swap_down", id=t.id, original=topic.id) }}"><i class="material-icons">keyboard_arrow_down</i></a> + {% endif %} + </td> + <tr> + {% endfor %} + </table> + </div> {% endblock %}