Commit 2deb901d authored by marco's avatar marco
Browse files

Merge remote-tracking branch 'origin/156-protokolle-ubersichtseite-umbauen'...

Merge remote-tracking branch 'origin/156-protokolle-ubersichtseite-umbauen' into 156-protokolle-ubersichtseite-umbauen
parents c7f74647 1c4a04a9
......@@ -2,7 +2,7 @@
## Setup
* Install python3 and virtualenv
* Install python3, virtualenv, redis and a database program (postgres, mysql, sqlite does not work with alembic migrations)
* Create a virtualenv and install the requirements
```sh
......@@ -22,7 +22,7 @@ cp config.py.example config.py
- Don't forget to enter your database connection
- And your authentication backend
- And deactivate everything you do not use
* create the path where PDFs will be stored (`DOCUMENTS_PATH` in config.py)
* Fill your database
```sh
......
......@@ -77,9 +77,10 @@ AUTH_BACKENDS = [
StaticUserManager(
users=(
("username", "password", ("group1", "group2")),
("testuser", "abc123", ("group1")),
("testuser", "abc123", ("group1",)),
)
)
),
PAMManager(),
]
OBSOLETION_WARNING = """Please migrate your account!""" # not important
......@@ -147,6 +148,7 @@ FONTS = {
}
# local filesystem path to save compiled and uploaded protocols (and attachments)
# create this path!
DOCUMENTS_PATH = "documents"
# keywords indicating private protocol parts
......
......@@ -611,7 +611,7 @@ class Todo(DatabaseModel):
return " ".join(parts)
def render_latex(self, current_protocol=None):
return r"\textbf{{{}}}: {}: {} -- {}".format(
return r"\Todo{{{}}}{{{}}}{{{}}}{{{}}}".format(
"Neuer Todo" if self.is_new(current_protocol) else "Todo",
escape_tex(self.who),
escape_tex(self.description),
......
......@@ -221,12 +221,10 @@ class Tag:
return ""
return self.todo.render_latex(current_protocol=protocol)
elif self.name == "beschluss":
parts = [r"\textbf{{Beschluss:}} {}".format(self.decision.content)]
if len(self.decision.categories):
parts.append(
r"\textit{{({})}}".format(self.decision.get_categories_str())
)
return " ".join(parts)
return r"\Beschluss[{}]{{{}}}".format(self.decision.get_categories_str(),self.decision.content)
else:
return r"\Beschluss{{{}}}".format(self.decision.content)
elif self.name == "footnote":
return r"\footnote{{{}}}".format(self.values[0])
return r"\textbf{{{}:}} {}".format(escape_tex(self.name.capitalize()), escape_tex(";".join(self.values)))
......@@ -433,7 +431,10 @@ class Fork(Element):
else:
return "\n".join([escape_tex(name_line), begin_line, content_lines, end_line])
elif render_type == RenderType.wikitext or render_type == RenderType.dokuwiki:
title_line = "{0} {1} {0}".format("=" * (level + 2), name_line)
equal_signs = level + 2
if render_type == RenderType.dokuwiki:
equal_signs = 6 - level
title_line = "{0} {1} {0}".format("=" * equal_signs, name_line)
content_parts = []
for child in self.children:
part = child.render(render_type, show_private, level=level+1, protocol=protocol)
......
......@@ -18,6 +18,7 @@ import os
from datetime import datetime
import math
import mimetypes
import subprocess
import config
from shared import db, date_filter, datetime_filter, date_filter_long, date_filter_short, time_filter, time_filter_short, user_manager, security_manager, current_user, check_login, login_required, group_required, class_filter, needs_date_test, todostate_name_filter, code_filter, indent_tab_filter
......@@ -80,6 +81,18 @@ app.jinja_env.globals.update(max=max)
app.jinja_env.globals.update(dir=dir)
app.jinja_env.globals.update(now=datetime.now)
def get_git_revision():
gitlab_url = "https://git.fsmpi.rwth-aachen.de/protokollsystem/proto3"
commit_hash = subprocess.check_output(["git", "log", "-g", "-1", "--pretty=%H"]).decode("UTF-8").strip()
timestamp = int(subprocess.check_output(["git", "log", "-g", "-1", "--pretty=%at"]).strip())
commit_date = datetime.fromtimestamp(timestamp)
return {"url": gitlab_url, "hash": commit_hash, "date": commit_date}
try:
app.jinja_env.globals["git_revision"] = get_git_revision()
except:
pass
# blueprints here
@manager.command
......
......@@ -517,14 +517,22 @@ def push_to_dokuwiki(protocol, content, summary):
@celery.task
def push_to_dokuwiki_async(protocol_id, content, summary):
protocol = Protocol.query.filter_by(id=protocol_id).first()
with xmlrpc.client.ServerProxy(config.WIKI_API_URL) as proxy:
if not proxy.wiki.putPage(protocol.get_wiki_title(),
content, {"sum": "Automatisch generiert vom Protokollsystem 3."}):
error = protocol.create_error("Pushing to Wiki",
"Pushing to Wiki failed." "")
db.session.add(error)
db.session.commit()
with app.app_context():
protocol = Protocol.query.filter_by(id=protocol_id).first()
with xmlrpc.client.ServerProxy(config.WIKI_API_URL) as proxy:
try:
if not proxy.wiki.putPage(protocol.get_wiki_title(),
content, {"sum": "Automatisch generiert vom Protokollsystem 3."}):
error = protocol.create_error("Pushing to Wiki",
"Pushing to Wiki failed." "")
db.session.add(error)
db.session.commit()
except xmlrpc.client.Error as exception:
error = protocol.create_error("Pushing to Wiki",
"XML RPC Exception",
str(exception))
db.session.add(error)
db.session.commit()
def compile(content, protocol, show_private, maxdepth):
compile_async.delay(content, protocol.id, show_private=show_private, maxdepth=maxdepth)
......@@ -595,19 +603,20 @@ def compile_async(content, protocol_id, show_private=False, use_decision=False,
except subprocess.SubprocessError:
log = ""
total_log_filename = os.path.join(compile_dir, log_filename)
if os.path.isfile(total_log_filename):
with open(total_log_filename, "r") as log_file:
log = "Log:\n\n" + add_line_numbers(log_file.read())
else:
log = "Logfile not found."
total_source_filename = os.path.join(compile_dir, protocol_source_filename)
log = ""
if os.path.isfile(total_source_filename):
with open(total_source_filename, "r") as source_file:
log += "\n\nSource:\n\n" + add_line_numbers(source_file.read())
log += "Source:\n\n" + add_line_numbers(source_file.read())
total_class_filename = os.path.join(compile_dir, protocol_class_filename)
if os.path.isfile(total_class_filename):
with open(total_class_filename, "r") as class_file:
log += "\n\nClass:\n\n" + add_line_numbers(class_file.read())
if os.path.isfile(total_log_filename):
with open(total_log_filename, "r") as log_file:
log += "\n\nLog:\n\n" + add_line_numbers(log_file.read())
else:
log += "\n\nLogfile not found."
error = protocol.create_error("Compiling", "Compiling LaTeX failed", log)
db.session.add(error)
db.session.commit()
......
......@@ -214,6 +214,11 @@
Optional kann zusätzlich eine Uhrzeit angegeben werden: <code>[sitzung;Datum;Uhrzeit]</code> (z.B. <code>[sitzung;01.01.2018;9:00]</code>).
{% endif %}
{% if git_revision %}
<h3 id="version">Version</h4>
Dieses Protokollsystem nutzt die Software <a href="{{git_revision.url}}">„Protokollsystem 3“</a> in der Version vom <a href="{{git_revision.url}}/commit/{{git_revision.hash}}">{{git_revision.date|datify}}</a>.
Alle Änderungen, die seitdem hinzugekommen sind, kannst du <a href="{{git_revision.url}}/compare/{{git_revision.hash}}...master">hier</a> sehen.
{% endif %}
</div>
</div>
{% endblock %}
......@@ -26,7 +26,7 @@
{% endif %}
{% if not protocol.public %}
{% if config.ETHERPAD_ACTIVE %}
<a class="btn btn-primary" href="{{url_for("etherpush_protocol", protocol_id=protocol.id)}}"{% if large_time_diff %} onclick="return confirm('Bist du dir sicher, dass du das Template bereits in das Etherpad kopieren willst? Die Sitzung ist erst in {{time_diff.days}} Tagen.');"{% endif %}>Etherpad</a>
<a class="btn btn-primary" href="{{url_for("etherpush_protocol", protocol_id=protocol.id)}}"{% if large_time_diff %} onclick="return confirm('Bist du dir sicher, dass du das Template bereits in das Etherpad kopieren willst? Die Sitzung ist erst in {{time_diff.days}} Tagen.');"{% endif %} target="_blank">Etherpad</a>
{% endif %}
{% endif %}
{% if not protocol.is_done() %}
......
== Beschlüsse ==
====== Beschlüsse ======
<env> if protocol.decisions|length > 0 </env>
<env> for decision in protocol.decisions </env>
* <var>decision.content</var>
* <var>decision.content</var>
<env> endfor </env>
<env> else </env>
* keine Beschlüsse
* keine Beschlüsse
<env> endif </env>
<env> for top in tree.children </env>
......
......@@ -5,7 +5,9 @@
\usepackage{pdfpages}
\usepackage{eurosym}
%\usepackage[utf8]{inputenc}
\usepackage[pdfborder={0 0 0}]{hyperref}
\usepackage[hyphens]{url}
\usepackage[pdfborder={0 0 0},breaklinks=true]{hyperref}
\def\UrlBreaks{\do\/\do-\do\&\do.\do,\do;\do\_\do?\do\#}
%\usepackage{ngerman}
% \usepackage[left]{lineno}
%\usepackage{footnote}
......
% protokoll.cls -- version 0.1 -- last changed: see mtime of the file ;)
%
%
% Author: Sebastian Gnther <samson@asta.rwth-aachen.de>
% Author: Sebastian Günther <samson@asta.rwth-aachen.de>
% zuerst mal LaTeX's formalzeug
\NeedsTeXFormat{LaTeX2e}
......@@ -126,7 +126,7 @@
\renewcommand{\thesubsection}{TOP~\arabic{section}~(\alph{subsection})}
\newcommand{\TOP}[1]{\section{#1}}
\newcommand{\unterTOP}[1]{\subsection{#1}}
% Frs Inhaltsverzeichnisanpassen
% Fürs Inhaltsverzeichnisanpassen
\renewcommand{\l@section}{\@dottedtocline{1}{1.5em}{4em}}
\renewcommand{\l@subsection}{\@dottedtocline{2}{5.5em}{5.2em}}
\renewcommand{\contentsname}{Tagesordnung}
......@@ -166,7 +166,7 @@
}%
{\end{list}}
% Abkrzungen
% Abkürzungen
\newenvironment{Abk}{%
\begin{list}{}{%
Abkürzungen:
......@@ -183,7 +183,7 @@
}%
{\end{list}}
% Unterschriften fr eine und zwei Personen
% Unterschriften für eine und zwei Personen
\newcommand{\Unterschrift}[2]{
\vspace*{1.4cm}
\begin{center}
......@@ -250,3 +250,6 @@
\newcommand{\PE}[2]{\textbf{Persönliche Erklärung von #1:}\\\emph{\glqq{}#2\grqq{}}\\}
% Styling der Todo und Beschlusstags im Protokoll
\newcommand{\Todo}[4]{\textbf{{#1}}: #2: #3 -- #4}
\newcommand{\Beschluss}[2][\empty]{\textbf{Beschluss:} #2 \def\temp{#1}\ifx\temp\empty\else\textit{(#1)}\fi}
......@@ -99,8 +99,13 @@ class IPNetworkField(Field):
raise ValueError(self.gettext("Not a valid IP Network: {}".format(str(exc))))
self.data = ",".join(map(str, result_parts))
class FocusedStringField(StringField):
def __call__(self, **kwargs):
kwargs['autofocus'] = True
return super().__call__(**kwargs)
class LoginForm(FlaskForm):
username = StringField("Benutzer", validators=[InputRequired("Bitte gib deinen Benutzernamen ein.")])
username = FocusedStringField("Benutzer", validators=[InputRequired("Bitte gib deinen Benutzernamen ein.")])
password = PasswordField("Passwort", validators=[InputRequired("Bitte gib dein Passwort ein.")])
permanent = BooleanField("Eingeloggt bleiben?")
......
Supports Markdown
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