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

Upload source

parent b4e667c7
Branches
No related tags found
No related merge requests found
"""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): ...@@ -103,8 +103,11 @@ class Protocol(db.Model):
def fill_from_remarks(self, remarks): def fill_from_remarks(self, remarks):
new_date = datetime.strptime(remarks["Datum"].value, "%d.%m.%Y").date() new_date = datetime.strptime(remarks["Datum"].value, "%d.%m.%Y").date()
if self.date is not None:
if new_date != self.date: if new_date != self.date:
raise DateNotMatchingException(original_date=self.date, protocol_date=new_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.start_time = datetime.strptime(remarks["Beginn"].value, "%H:%M").time()
self.end_time = datetime.strptime(remarks["Ende"].value, "%H:%M").time() self.end_time = datetime.strptime(remarks["Ende"].value, "%H:%M").time()
self.author = remarks["Autor"].value self.author = remarks["Autor"].value
...@@ -115,11 +118,16 @@ class Protocol(db.Model): ...@@ -115,11 +118,16 @@ class Protocol(db.Model):
return self.done return self.done
def get_identifier(self): def get_identifier(self):
if self.date is None:
return None
return "{}-{}".format( return "{}-{}".format(
self.protocoltype.short_name.lower(), self.protocoltype.short_name.lower(),
self.date.strftime("%y-%m-%d")) self.date.strftime("%y-%m-%d"))
def get_etherpad_link(self): def get_etherpad_link(self):
identifier = self.get_identifier()
if identifier is None:
return ""
return config.ETHERPAD_URL + self.get_identifier() return config.ETHERPAD_URL + self.get_identifier()
def get_etherpad_source_link(self): def get_etherpad_source_link(self):
...@@ -131,6 +139,28 @@ class Protocol(db.Model): ...@@ -131,6 +139,28 @@ class Protocol(db.Model):
def get_originating_todos(self): def get_originating_todos(self):
return [todo for todo in self.todos if self == todo.get_first_protocol()] 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): def delete_orphan_todos(self):
orphan_todos = [ orphan_todos = [
todo for todo in self.todos todo for todo in self.todos
...@@ -187,7 +217,7 @@ class Document(db.Model): ...@@ -187,7 +217,7 @@ class Document(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
protocol_id = db.Column(db.Integer, db.ForeignKey("protocols.id")) protocol_id = db.Column(db.Integer, db.ForeignKey("protocols.id"))
name = db.Column(db.String) name = db.Column(db.String)
filename = db.Column(db.String, unique=True) filename = db.Column(db.String)
is_compiled = db.Column(db.Boolean) is_compiled = db.Column(db.Boolean)
is_private = db.Column(db.Boolean) is_private = db.Column(db.Boolean)
......
...@@ -17,7 +17,7 @@ import config ...@@ -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 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 utils import is_past, mail_manager, url_manager
from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error 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 from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable
app = Flask(__name__) app = Flask(__name__)
...@@ -293,6 +293,7 @@ def new_protocol(): ...@@ -293,6 +293,7 @@ def new_protocol():
if protocoltype.has_modify_right(user) if protocoltype.has_modify_right(user)
] ]
form = NewProtocolForm(protocoltypes) form = NewProtocolForm(protocoltypes)
upload_form = NewProtocolSourceUploadForm(protocoltypes)
if form.validate_on_submit(): if form.validate_on_submit():
protocoltype = ProtocolType.query.filter_by(id=form.protocoltype.data).first() protocoltype = ProtocolType.query.filter_by(id=form.protocoltype.data).first()
if protocoltype is None or not protocoltype.has_modify_right(user): if protocoltype is None or not protocoltype.has_modify_right(user):
...@@ -305,7 +306,7 @@ def new_protocol(): ...@@ -305,7 +306,7 @@ def new_protocol():
type_id = request.args.get("type_id") type_id = request.args.get("type_id")
if type_id is not None: if type_id is not None:
form.protocoltype.data = type_id 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>") @app.route("/protocol/show/<int:protocol_id>")
def show_protocol(protocol_id): def show_protocol(protocol_id):
...@@ -322,7 +323,8 @@ def show_protocol(protocol_id): ...@@ -322,7 +323,8 @@ def show_protocol(protocol_id):
] ]
documents_table = DocumentsTable(visible_documents) documents_table = DocumentsTable(visible_documents)
document_upload_form = DocumentUploadForm() 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>") @app.route("/protocol/delete/<int:protocol_id>")
@login_required @login_required
...@@ -339,6 +341,7 @@ def delete_protocol(protocol_id): ...@@ -339,6 +341,7 @@ def delete_protocol(protocol_id):
return redirect(request.args.get("next") or url_for("list_protocols")) return redirect(request.args.get("next") or url_for("list_protocols"))
@app.route("/protocol/etherpull/<int:protocol_id>") @app.route("/protocol/etherpull/<int:protocol_id>")
@login_required
def etherpull_protocol(protocol_id): def etherpull_protocol(protocol_id):
user = current_user() user = current_user()
protocol = Protocol.query.filter_by(id=protocol_id).first() protocol = Protocol.query.filter_by(id=protocol_id).first()
...@@ -353,6 +356,64 @@ def etherpull_protocol(protocol_id): ...@@ -353,6 +356,64 @@ def etherpull_protocol(protocol_id):
flash("Das Protokoll wird kompiliert.", "alert-success") flash("Das Protokoll wird kompiliert.", "alert-success")
return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id)) 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>") @app.route("/protocol/source/<int:protocol_id>")
@login_required @login_required
def get_protocol_source(protocol_id): def get_protocol_source(protocol_id):
...@@ -372,8 +433,8 @@ def update_protocol(protocol_id): ...@@ -372,8 +433,8 @@ def update_protocol(protocol_id):
if protocol is None or not protocol.protocoltype.has_modify_right(user): if protocol is None or not protocol.protocoltype.has_modify_right(user):
flash("Invalides Protokoll oder keine Berechtigung.", "alert-error") flash("Invalides Protokoll oder keine Berechtigung.", "alert-error")
return redirect(request.args.get("next") or url_for("index")) 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") @app.route("/todos/list")
def list_todos(): def list_todos():
......
...@@ -172,9 +172,12 @@ def parse_protocol_async(protocol_id, encoded_kwargs): ...@@ -172,9 +172,12 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
db.session.add(top) db.session.add(top)
db.session.commit() db.session.commit()
for show_private in [True, False]: latex_source_private = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=True)
latex_source = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=show_private) latex_source_public = texenv.get_template("protocol.tex").render(protocol=protocol, tree=tree, show_private=False)
compile(latex_source, protocol, show_private=show_private) 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 protocol.done = True
db.session.commit() db.session.commit()
......
...@@ -4,6 +4,15 @@ ...@@ -4,6 +4,15 @@
{% block content %} {% block content %}
<div class="container"> <div class="container">
<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")}} {{render_form(form, action_url=url_for("new_protocol"), action_text="Anlegen")}}
</div> </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 %} {% endblock %}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
{% block content %} {% block content %}
<div class="container"> <div class="container">
<div class="btn-group"> <div class="btn-group">
{% 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> <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 %} {% if protocol.source is not none %}
<a class="btn btn-primary" href="{{url_for("get_protocol_source", protocol_id=protocol.id)}}">Download Quelltext</a> <a class="btn btn-primary" href="{{url_for("get_protocol_source", protocol_id=protocol.id)}}">Download Quelltext</a>
...@@ -14,16 +15,28 @@ ...@@ -14,16 +15,28 @@
{% endif %} {% endif %}
<a class="btn btn-default" href="{{protocol.get_etherpad_link()}}" target="_blank">Etherpad</a> <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-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 %}
</div> </div>
<div class="row"> <div class="row">
<div id="left-column" class="col-lg-6"> <div id="left-column" class="col-lg-6">
<h2>Protokoll: {{protocol.protocoltype.name}} vom {{protocol.date|datify}}</h2> <h2>Protokoll: {{protocol.protocoltype.name}} vom {{protocol.date|datify}}</h2>
{% if protocol.is_done() %} {% if protocol.is_done() %}
{% if protocol.date is not none %}
<p><strong>Datum:</strong> {{protocol.date|datify_long}}</p> <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> <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> <p><strong>Ort:</strong> {{protocol.location}}</p>
{% endif %}
{% if protocol.author is not none %}
<p><strong>Protokollant:</strong> {{protocol.author}}</p> <p><strong>Protokollant:</strong> {{protocol.author}}</p>
{% endif %}
{% if protocol.participants is not none %}
<p><strong>Anwesende:</strong> {{protocol.participants}}</p> <p><strong>Anwesende:</strong> {{protocol.participants}}</p>
{% endif %}
{% else %} {% else %}
<p><strong>Geplant:</strong> {{protocol.date|datify_long}}</p> <p><strong>Geplant:</strong> {{protocol.date|datify_long}}</p>
{% endif %} {% endif %}
...@@ -71,13 +84,18 @@ ...@@ -71,13 +84,18 @@
{% endif %} {% endif %}
</ul> </ul>
{% endif %} {% endif %}
{% if protocol.protocoltype.has_modify_right(current_user()) %}
{% if protocol.errors|length > 0 %} {% if protocol.errors|length > 0 %}
{{render_table(errors_table)}} {{render_table(errors_table)}}
{% endif %} {% endif %}
{% endif %}
{% if protocol.documents|length > 0 %} {% if protocol.documents|length > 0 %}
{{render_table(documents_table)}} {{render_table(documents_table)}}
{% else %}
<h3>Hochladen</h3>
{% endif %} {% endif %}
{% if protocol.is_done() %} {% 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")}} {{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 %} {% 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): ...@@ -34,5 +34,16 @@ class NewProtocolForm(FlaskForm):
self.protocoltype.choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes] self.protocoltype.choices = [(protocoltype.id, protocoltype.short_name) for protocoltype in protocoltypes]
class DocumentUploadForm(FlaskForm): class DocumentUploadForm(FlaskForm):
document = FileField("Datei", validators=[InputRequired("Du musst eine Datei angeben.")]) document = FileField("Datei")
private = BooleanField("Intern") 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]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment