Skip to content
Snippets Groups Projects
Verified Commit ff0b2028 authored by Nils Beyer's avatar Nils Beyer
Browse files

Exportieren von TOP, erste lauffähige Version

parent 377b3d9c
Branches
No related tags found
1 merge request!21TOPs automatisiert als Anhang exportieren
...@@ -766,8 +766,8 @@ CONFIG_SECTIONS = [ ...@@ -766,8 +766,8 @@ CONFIG_SECTIONS = [
"files: e.g. the files for the template 'yourtemplate' " "files: e.g. the files for the template 'yourtemplate' "
"need to be in the folder named 'yourtemplate', and the " "need to be in the folder named 'yourtemplate', and the "
"templates provides the files: 'protokoll2.cls' (class), " "templates provides the files: 'protokoll2.cls' (class), "
"'protocol.tex' (protocol), 'decision.tex' (decision) and " "'protocol.tex' (protocol), 'decision.tex' (decision),"
"'asta-logo.tex'")), "'extra.tex' (exported TOP) and 'asta-logo.tex'")),
], ],
check=check_rendering, check=check_rendering,
description="Settings for rendering protocols to pdf, html, etc."), description="Settings for rendering protocols to pdf, html, etc."),
......
"""Append extra column to Document
Revision ID: 7834767242e8
Revises: ead59eff0835
Create Date: 2022-03-21 11:46:20.368800
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '7834767242e8'
down_revision = 'ead59eff0835'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('documents', sa.Column('is_extra', sa.Boolean(), default=False, nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('documents', 'is_extra')
# ### end Alembic commands ###
...@@ -540,6 +540,7 @@ class Document(DatabaseModel): ...@@ -540,6 +540,7 @@ class Document(DatabaseModel):
name = db.Column(db.Text) name = db.Column(db.Text)
filename = db.Column(db.Text) filename = db.Column(db.Text)
is_compiled = db.Column(db.Boolean) is_compiled = db.Column(db.Boolean)
is_extra = db.Column(db.Boolean)
is_private = db.Column(db.Boolean) is_private = db.Column(db.Boolean)
def get_parent(self): def get_parent(self):
......
...@@ -38,6 +38,7 @@ class RenderType(Enum): ...@@ -38,6 +38,7 @@ class RenderType(Enum):
plaintext = 2 plaintext = 2
html = 3 html = 3
dokuwiki = 4 dokuwiki = 4
extra = 5
def _not_implemented(self, render_type): def _not_implemented(self, render_type):
...@@ -187,7 +188,7 @@ class Text: ...@@ -187,7 +188,7 @@ class Text:
self.fork = fork self.fork = fork
def render(self, render_type, show_private, level=None, protocol=None): def render(self, render_type, show_private, level=None, protocol=None):
if render_type == RenderType.latex: if render_type == RenderType.latex or render_type == RenderType.extra:
return escape_tex(self.text) return escape_tex(self.text)
elif render_type == RenderType.wikitext: elif render_type == RenderType.wikitext:
return self.text return self.text
...@@ -244,6 +245,22 @@ class Tag: ...@@ -244,6 +245,22 @@ class Tag:
return r"\textbf{{{}:}} {}".format( return r"\textbf{{{}:}} {}".format(
escape_tex(self.name.capitalize()), escape_tex(self.name.capitalize()),
escape_tex(";".join(self.values))) escape_tex(";".join(self.values)))
elif render_type == RenderType.extra:
if self.name == "url":
return r"\url{{{}}}".format(self.values[0])
elif self.name == "todo":
return ""
elif self.name == "beschluss":
return (
r"\begin{tcolorbox}[breakable,title=Beschluss, colframe=red!45!yellow, colback=yellow!10, coltitle=white,]" + "\n"
+ r"\begin{itemize}"
+ r"\item[] " + self.values[0] + "\n"
+ r"\end{itemize} \end{tcolorbox}")
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)))
elif render_type == RenderType.plaintext: elif render_type == RenderType.plaintext:
if self.name == "url": if self.name == "url":
return self.values[0] return self.values[0]
...@@ -357,7 +374,7 @@ class Remark(Element): ...@@ -357,7 +374,7 @@ class Remark(Element):
self.linenumber = linenumber self.linenumber = linenumber
def render(self, render_type, show_private, level=None, protocol=None): def render(self, render_type, show_private, level=None, protocol=None):
if render_type == RenderType.latex: if render_type == RenderType.latex or render_type == RenderType.extra:
return r"\textbf{{{}}}: {}".format(self.name, self.value) return r"\textbf{{{}}}: {}".format(self.name, self.value)
elif render_type == RenderType.wikitext: elif render_type == RenderType.wikitext:
return "{}: {}".format(self.name, self.value) return "{}: {}".format(self.name, self.value)
...@@ -428,27 +445,39 @@ class Fork(Element): ...@@ -428,27 +445,39 @@ class Fork(Element):
name_line = self.name if self.name is not None else "" name_line = self.name if self.name is not None else ""
if level == 0 and self.name == "Todos" and not show_private: if level == 0 and self.name == "Todos" and not show_private:
return "" return ""
if render_type == RenderType.latex: if render_type == RenderType.latex or render_type == RenderType.extra:
if self.is_extra: if render_type == RenderType.latex and self.is_extra:
return r"\textit{[Dieser Tagesordnungspunkt wird in einem eigenem PDF exportiert.]}" return r"\textit{[Dieser Tagesordnungspunkt wird in einem eigenem PDF exportiert.]}"
begin_line = r"\begin{itemize}" begin_line = r"\begin{itemize}"
end_line = r"\end{itemize}" end_line = r"\end{itemize}"
content_parts = [] content_parts = []
parts = []
for child in self.children: for child in self.children:
part = child.render( part = child.render(
render_type, show_private, level=level + 1, render_type, show_private, level=level + 1,
protocol=protocol) protocol=protocol)
parts.append(part)
if len(part.strip()) == 0: if len(part.strip()) == 0:
continue continue
if render_type == RenderType.latex:
if not part.startswith(r"\item"): if not part.startswith(r"\item"):
part = r"\item {}".format(part) part = r"\item {}".format(part)
elif render_type == RenderType.extra:
if not part.startswith(r"\item") and not part.startswith(r"\footnote") and not part.startswith(
r"\begin{tcolorbox}"):
part = r"\item {}".format(part)
elif part.startswith(r"\begin{tcolorbox}"):
part = r"\item[] {}".format(part)
content_parts.append(part) content_parts.append(part)
content_lines = "\n".join(content_parts) content_lines = "\n".join(content_parts)
if len(content_lines.strip()) == 0: if len(content_lines.strip()) == 0:
content_lines = "\\item Nichts\n" content_lines = "\\item Nichts\n"
if level == 0: if level == 0:
if render_type == RenderType.latex:
return "\n".join([begin_line, content_lines, end_line]) return "\n".join([begin_line, content_lines, end_line])
elif render_type == RenderType.extra:
return "\n".join(parts)
elif self.test_private(self.name): elif self.test_private(self.name):
if show_private: if show_private:
return (r"\begin{tcolorbox}[breakable,title=Interner " return (r"\begin{tcolorbox}[breakable,title=Interner "
...@@ -460,6 +489,12 @@ class Fork(Element): ...@@ -460,6 +489,12 @@ class Fork(Element):
else: else:
return (r"\textit{[An dieser Stelle wurde intern " return (r"\textit{[An dieser Stelle wurde intern "
r"protokolliert.]}") r"protokolliert.]}")
elif render_type == RenderType.extra and level == 1:
name_escape = escape_tex(name_line)
return "\n".join([
f"\section{{{name_escape}}}", begin_line,
content_lines, end_line
])
else: else:
return "\n".join([ return "\n".join([
escape_tex(name_line), begin_line, escape_tex(name_line), begin_line,
......
...@@ -70,7 +70,8 @@ def provide_latex_template(template, documenttype): ...@@ -70,7 +70,8 @@ def provide_latex_template(template, documenttype):
_DOCUMENTTYPE_FILENAME_MAP = { _DOCUMENTTYPE_FILENAME_MAP = {
"class": "protokoll2.cls", "class": "protokoll2.cls",
"protocol": "protocol.tex", "protocol": "protocol.tex",
"decision": "decision.tex" "decision": "decision.tex",
"extra": "extra.tex"
} }
_PROVIDES = "provides" _PROVIDES = "provides"
_LOGO_TEMPLATE = "logo_template" _LOGO_TEMPLATE = "logo_template"
...@@ -558,6 +559,21 @@ def parse_protocol_async_inner(protocol, ignore_old_date=False): ...@@ -558,6 +559,21 @@ def parse_protocol_async_inner(protocol, ignore_old_date=False):
latex_source, protocol, show_private=show_private, latex_source, protocol, show_private=show_private,
maxdepth=maxdepth) maxdepth=maxdepth)
# Export extra TOPs
extra_tops = [child for child in tree.children if isinstance(child, Fork) and child.is_extra]
for top in extra_tops:
for show_private in privacy_states:
latex_source = texenv.get_template(provide_latex_template(
protocol.protocoltype.latex_template, "extra")).render(
render_type=RenderType.extra,
top=top,
show_private=show_private,
**render_kwargs[show_private])
compile_extra(
latex_source, protocol, show_private=show_private, extra_name=top.name,
maxdepth=maxdepth)
if protocol.protocoltype.use_wiki: if protocol.protocoltype.use_wiki:
wiki_type = WikiType[getattr(config, "WIKI_TYPE", "MEDIAWIKI")] wiki_type = WikiType[getattr(config, "WIKI_TYPE", "MEDIAWIKI")]
wiki_template = { wiki_template = {
...@@ -644,10 +660,13 @@ def compile_decision(content, decision, maxdepth): ...@@ -644,10 +660,13 @@ def compile_decision(content, decision, maxdepth):
compile_async.delay( compile_async.delay(
content, decision.id, use_decision=True, maxdepth=maxdepth) content, decision.id, use_decision=True, maxdepth=maxdepth)
def compile_extra(content, protocol, show_private, maxdepth, extra_name):
compile_async.delay(
content, protocol.id, use_decision=False, show_private=show_private, maxdepth=maxdepth, is_extra=True, extra_name=extra_name)
@celery.task @celery.task
def compile_async( def compile_async(
content, protocol_id, show_private=False, use_decision=False, content, protocol_id, show_private=False, use_decision=False, is_extra=False, extra_name="",
maxdepth=5): maxdepth=5):
with tempfile.TemporaryDirectory() as compile_dir, app.app_context(): with tempfile.TemporaryDirectory() as compile_dir, app.app_context():
decision = None decision = None
...@@ -692,7 +711,7 @@ def compile_async( ...@@ -692,7 +711,7 @@ def compile_async(
stderr=subprocess.DEVNULL) stderr=subprocess.DEVNULL)
os.chdir(current) os.chdir(current)
document = None document = None
if not use_decision: if not use_decision and not is_extra:
for old_document in [ for old_document in [
document for document in protocol.documents document for document in protocol.documents
if document.is_compiled if document.is_compiled
...@@ -708,7 +727,7 @@ def compile_async( ...@@ -708,7 +727,7 @@ def compile_async(
filename="", filename="",
is_compiled=True, is_compiled=True,
is_private=show_private) is_private=show_private)
else: elif use_decision and not is_extra:
document = DecisionDocument( document = DecisionDocument(
decision_id=decision.id, decision_id=decision.id,
name="beschluss_{}_{}_{}.pdf".format( name="beschluss_{}_{}_{}.pdf".format(
...@@ -716,6 +735,20 @@ def compile_async( ...@@ -716,6 +735,20 @@ def compile_async(
date_filter_short(protocol.date), date_filter_short(protocol.date),
decision.id), decision.id),
filename="") filename="")
elif is_extra and not use_decision:
document = Document(
protocol_id=protocol.id,
name="extra-{}{}_{}_{}.pdf".format(
extra_name,
"_intern" if show_private else "",
protocol.protocoltype.short_name,
date_filter_short(protocol.date)),
filename="",
is_compiled=True,
is_extra=True,
is_private=show_private)
else:
raise NotImplementedError("Unknown type.")
db.session.add(document) db.session.add(document)
db.session.commit() db.session.commit()
target_filename = "compiled-{}-{}.pdf".format( target_filename = "compiled-{}-{}.pdf".format(
......
...@@ -40,4 +40,19 @@ ...@@ -40,4 +40,19 @@
</div> </div>
</div> </div>
</div> </div>
<h4>Exportieren</h4>
<p>
Außerdem kann ein Tagesordnungspunkt auch so angelegt werden, dass ein eigenes PDF für diesen angelegt wird, und im Hauptprotokoll auf dieses PDF verwiesen wird. Dies wird durch ein Hinzufügen eines Ausrufezeichens (<span class="highlight"><span class="kr">!</span></span>) vor dem Schlüsselword <span class="highlight"><span class="kr">TOP</span></span> erreicht.
</p>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">Tagesordnungspunkt in eigenem PDF</a></h5>
</div>
<figure class="panel-body">
<pre class="highlight"><code>{<span class="kr">!TOP</span> <span class="sx">Titel des Tagesordnungspunkts</span>
<span class="c1">Hier steht der Inhalt des Tagesordnungspunkts</span>
<span class="c1">Dies wird in einem separaten PDF exportiert</span>
}</code></pre>
</figure>
</div>
{% endblock %} {% endblock %}
% Template created by Karol Kozioł (www.karol-koziol.net) for ShareLaTeX
% Template adapted by Nils Beyer
\documentclass[a4paper,ngerman,twocolumn,9pt]{extarticle}
\usepackage[utf8]{inputenc}
\usepackage{ifthen}
\newboolean{intern}
\newcommand{\intern}[2]{\ifthenelse{\boolean{intern}}{#1}{#2} }
\usepackage[T1]{fontenc}
\usepackage{verbatim}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{pgf,tikz}
\usepackage{mathrsfs}
\usepackage{csquotes}
\usepackage{tcolorbox}
\tcbuselibrary{listings,breakable}
\usepackage{draftwatermark}
\SetWatermarkText{}
\SetWatermarkScale{1}
\usetikzlibrary{shapes, calc, shapes, arrows, babel}
\usepackage{amsmath,amssymb,textcomp}
\everymath{\displaystyle}
\usepackage{times}
\renewcommand\familydefault{\sfdefault}
\usepackage{tgheros}
\usepackage{multicol}
\setlength{\columnseprule}{0.5pt}
\setlength{\columnsep}{20.0pt}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{eurosym}
\usepackage{hyperref}
\usepackage{geometry}
\geometry{
a4paper,
total={210mm,297mm},
left=10mm,right=10mm,top=10mm,bottom=15mm}
\linespread{1.2}
% custom section titles
\usepackage[explicit]{titlesec}
\newcommand*\sectionlabel{}
\titleformat{\section}
% {\gdef\sectionlabel{}\normalfont\sffamily\Large\bfseries\scshape}
{\gdef\sectionlabel{}\normalfont\sffamily\bfseries}
{\gdef\sectionlabel{\thesection }}{0pt}
{
\noindent
\begin{tikzpicture}
\node[rectangle,rounded corners=1pt,inner sep=4pt,fill=red!45!black,text width=0.95\columnwidth] {\color{white}\sectionlabel #1};
\end{tikzpicture}
}
\titlespacing*{\section}{0pt}{10pt}{0pt}
% Numbering style
\renewcommand*{\thesection}{\Roman{section}~: }
% custom footer
\usepackage{fancyhdr}
\makeatletter
\pagestyle{fancy}
\fancyhead{}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}
\makeatother
% href boxes
\hypersetup{
colorlinks,
linkcolor={red!50!black},
citecolor={blue!50!black},
urlcolor={blue!80!black}
}
% Line numbers on sides
\usepackage[switch,columnwise]{lineno}
\setlength{\parindent}{0em}
\usepackage{enumitem}
\setlist{nosep}
\newcommand{\Beschluss}[2][]{\textbf{Beschluss:} #2 \def\temp{#1}\ifx\temp\empty\else\textit{(#1)}\fi}
\ENV{if show_private}\setboolean{intern}{true}\ENV{endif}
\intern{\SetWatermarkText{INTERN} \SetWatermarkScale{1}}{}
\begin{document}
\small
\begin{center}
\VAR{top.name|escape_tex} zur \textsc{\VAR{protocol.protocoltype.name|escape_tex}} am \VAR{protocol.date|datify_long|escape_tex}
\end{center}
\ENV{if top|class == "Fork"}
\VAR{top.render(render_type=render_type, level=0, show_private=show_private, protocol=protocol)}
\ENV{endif}
\runningpagewiselinenumbers \linenumbers
\end{document}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment