Skip to content
Snippets Groups Projects
Commit 123389f8 authored by Jonathan Weth's avatar Jonathan Weth :keyboard: Committed by root
Browse files

Merge pull request #223 from Katharineum/dev

Dev to server
parents 581f19e2 57678e99
No related branches found
No related tags found
No related merge requests found
Showing
with 470 additions and 196 deletions
from django.contrib import admin
# Register your models here.
from timetable.models import Hint
def refresh_cache(modeladmin, request, queryset):
for obj in queryset.all():
obj.save()
refresh_cache.short_description = "Cache aktualisieren"
class HintAdmin(admin.ModelAdmin):
exclude = ("text_as_latex", "classes_formatted")
actions = [refresh_cache]
admin.site.register(Hint, HintAdmin)
......@@ -3,5 +3,5 @@ from django.shortcuts import render
@login_required
def failback(request, *args, **kwargs):
return render(request, "timetable/failback.html")
def fallback(request, *args, **kwargs):
return render(request, "timetable/fallback.html")
import django_filters
from django.forms import Form
from material import Fieldset, Row
from .models import Hint
class HintForm(Form):
layout = Row("from_date", "to_date", "classes", "teachers")
class HintFilter(django_filters.FilterSet):
class Meta:
model = Hint
fields = ['from_date', "to_date", "classes", "teachers"]
form = HintForm
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from timetable.models import Hint
class HintForm(ModelForm):
class Meta:
model = Hint
fields = ("from_date", "to_date", "text", "classes", "teachers")
def clean(self):
super().clean()
print("validate")
print(self.cleaned_data["classes"], self.cleaned_data["teachers"])
if len(self.cleaned_data["classes"]) == 0 and self.cleaned_data["teachers"] is False:
raise ValidationError("Bitte gib eine Zielgruppe an (Klassen oder Lehrer).")
import datetime
from timetable.models import Hint
def get_all_hints_by_date(date):
hints = filter_date(date)
return hints
def get_all_hints_by_class_and_time_period(_class, from_date, to_date):
hints_tmp = get_all_hints_by_time_period(from_date, to_date)
hints_match = []
for hint in hints_tmp:
if _class.id in [x.class_id for x in hint.classes.all()]:
hints_match.append(hint)
return hints_match
def get_all_hints_for_teachers_by_time_period(from_date, to_date):
hints_tmp = get_all_hints_by_time_period(from_date, to_date)
hints_match = []
for hint in hints_tmp:
if hint.teachers:
hints_match.append(hint)
return hints_match
def get_all_hints_not_for_teachers_by_time_period(from_date, to_date):
hints_tmp = get_all_hints_by_time_period(from_date, to_date)
hints_match = []
for hint in hints_tmp:
if not hint.teachers:
hints_match.append(hint)
return hints_match
def get_all_hints_by_time_period(from_date, to_date):
print(from_date, to_date)
delta = to_date - from_date
print(delta.days + 1)
week_days = [from_date + datetime.timedelta(days=i) for i in range(delta.days + 1)]
hints = []
for week_day in week_days:
hints_tmp = get_all_hints_by_date(week_day)
for hint in hints_tmp:
if hint not in hints:
hints.append(hint)
print(hints)
return hints
def filter_date(date):
hints = Hint.objects.filter(from_date__lte=date, to_date__gte=date).order_by("from_date", "classes")
return hints
import os
import subprocess
from debug.models import register_log_with_filename
from schoolapps.settings import BASE_DIR
# from .models import register_log_with_filename
def convert_markdown_2_latex(s):
try:
# Write markdown file
md_file = open(os.path.join(BASE_DIR, "latex", "m2l.md"), "w", encoding="utf8")
md_file.write(s)
md_file.close()
# Execute pandoc to convert markdown to latex
bash_command = "pandoc --log={} --from markdown --to latex --output {} {}".format(
os.path.join(BASE_DIR, "latex", "m2l.log"),
os.path.join(BASE_DIR, "latex", "m2l.tex"),
os.path.join(BASE_DIR, "latex", "m2l.md"))
process = subprocess.Popen(bash_command.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]
del output
# Register log file in debugging tool
register_log_with_filename("m2l", "m2l", "m2l.log", process.returncode)
# Read converted latex from file
tex_file = open(os.path.join(BASE_DIR, "latex", "m2l.tex"), "r", encoding="utf8")
r = tex_file.read()
tex_file.close()
# Replace some things
r = r.replace("\subparagraph", "\subsubsection")
r = r.replace("\paragraph", "\subsubsection")
r = r.replace("section", "section*")
# Return latex
return r
except Exception as e:
# Print error
print("[MD TO LATEX]", e)
return ""
# Generated by Django 2.1.5 on 2019-04-10 12:30
import datetime
from django.db import migrations, models
import martor.models
class Migration(migrations.Migration):
initial = True
dependencies = [
('untisconnect', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Hint',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('from_date', models.DateField(default=datetime.date.today, verbose_name='Startdatum')),
('to_date', models.DateField(default=datetime.date.today, verbose_name='Enddatum')),
('text', martor.models.MartorField(verbose_name='Hinweistext')),
],
options={
'verbose_name': 'Hinweis',
'verbose_name_plural': 'Hinweise',
},
),
migrations.CreateModel(
name='Timetable',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
options={
'permissions': (('show_plan', 'Show plan'),),
},
),
]
# Generated by Django 2.1.5 on 2019-04-10 12:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timetable', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='HintClass',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('class_id', models.IntegerField()),
],
),
]
# Generated by Django 2.1.5 on 2019-04-10 14:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timetable', '0002_hintclass'),
]
operations = [
migrations.AddField(
model_name='hint',
name='classes',
field=models.ManyToManyField(related_name='hints', to='timetable.HintClass'),
),
migrations.AlterField(
model_name='hintclass',
name='class_id',
field=models.IntegerField(
choices=[(1, '5a'), (2, '5b'), (3, '5c'), (4, '5d'), (5, '6a'), (6, '6b'), (7, '6c'), (8, '6d'),
(9, '7a'), (10, '7b'), (11, '7c'), (12, '7d'), (13, '8a'), (14, '8b'), (15, '8c'), (16, '8d'),
(17, '9a'), (18, '9b'), (19, '9c'), (20, '9d'), (21, 'Ea'), (22, 'Eb'), (23, 'Ec'), (24, 'Ed'),
(25, 'Q1a'), (26, 'Q1b'), (27, 'Q1c'), (28, 'Q1d'), (29, 'Q2a'), (30, 'Q2b'), (31, 'Q2c'),
(32, 'Q2d')]),
),
]
# Generated by Django 2.2 on 2019-04-11 10:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timetable', '0003_auto_20190410_1634'),
]
operations = [
migrations.AddField(
model_name='hint',
name='teachers',
field=models.BooleanField(default=False, verbose_name='Lehrer?'),
),
migrations.AlterField(
model_name='hint',
name='classes',
field=models.ManyToManyField(related_name='hints', to='timetable.HintClass', verbose_name='Klassen'),
),
]
# Generated by Django 2.2 on 2019-04-13 12:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timetable', '0004_auto_20190411_1219'),
]
operations = [
migrations.AlterField(
model_name='hint',
name='classes',
field=models.ManyToManyField(blank=True, related_name='hints', to='timetable.HintClass',
verbose_name='Klassen'),
),
migrations.AlterField(
model_name='hint',
name='teachers',
field=models.BooleanField(blank=True, default=False, verbose_name='Lehrer?'),
),
]
# Generated by Django 2.2.1 on 2019-05-02 15:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timetable', '0005_auto_20190413_1413'),
]
operations = [
migrations.AddField(
model_name='hint',
name='text_as_latex',
field=models.TextField(blank=True, verbose_name='LaTeX (automatisch)'),
),
]
# Generated by Django 2.2.1 on 2019-05-02 15:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timetable', '0006_hint_text_as_latex'),
]
operations = [
migrations.AddField(
model_name='hintclass',
name='class_name',
field=models.CharField(default='', max_length=100),
),
]
# Generated by Django 2.2.1 on 2019-05-02 15:22
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('timetable', '0007_hintclass_class_name'),
]
operations = [
migrations.RenameField(
model_name='hintclass',
old_name='class_name',
new_name='name',
),
]
# Generated by Django 2.2.1 on 2019-05-02 15:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('timetable', '0008_auto_20190502_1722'),
]
operations = [
migrations.AddField(
model_name='hint',
name='classes_formatted',
field=models.CharField(blank=True, max_length=200),
),
]
from django import forms
import dbsettings
from django.db import models
import os
from datetime import date
from untisconnect.api_helper import get_terms
from django.db import models, ProgrammingError
from django.utils import timezone
from martor.models import MartorField
choices = []
terms = get_terms()
for term in terms:
choices.append((term.id, term.name))
from schoolapps.settings import BASE_DIR
from timetable.m2l import convert_markdown_2_latex
from untisconnect.models import Terms
try:
from untisconnect.api import get_all_classes, format_classes
from untisconnect.models import Class
classes = get_all_classes()
class_choices = [(x.id, x.name) for x in classes]
except Terms.DoesNotExist:
classes = []
class_choices = []
class HintClass(models.Model):
"""Maps a UNTIS class to a usable format for Django models"""
class_id = models.IntegerField(choices=class_choices)
name = models.CharField(max_length=100, default="")
def __str__(self):
return self.name
# Map all classes from UNTIS to HintClass objects
try:
for x in classes:
obj, _ = HintClass.objects.get_or_create(class_id=x.id)
obj.name = x.name
obj.save()
except ProgrammingError:
pass
class Hint(models.Model):
# Time
from_date = models.DateField(default=date.today, verbose_name="Startdatum")
to_date = models.DateField(default=date.today, verbose_name="Enddatum")
# Text
text = MartorField(verbose_name="Hinweistext")
# Relations
classes = models.ManyToManyField(HintClass, related_name="hints", verbose_name="Klassen", blank=True)
teachers = models.BooleanField(verbose_name="Lehrer?", default=False, blank=True)
# Caching
text_as_latex = models.TextField(verbose_name="LaTeX (automatisch)", blank=True)
classes_formatted = models.CharField(max_length=200, blank=True)
class Timetable(models.Model):
class Meta:
permissions = (
('show_plan', 'Show plan'),
)
verbose_name = "Hinweis"
verbose_name_plural = "Hinweise"
def __init__(self, *args, **kwargs):
super(Hint, self).__init__(*args, **kwargs)
def __str__(self):
targets = self.classes_formatted
if self.teachers and targets != "":
targets += ", Lehrkräfte"
elif self.teachers:
targets = "Lehrkräfte"
return "[{}]: {}–{}".format(targets, self.from_date, self.to_date)
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
# Convert LaTeX already when saving as cache because then is no need to do it later > performance savings
self.text_as_latex = convert_markdown_2_latex(self.text)
super(Hint, self).save(force_insert=force_insert, force_update=force_update, using=using,
update_fields=update_fields)
class UNTISSettings(dbsettings.Group):
term = dbsettings.IntegerValue(widget=forms.Select, choices=choices)
# Format classes already > cache, too
self.classes_formatted = format_classes(self.classes.all())
super(Hint, self).save(force_insert=force_insert, force_update=force_update, using=using,
update_fields=update_fields)
untis_settings = UNTISSettings()
class Timetable(models.Model):
class Meta:
permissions = (
('show_plan', 'Show plan'),
)
import os
import subprocess
from django.utils import timezone
from django.utils import formats
from django.template.loader import render_to_string
from schoolapps.settings import BASE_DIR
from debug.models import register_log_with_filename
# LaTeX constants
# from untisconnect.sub import get_header_information
DIR = os.path.join(BASE_DIR, "static", "common", "logo.png")
TEX_HEADER_1 = """\\documentclass[11pt]{article}
\\usepackage[ngerman]{babel}
\\usepackage[sfdefault]{cabin}
\\usepackage[utf8]{inputenc}
\\usepackage[a4paper,left=1cm,right=1cm,top=2cm,bottom=2cm,bindingoffset=0mm]{geometry}
% Packages
\\usepackage{fancyhdr}
\\usepackage{graphicx}
\\usepackage{longtable}
\\usepackage{multirow}
\\usepackage{color, colortbl}
\\usepackage{geometry}
\\usepackage{ulem, xpatch}
\\xpatchcmd{\\sout}
{\\bgroup}
{\\bgroup\def\\ULthickness{1.5pt}}
{}{}
% Badge box
\\usepackage{tcolorbox}
\\newtcbox{\\badge}{nobeforeafter,colframe=green,colback=green,boxrule=0.5pt,arc=4pt,
boxsep=0pt,left=5pt,right=5pt,top=5pt,bottom=5pt,tcbox raise base,
grow to left by=0pt,
grow to right by=-3pt,
enlarge top by=3pt,
enlarge bottom by=3pt,coltext=white}
% Define colors
\\definecolor{grey}{RGB}{208, 208, 208}
\\definecolor{darkgrey}{rgb}{0.6,0.6,0.6}
\\definecolor{white}{rgb}{1,1,1}
\\definecolor{green}{RGB}{76,175,80}
% Define header
\\pagestyle{fancy}
% Left header: logo
\\lhead{\\includegraphics[width=5cm]{"""
TEX_HEADER_2 = """}}
% Define footer
\\lfoot{Katharineum zu Lübeck}
\\cfoot{\\thepage}
\\rfoot{\\small Umsetzung: © 2018--2019 by Computer-AG}
\\begin{document}"""
TEX_HEADER = TEX_HEADER_1 + DIR + TEX_HEADER_2
TEX_FOOTER = '\end{document}'
TEX_TABLE_HEADER_CLASS = """
% Init table
\def\\arraystretch{1.5}
\\begin{longtable}{p{20mm}p{8mm}p{32mm}p{25mm}p{30mm}p{45mm}}
\\textbf{Klassen} &
\\textbf{Std.} &
\\textbf{Lehrer} &
\\textbf{Fach} &
\\textbf{Raum} &
\\textbf{Hinweis}\\\\
\\hline
\\endhead
"""
TEX_HEADER_CLASS = """
\\rhead{\\textbf{Vertretungen %s}\\\\Stand: %s\\\\ }
\\Large
\\subsubsection*{}
\\section*{\\Huge Vertretungen %s}
\n"""
TEX_HEADER_BOX_START = """
\\fbox{\\parbox{0.27\\linewidth}{
"""
TEX_HEADER_BOX_MIDDLE = """
}\\parbox{0.73\\linewidth}{
"""
TEX_HEADER_BOX_END = """
}} \n\n
"""
TEX_HEADER_BOX_ROW_A = """
\\textbf{%s}
"""
TEX_HEADER_BOX_ROW_B = """
%s
"""
LOGO_FILENAME = os.path.join(BASE_DIR, "static", "common", "logo.png")
def generate_pdf(tex, filename):
"""Generate a PDF by LaTeX code"""
# Read LaTeX file
# Write LaTeX file
tex_file = open(os.path.join(BASE_DIR, "latex", filename + ".tex"), "w", encoding="utf8")
tex_file.write(tex)
tex_file.close()
# Execute pdflatex to generate the PDF
bash_command = "pdflatex -output-directory {} {}.tex".format(os.path.join(BASE_DIR, "latex"),
os.path.join(BASE_DIR, "latex", filename))
print(bash_command)
bash_command = "pdflatex -halt-on-error -output-directory {} {}.tex".format(os.path.join(BASE_DIR, "latex"),
os.path.join(BASE_DIR, "latex",
filename))
process = subprocess.Popen(bash_command.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]
print(output)
del output
def tex_replacer(s):
"""Replace HTML tags by LaTeX tags"""
# Register log file in debugging tool
register_log_with_filename("latex_{}".format(filename), "latex", "{}.log".format(filename), process.returncode)
# Strong text
s = s.replace("<strong>", "\\textbf{")
s = s.replace("</strong>", "}")
# Struck out text
s = s.replace("<s>", "\\sout{")
s = s.replace("</s>", "}")
# Arrow
s = s.replace("", "$\\rightarrow$")
return s
def generate_class_tex(subs, date, header_info):
def generate_class_tex(subs, date, header_info, hints=None):
"""Generate LaTeX for a PDF by a substitution table"""
tex_body = ""
# Format dates
status_date = formats.date_format(date, format="j. F Y, \\K\\W W ")
current_date = formats.date_format(timezone.datetime.now(), format="j. F Y H:i")
head_date = formats.date_format(date, format="l, j. F Y")
# Generate header with dates
tex_body += TEX_HEADER_CLASS % (status_date, current_date, head_date)
if header_info.is_box_needed():
tex_body += TEX_HEADER_BOX_START
for row in header_info.rows:
tex_body += TEX_HEADER_BOX_ROW_A % row[0]
tex_body += TEX_HEADER_BOX_MIDDLE
for row in header_info.rows:
tex_body += TEX_HEADER_BOX_ROW_B % row[1]
tex_body += TEX_HEADER_BOX_END
# Begin table
tex_body += TEX_TABLE_HEADER_CLASS
color_background = True
last_classes = ""
for sub in subs:
# Color groups of classes in grey/white
if last_classes != sub.classes:
color_background = not color_background
last_classes = sub.classes
if color_background:
tex_body += '\\rowcolor{grey}'
# Get color tag for row
color = "\color{%s}" % sub.color
# Print classes
# print(sub.classes)
tex_body += color
tex_body += '\\textbf{' + sub.classes + '} & '
# Print lesson number, teacher, subject and room
for i in [sub.lesson, sub.teacher, sub.subject, sub.room]:
tex_body += color
tex_body += tex_replacer(i) + ' & '
# Print badge (Cancellation)
if sub.badge is not None:
tex_body += """\\large\\badge{%s}""" % sub.badge
# Print notice and new line
tex_body += color
tex_body += "\\Large\\textit{%s}\\\\\n" % (sub.text or "")
# End table
tex_body += '\\end{longtable}'
# Connect header, body and footer
tex_content = TEX_HEADER + tex_body + TEX_FOOTER
return tex_content
context = {
"subs": subs,
"date": date,
"header_info": header_info,
"LOGO_FILENAME": LOGO_FILENAME,
"hints": hints
}
return render_to_string("timetable/latex/substitutions.tex", context)
import dbsettings
from django import forms
from untisconnect.api_helper import get_terms
choices = []
terms = get_terms()
for term in terms:
choices.append((term.id, term.name))
class UNTISSettings(dbsettings.Group):
term = dbsettings.IntegerValue(widget=forms.Select, choices=choices)
untis_settings = UNTISSettings()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment