Skip to content
Snippets Groups Projects
Commit 9762468a authored by Robin Sonnabend's avatar Robin Sonnabend
Browse files

Fixed todos

parent 6ebc35e9
Branches
No related tags found
No related merge requests found
"""empty message
Revision ID: 24bd2198a626
Revises: 2e2682dfac21
Create Date: 2017-02-24 17:20:07.135782
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '24bd2198a626'
down_revision = '2e2682dfac21'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('todos', sa.Column('number', sa.Integer(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('todos', 'number')
# ### end Alembic commands ###
"""empty message
Revision ID: 2e2682dfac21
Revises: aebae2c4523d
Create Date: 2017-02-24 16:31:01.729972
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '2e2682dfac21'
down_revision = 'aebae2c4523d'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('todos', sa.Column('is_id_fixed', sa.Boolean(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('todos', 'is_id_fixed')
# ### end Alembic commands ###
......@@ -102,17 +102,17 @@ class Protocol(db.Model):
return Error(self.id, action, name, now, description)
def fill_from_remarks(self, remarks):
new_date = datetime.strptime(remarks["Datum"].value, "%d.%m.%Y").date()
new_date = datetime.strptime(remarks["Datum"].value.strip(), "%d.%m.%Y").date()
if self.date is not None:
if new_date != self.date:
raise DateNotMatchingException(original_date=self.date, protocol_date=new_date)
else:
self.date = new_date
self.start_time = datetime.strptime(remarks["Beginn"].value, "%H:%M").time()
self.end_time = datetime.strptime(remarks["Ende"].value, "%H:%M").time()
self.author = remarks["Autor"].value
self.participants = remarks["Anwesende"].value
self.location = remarks["Ort"].value
self.start_time = datetime.strptime(remarks["Beginn"].value.strip(), "%H:%M").time()
self.end_time = datetime.strptime(remarks["Ende"].value.strip(), "%H:%M").time()
self.author = remarks["Autor"].value.strip()
self.participants = remarks["Anwesende"].value.strip()
self.location = remarks["Ort"].value.strip()
def is_done(self):
return self.done
......@@ -160,6 +160,9 @@ class Protocol(db.Model):
return public_candidates[0]
return None
def get_template(self):
return render_template("protocol-template.txt", protocol=self)
def delete_orphan_todos(self):
orphan_todos = [
todo for todo in self.todos
......@@ -244,22 +247,28 @@ def on_document_delete(mapper, connection, document):
class Todo(db.Model):
__tablename__ = "todos"
id = db.Column(db.Integer, primary_key=True)
number = db.Column(db.Integer)
who = db.Column(db.String)
description = db.Column(db.String)
tags = db.Column(db.String)
done = db.Column(db.Boolean)
is_id_fixed = db.Column(db.Boolean, default=False)
protocols = relationship("Protocol", secondary="todoprotocolassociations", backref="todos")
def __init__(self, who, description, tags, done):
def __init__(self, who, description, tags, done, number=None):
self.who = who
self.description = description
self.tags = tags
self.done = done
self.number = number
def __repr__(self):
return "<Todo(id={}, who={}, description={}, tags={}, done={})>".format(
self.id, self.who, self.description, self.tags, self.done)
return "<Todo(id={}, number={}, who={}, description={}, tags={}, done={})>".format(
self.id, self.number, self.who, self.description, self.tags, self.done)
def get_id(self):
return self.number if self.number is not None else self.id
def get_first_protocol(self):
candidates = sorted(self.protocols, key=lambda p: p.date)
......
......@@ -304,27 +304,12 @@ def new_protocol():
protocol = Protocol(protocoltype.id, form.date.data)
db.session.add(protocol)
db.session.commit()
return redirect(request.args.get("next") or url_for("list_protocols"))
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
type_id = request.args.get("type_id")
if type_id is not None:
form.protocoltype.data = type_id
return render_template("protocol-new.html", form=form, upload_form=upload_form, protocoltypes=protocoltypes)
@app.route("/protocol/edit/<int:protocol_id>", methods=["POST"])
@login_required
def edit_protocol(protocol_id):
user = current_user()
protocol = Protocol.query.filter_by(id=protocol_id).first()
if protocol is None or not protocol.protocoltype.has_modify_right(user):
flash("Invalides Protokoll oder fehlende Zugriffsrechte.", "alert-error")
return redirect(request.args.get("next") or url_for("list_protocols"))
form = ProtocolForm(obj=protocol)
if form.validate_on_submit():
form.populate_obj(protocol)
db.session.commit()
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
return redirect(request.args.get("fail") or url_for("update_protocol", protocol_id=protocol.id))
@app.route("/protocol/show/<int:protocol_id>")
def show_protocol(protocol_id):
user = current_user()
......@@ -439,7 +424,18 @@ def get_protocol_source(protocol_id):
file_like = BytesIO(protocol.source.encode("utf-8"))
return send_file(file_like, cache_timeout=1, as_attachment=True, attachment_filename="{}.txt".format(protocol.get_identifier()))
@app.route("/protocol/update/<int:protocol_id>")
@app.route("/protocol/template/<int:protocol_id>")
@login_required
def get_protocol_template(protocol_id):
user = current_user()
protocol = Protocol.query.filter_by(id=protocol_id).first()
if protocol is None or not protocol.protocoltype.has_modify_right(user):
flash("Invalides Protokoll oder keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
file_like = BytesIO(protocol.get_template().encode("utf-8"))
return send_file(file_like, cache_timeout=1, as_attachment=True, attachment_filename="{}-template.txt".format(protocol.get_identifier()))
@app.route("/protocol/update/<int:protocol_id>", methods=["GET", "POST"])
@login_required
def update_protocol(protocol_id):
user = current_user()
......@@ -449,6 +445,10 @@ def update_protocol(protocol_id):
return redirect(request.args.get("next") or url_for("index"))
upload_form = KnownProtocolSourceUploadForm()
edit_form = ProtocolForm(obj=protocol)
if edit_form.validate_on_submit():
edit_form.populate_obj(protocol)
db.session.commit()
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
return render_template("protocol-update.html", upload_form=upload_form, edit_form=edit_form, protocol=protocol)
@app.route("/protocol/tops/new/<int:protocol_id>", methods=["GET", "POST"])
......
......@@ -121,9 +121,9 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
who = todo_tag.values[0]
what = todo_tag.values[1]
todo = None
field_id = None
for other_field in todo_tag.values[2:]:
if other_field.startswith(ID_FIELD_BEGINNING):
field_id = 0
try:
field_id = int(other_field[len(ID_FIELD_BEGINNING):])
except ValueError:
......@@ -133,8 +133,25 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
db.session.add(error)
db.session.commit()
return
todo = Todo.query.filter_by(id=field_id).first()
todo = Todo.query.filter_by(number=field_id).first()
who = who.strip()
what = what.strip()
if todo is None:
if field_id is not None:
candidate = Todo.query.filter_by(who=who, description=what, number=None).first()
if candidate is None:
candidate = Todo.query.filter_by(description=what, number=None).first()
if candidate is not None:
candidate.number = field_id
todo = candidate
else:
todo = Todo(who=who, description=what, tags="", done=False)
todo.number = field_id
else:
candidate = Todo.query.filter_by(who=who, description=what).first()
if candidate is not None:
todo = candidate
else:
todo = Todo(who=who, description=what, tags="", done=False)
db.session.add(todo)
todo.protocols.append(protocol)
......
......@@ -12,11 +12,14 @@
<div class="container">
<div class="btn-group">
{% if has_modify_right %}
<a class="btn {% if protocol.source is none %}btn-primary{% else %}btn-default{% endif %}" href="{{url_for("etherpull_protocol", protocol_id=protocol.id)}}">From etherpad</a>
<a class="btn {% if protocol.source is none %}btn-primary{% else %}btn-default{% endif %}" href="{{url_for("etherpull_protocol", protocol_id=protocol.id)}}">Aus Etherpad</a>
{% if protocol.source is not none %}
<a class="btn btn-primary" href="{{url_for("get_protocol_source", protocol_id=protocol.id)}}">Download Quelltext</a>
{% endif %}
<a class="btn {% if protocol.is_done() %}btn-success{% else %}btn-default{% endif %}" href="{{url_for("update_protocol", protocol_id=protocol.id)}}">Protokoll editieren</a>
{% if not protocol.is_done() %}
<a class="btn btn-default" href="{{url_for("get_protocol_template", protocol_id=protocol.id)}}">Vorlage herunterladen</a>
{% endif %}
<a class="btn btn-default" href="{{protocol.get_etherpad_link()}}" target="_blank">Etherpad</a>
<a class="btn btn-default" href="{{url_for("show_type", type_id=protocol.protocoltype.id)}}">Typ</a>
<a class="btn btn-danger" href="{{url_for("delete_protocol", protocol_id=protocol.id)}}" onclick="return confirm('Bist du dir sicher, dass du das Protokoll {{protocol.get_identifier()}} löschen möchtest?');">Löschen</a>
......
#Datum;{{protocol.date|datify}}
#Anwesende;
#Beginn;
#Ende;
#Autor;
#Ort;
{% macro render_top(top) %}
{TOP {{top.name}}
{% if top.name == "Todos" %}
{% if protocol.todos|length > 0 %}
{% for todo in protocol.todos %}
[todo;{{todo.who}};{{todo.description}};id {{todo.get_number()}}];
{% endfor %}
{% else %}
{% endif %}
{% else %}
{% endif %}
}
{% endmacro -%}
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if not default_top.is_at_end() %}
{{-render_top(default_top)}}
{% endif %}
{% endfor %}
{% endif %}
{% for top in protocol.tops %}
{{-render_top(top)}}
{% endfor %}
{% if not protocol.has_nonplanned_tops() %}
{% for default_top in protocol.protocoltype.default_tops %}
{% if default_top.is_at_end() %}
{{-render_top(default_top)}}
{% endif %}
{% endfor %}
{% endif %}
......@@ -9,10 +9,10 @@
{% for top in protocol.tops %}
<li>
{{top.name}}
{% if has_private_view_right %}
{% if not protocol.is_done() and has_private_view_right %}
({{top.number}})
{% endif %}
{% if has_modify_right %}
{% if not protocol.is_done() and has_modify_right %}
<a href="{{url_for('edit_top', top_id=top.id)}}">Ändern</a>
<a href="{{url_for('move_top', top_id=top.id, diff=1)}}">Runter</a>
<a href="{{url_for('move_top', top_id=top.id, diff=-1)}}">Hoch</a>
......
......@@ -6,7 +6,7 @@
<div class="container">
<div class="row">
<div id="left-column" class="col-lg-6">
{{render_form(edit_form, action_url=url_for("edit_protocol", protocol_id=protocol.id), action_text="Ändern")}}
{{render_form(edit_form, action_url=url_for("update_protocol", protocol_id=protocol.id), action_text="Ändern")}}
</div>
<div id="right-column" class="col-lg-6">
<h3>Protokoll herunterladen</h3>
......
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, DateField, HiddenField, IntegerField, SelectField, FileField, DateTimeField
from wtforms.validators import InputRequired
from wtforms.validators import InputRequired, Optional
class LoginForm(FlaskForm):
username = StringField("Benutzer", validators=[InputRequired("Bitte gib deinen Benutzernamen ein.")])
......@@ -50,8 +50,8 @@ class NewProtocolSourceUploadForm(FlaskForm):
class ProtocolForm(FlaskForm):
date = DateField("Datum", validators=[InputRequired("Bitte gib das Datum des Protkolls an.")], format="%d.%m.%Y")
start_time = DateTimeField("Beginn", format="%H:%M")
end_time = DateTimeField("Ende", format="%H:%M")
start_time = DateTimeField("Beginn", format="%H:%M", validators=[Optional()])
end_time = DateTimeField("Ende", format="%H:%M", validators=[Optional()])
location = StringField("Ort")
author = StringField("Protokollant")
participants = StringField("Anwesende")
......
......@@ -177,11 +177,12 @@ class TodosTable(Table):
super().__init__("Todos", todos)
def headers(self):
return ["Status", "Sitzung", "Name", "Aufgabe"]
return ["ID", "Status", "Sitzung", "Name", "Aufgabe"]
def row(self, todo):
protocol = todo.get_first_protocol()
return [
todo.get_id(),
todo.get_state(),
Table.link(url_for("show_protocol", protocol_id=protocol.id), protocol.get_identifier()) if protocol is not None else "",
todo.who,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment