Commit dabb0158 authored by Robin Sonnabend's avatar Robin Sonnabend
Browse files

Upload source

parent b4e667c7
"""empty message
Revision ID: aebae2c4523d
Revises: b114754024fb
Create Date: 2017-02-24 05:58:37.240601
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'aebae2c4523d'
down_revision = 'b114754024fb'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('documents_filename_key', 'documents', type_='unique')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_unique_constraint('documents_filename_key', 'documents', ['filename'])
# ### end Alembic commands ###
......@@ -103,8 +103,11 @@ class Protocol(db.Model):
def fill_from_remarks(self, remarks):
new_date = datetime.strptime(remarks["Datum"].value, "%d.%m.%Y").date()
if new_date != self.date:
raise DateNotMatchingException(original_date=self.date, protocol_date=new_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
......@@ -115,11 +118,16 @@ class Protocol(db.Model):
return self.done
def get_identifier(self):
if self.date is None:
return None
return "{}-{}".format(
self.protocoltype.short_name.lower(),
self.date.strftime("%y-%m-%d"))
def get_etherpad_link(self):
identifier = self.get_identifier()
if identifier is None:
return ""
return config.ETHERPAD_URL + self.get_identifier()
def get_etherpad_source_link(self):
......@@ -131,6 +139,28 @@ class Protocol(db.Model):
def get_originating_todos(self):
return [todo for todo in self.todos if self == todo.get_first_protocol()]
def has_compiled_document(self):
candidates = [
document for document in self.documents
if document.is_compiled
]
return len(candidates) > 0
def get_compiled_document(self, private=None):
candidates = [
document for document in self.documents
if document.is_compiled
and (private is None or document.is_private == private)
]
print(candidates)
private_candidates = [document for document in candidates if document.is_private]
public_candidates = [document for document in candidates if not document.is_private]
if len(private_candidates) > 0:
return private_candidates[0]
elif len(public_candidates) > 0:
return public_candidates[0]
return None
def delete_orphan_todos(self):
orphan_todos = [
todo for todo in self.todos
......@@ -187,7 +217,7 @@ class Document(db.Model):
id = db.Column(db.Integer, primary_key=True)
protocol_id = db.Column(db.Integer, db.ForeignKey("protocols.id"))
name = db.Column(db.String)
filename = db.Column(db.String, unique=True)
filename = db.Column(db.String)
is_compiled = db.Column(db.Boolean)
is_private = db.Column(db.Boolean)
......
......@@ -17,7 +17,7 @@ import config
from shared import db, date_filter, datetime_filter, date_filter_long, time_filter, ldap_manager, security_manager, current_user, check_login, login_required, group_required
from utils import is_past, mail_manager, url_manager
from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm
from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable
app = Flask(__name__)
......@@ -293,6 +293,7 @@ def new_protocol():
if protocoltype.has_modify_right(user)
]
form = NewProtocolForm(protocoltypes)
upload_form = NewProtocolSourceUploadForm(protocoltypes)
if form.validate_on_submit():
protocoltype = ProtocolType.query.filter_by(id=form.protocoltype.data).first()
if protocoltype is None or not protocoltype.has_modify_right(user):
......@@ -305,7 +306,7 @@ def new_protocol():
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, protocoltypes=protocoltypes)
return render_template("protocol-new.html", form=form, upload_form=upload_form, protocoltypes=protocoltypes)
@app.route("/protocol/show/<int:protocol_id>")
def show_protocol(protocol_id):
......@@ -322,7 +323,8 @@ def show_protocol(protocol_id):
]
documents_table = DocumentsTable(visible_documents)
document_upload_form = DocumentUploadForm()
return render_template("protocol-show.html", protocol=protocol, errors_table=errors_table, documents_table=documents_table, document_upload_form=document_upload_form)
source_upload_form = KnownProtocolSourceUploadForm()
return render_template("protocol-show.html", protocol=protocol, errors_table=errors_table, documents_table=documents_table, document_upload_form=document_upload_form, source_upload_form=source_upload_form)
@app.route("/protocol/delete/<int:protocol_id>")
@login_required
......@@ -339,6 +341,7 @@ def delete_protocol(protocol_id):
return redirect(request.args.get("next") or url_for("list_protocols"))
@app.route("/protocol/etherpull/<int:protocol_id>")
@login_required
def etherpull_protocol(protocol_id):
user = current_user()
protocol = Protocol.query.filter_by(id=protocol_id).first()
......@@ -353,6 +356,64 @@ def etherpull_protocol(protocol_id):
flash("Das Protokoll wird kompiliert.", "alert-success")
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
@app.route("/protocol/upload/known/<int:protocol_id>", methods=["POST"])
@login_required
def upload_source_to_known_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 keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index"))
form = KnownProtocolSourceUploadForm()
if form.validate_on_submit():
if form.source.data is None:
flash("Es wurde keine Datei ausgewählt.", "alert-error")
else:
file = form.source.data
if file.filename == "":
flash("Es wurde keine Datei ausgewählt.", "alert-error")
else:
# todo: Prüfen, ob es Text ist?
source = file.stream.read().decode("utf-8")
protocol.source = source
db.session.commit()
tasks.parse_protocol(protocol)
flash("Das Protokoll wird kompiliert.", "alert-success")
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
@app.route("/protocol/upload/new/", methods=["POST"])
@login_required
def upload_new_protocol():
user = current_user()
available_types = [
protocoltype for protocoltype in ProtocolType.query.all()
if protocoltype.has_modify_right(user)
]
form = NewProtocolSourceUploadForm(protocoltypes=available_types)
if form.validate_on_submit():
if form.source.data is None:
flash("Es wurde keine Datei ausgewählt.", "alert-error")
else:
print(form.source.data)
file = form.source.data
if file.filename == "":
flash("Es wurde keine Datei ausgewählt.", "alert-error")
else:
source = file.stream.read().decode("utf-8")
protocoltype = ProtocolType.query.filter_by(id=form.protocoltype.data).first()
if protocoltype is None or not protocoltype.has_modify_right(user):
flash("Invalider Protokolltyp oder keine Rechte.", "alert-error")
else:
protocol = Protocol(protocoltype.id, None, source)
db.session.add(protocol)
db.session.commit()
tasks.parse_protocol(protocol)
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
return redirect(request.args.get("fail") or url_for("new_protocol"))
@app.route("/protocol/source/<int:protocol_id>")
@login_required
def get_protocol_source(protocol_id):
......@@ -372,8 +433,8 @@ def update_protocol(protocol_id):
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"))
# TODO: render form to upload a new version
upload_form = KnownProtocolSourceUploadForm()
return render_template("protocol-update.html", upload_form=upload_form, protocol=protocol)
@app.route("/todos/list")
def list_todos():
......
......@@ -172,9 +172,12 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
db.session.add(top)
db.session.commit()
for show_private in [True, False]:
latex_source = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=show_private)
compile(latex_source, protocol, show_private=show_private)
latex_source_private = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=True)
latex_source_public = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=False)
compile(latex_source_public, protocol, show_private=False)
if latex_source_private != latex_source_public:
compile(latex_source_private, protocol, show_private=True)
# TODO compare something that may actually be equal
protocol.done = True
db.session.commit()
......
......@@ -4,6 +4,15 @@
{% block content %}
<div class="container">
{{render_form(form, action_url=url_for("new_protocol"), action_text="Anlegen")}}
<div class="row">
<div id="left-column" class="col-lg-6">
<h3>Neues Protokoll</h3>
{{render_form(form, action_url=url_for("new_protocol"), action_text="Anlegen")}}
</div>
<div id="left-column" class="col-lg-6">
<h3>Neues Protokoll hochladen</h3>
{{render_form(upload_form, action_url=url_for("upload_new_protocol", fail=url_for("new_protocol")), action_text="Hochladen", enctype="multipart/form-data")}}
</div>
</div>
</div>
{% endblock %}
......@@ -5,25 +5,38 @@
{% block content %}
<div class="container">
<div class="btn-group">
<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>
{% 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 %}
{% if protocol.is_done() %}
<a class="btn btn-success" href="{{url_for("update_protocol", protocol_id=protocol.id)}}">Protokoll editieren</a>
{% if protocol.protocoltype.has_modify_right(current_user()) %}
<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>
{% 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 %}
{% if protocol.is_done() %}
<a class="btn btn-success" href="{{url_for("update_protocol", protocol_id=protocol.id)}}">Protokoll editieren</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>
{% 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>
</div>
<div class="row">
<div id="left-column" class="col-lg-6">
<h2>Protokoll: {{protocol.protocoltype.name}} vom {{protocol.date|datify}}</h2>
{% if protocol.is_done() %}
<p><strong>Datum:</strong> {{protocol.date|datify_long}}</p>
<p><strong>Zeit:</strong> von {{protocol.start_time|timify}} bis {{protocol.end_time|timify}}</p>
<p><strong>Ort:</strong> {{protocol.location}}</p>
<p><strong>Protokollant:</strong> {{protocol.author}}</p>
<p><strong>Anwesende:</strong> {{protocol.participants}}</p>
{% if protocol.date is not none %}
<p><strong>Datum:</strong> {{protocol.date|datify_long}}</p>
{% endif %}
{% if protocol.start_time is not none and protocol.end_time is not none %}
<p><strong>Zeit:</strong> von {{protocol.start_time|timify}} bis {{protocol.end_time|timify}}</p>
{% endif %}
{% if protocol.location is not none %}
<p><strong>Ort:</strong> {{protocol.location}}</p>
{% endif %}
{% if protocol.author is not none %}
<p><strong>Protokollant:</strong> {{protocol.author}}</p>
{% endif %}
{% if protocol.participants is not none %}
<p><strong>Anwesende:</strong> {{protocol.participants}}</p>
{% endif %}
{% else %}
<p><strong>Geplant:</strong> {{protocol.date|datify_long}}</p>
{% endif %}
......@@ -60,25 +73,30 @@
</div>
<div id="right-column" class="col-lg-6">
{% if protocol.is_done() %}
<h3>Todos dieser Sitzung <a href="{{url_for("list_todos")}}">Aktuelle Todos</a></h3>
<ul>
{% if protocol.get_originating_todos()|length > 0 %}
{% for todo in protocol.get_originating_todos() %}
<li>{{todo.render_html()|safe}}</li>
{% endfor %}
{% else %}
<li>Keine Todos</li>
{% endif %}
</ul>
<h3>Todos dieser Sitzung <a href="{{url_for("list_todos")}}">Aktuelle Todos</a></h3>
<ul>
{% if protocol.get_originating_todos()|length > 0 %}
{% for todo in protocol.get_originating_todos() %}
<li>{{todo.render_html()|safe}}</li>
{% endfor %}
{% else %}
<li>Keine Todos</li>
{% endif %}
</ul>
{% endif %}
{% if protocol.errors|length > 0 %}
{{render_table(errors_table)}}
{% if protocol.protocoltype.has_modify_right(current_user()) %}
{% if protocol.errors|length > 0 %}
{{render_table(errors_table)}}
{% endif %}
{% endif %}
{% if protocol.documents|length > 0 %}
{{render_table(documents_table)}}
{% else %}
<h3>Hochladen</h3>
{% endif %}
{% if protocol.is_done() %}
{{render_form(document_upload_form, action_url=url_for("upload_document", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Hochladen", enctype="multipart/form-data")}}
{% if protocol.protocoltype.has_modify_right(current_user()) %}
{{render_form(source_upload_form, action_url=url_for("upload_source_to_known_protocol", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Hochladen", enctype="multipart/form-data")}}
{{render_form(document_upload_form, action_url=url_for("upload_document", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Hochladen", enctype="multipart/form-data")}}
{% endif %}
</div>
</div>
......
{% extends "layout.html" %}
{% from "macros.html" import render_form %}
{% block title %}Protokoll ändern{% endblock %}
{% block content %}
<div class="container">
<div class="row">
<div id="left-column" class="col-lg-6">
<h3>Protokoll herunterladen</h3>
<div class="btn-group">
{% 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 btn-default" href="{{url_for("show_protocol", protocol_id=protocol.id)}}">Zurück</a>
{% if protocol.has_compiled_document() %}
<a class="btn btn-success" href="{{url_for("download_document", document_id=protocol.get_compiled_document().id)}}">Download PDF</a>
{% endif %}
</div>
</div>
<div id="right-column" class="col-lg-6">
<h3>Neue Version hochladen</h3>
{{render_form(upload_form, action_url=url_for("upload_source_to_known_protocol", protocol_id=protocol.id), action_text="Hochladen", enctype="multipart/form-data")}}
</div>
</div>
</div>
{% endblock %}
......@@ -34,5 +34,16 @@ class NewProtocolForm(FlaskForm):
self.protocoltype.choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
class DocumentUploadForm(FlaskForm):
document = FileField("Datei", validators=[InputRequired("Du musst eine Datei angeben.")])
document = FileField("Datei")
private = BooleanField("Intern")
class KnownProtocolSourceUploadForm(FlaskForm):
source = FileField("Quellcode")
class NewProtocolSourceUploadForm(FlaskForm):
source = FileField("Quellcode")
protocoltype = SelectField("Typ", choices=[], coerce=int)
def __init__(self, protocoltypes, **kwargs):
super().__init__(**kwargs)
self.protocoltype.choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment