Initialisierung: Übertragung aus altem Repository

This commit is contained in:
2021-07-12 00:49:07 +02:00
commit c7f0c6a1c4
80 changed files with 12063 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/admin/index.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Administration{% endblock %}
{% block header %}Administration{% endblock %}
{% block content %}
<p><a href="{{ url_for('admin.lehrer.index') }}" data-icon="&#xf0c0;">Lehrerkonten</a></p>
<p><a href="{{ url_for('admin.sql_access') }}" data-icon="&#xf1c0;">SQL-Zugriff</a></p>
{% endblock %}
@@ -0,0 +1,45 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/admin/lehrer/add.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Lehrer(in) hinzufügen{% endblock %}
{% block header %}Lehrer(in) hinzufügen{% endblock %}
{% block content %}
<form method="post">
<div class="table-aligned">
<div>
<div><label for="kuerzel-input">Lehrerkürzel:</label></div>
<div><input type="text" name="kuerzel" id="kuerzel-input" autocomplete="off" required autofocus></div>
</div>
<div>
<div><label for="password-input">Passwort:</label></div>
<div><input type="password" name="password" id="password-input" autocomplete="off" required></div>
</div>
</div>
<label>
<input type="checkbox" name="force-password-change" id="force-password-change-cb">
bei Erstanmeldung Passwortänderung erzwingen
</label>
<p><input type="submit" value="Hinzufügen"></p>
</form>
{% endblock %}
@@ -0,0 +1,90 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/admin/lehrer/edit.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Lehrer(in): {{ lehrer.kuerzel }}{% endblock %}
{% block header %}Lehrer(in): {{ lehrer.kuerzel }}{% endblock %}
{# lehrer #}
{% set stufen_list = Stufe.query.all() %}
{% block js_head %}
var delete_warn = "Durch das Löschen eines Lehrerkontos werden alle Klausuren,\ndie dem gelöschten Konto zugeordnet "
+ "sind, unwiderruflich gelöscht.\nWollen Sie wirklich fortfahren?"
{% endblock %}
{% block content %}
<form method="post">
<input name="action" type="hidden" value="change-credentials">
<div class="table-aligned">
<div>
<div><label for="new-kuerzel-input">Lehrerkürzel:</label></div>
<div><input type="text" name="new-kuerzel" id="new-kuerzel-input" value="{{ lehrer.kuerzel }}" required></div>
</div>
<div>
<div><label for="new-email-input">E-Mail-Adresse:</label></div>
<div>
<input type="email" name="new-email" id="new-email-input"
value="{% if lehrer.email %}{{ lehrer.email }}{% endif %}" autocomplete="off">
</div>
{% if lehrer.email is not none %}
<div>
{% if lehrer.is_confirmed %}
<span class="positive-status" title="bestätigt"></span>
{% else %}
<span class="negative-status">nicht bestätigt</span>
{% endif %}
</div>
{% endif %}
</div>
<div>
<div><label for="new-password-input">Neues Passwort:</label></div>
<div><input type="password" name="new-password" id="new-password-input" autocomplete="new-password"></div>
</div>
<div>
<div><label for="new-beraet-select">Beratungslehrer(in) von:</label></div>
<div><select name="new-beraet" id="new-beraet-select">
<option value="">(keine Stufe)</option>
{% for stufe in stufen_list %}
<option {% if stufe.name == lehrer.beraet.name %}selected{% endif %}>{{ stufe.name }}</option>
{% endfor %}
</select></div>
</div>
<div>
<div><label for="new-admin-cb">Administrator(in):</label></div>
<div>
<input type="checkbox" name="new-admin" id="new-admin-cb" value="admin"
{% if lehrer.is_admin %}checked{% endif %}>
</div>
</div>
</div>
<p><input type="submit" value="Speichern"></p>
</form>
<br>
<form method="post">
<h3>Benutzerkonto löschen</h3>
<input name="action" type="hidden" value="delete-account">
<p><input onclick="return confirm(delete_warn)" type="submit" value="Benutzerkonto jetzt löschen"></p>
</form>
{% endblock %}
@@ -0,0 +1,69 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/admin/lehrer/index.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Lehrerkonten{% endblock %}
{% block header %}Lehrerkonten{% endblock %}
{% set lehrer_list = Lehrer.query.order_by(Lehrer.kuerzel).all() %}
{% block content %}
<p><a href="{{ url_for('admin.lehrer.add') }}" data-icon="&#xf234;">Lehrer(in) hinzufügen</a></p>
<p>Klicken Sie eine Zeile aus der folgenden Übersicht an, um ein bestehendes Benutzerkonto zu bearbeiten.</p>
<table>
<thead>
<tr>
<th>Kürzel</th>
<th>E-Mail-Adresse</th>
<th>Admin</th>
<th>Beratungslehrer(in)</th>
<th>Passwort<br>gesetzt</th>
</tr>
</thead>
<tbody>
{% for l in lehrer_list %}
<tr class="clickable" tabindex="0" data-href="{{ url_for('admin.lehrer.edit', lehrer_id=l.id) }}">
<td>{{ l.kuerzel }}</td>
<td>
{% if l.email is not none %}
{{ l.email }}
{% if l.is_confirmed %}
<span class="positive-status" title="bestätigt"></span>
{% else %}
<span class="negative-status" title="nicht bestätigt"></span>
{% endif %}
{% else %}
<span class="detail">(keine)</span>
{% endif %}
</td>
<td>{{ 'ja' if l.is_admin else 'nein' }}</td>
<td>{{ l.beraet.name if l.beraet is not none else '<span class="detail">(keine Stufe)</span>' }}</td>
{% if l.pwd_changed %}
<td class="positive-status">ja</td>
{% else %}
<td class="negative-status">nein</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
@@ -0,0 +1,83 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/admin/sql_access.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}SQL-Zugriff{% endblock %}
{% block header %}SQL-Zugriff{% endblock %}
{# result: Ergebnis einer SQL-Abfrage als sqlalchemy.engine.ResultProxy #}
{% block content %}
<p>
Diese Seite erlaubt direkten Zugriff auf die SQL-Datenbank von NateMan durch die Eingabe von SQL-Abfragen.<br>
<b>
Bei falscher Anwendung können Daten unwiderruflich verloren gehen.<br>
Außerdem kann es bei der Veränderung bestimmter Daten zu unerwarteten Fehlern in der NateMan-Anwendung kommen.<br>
<span class="marked">Benutzen Sie diese Seite nur, wenn Sie wissen, was Sie tun.</span>
</b>
</p>
<p>
{% set nateman_erm_url = url_for('static', filename='img/nateman-erm.svg') %}
<a href="{{ nateman_erm_url }}" target="_blank" rel="noreferrer noopener">
<img src="{{ nateman_erm_url }}" height="500" alt="Entity-Relationship-Modell der NateMan-Datenbank"
title="Entity-Relationship-Modell der NateMan-Datenbank">
</a>
</p>
<form method="post">
<p>
<textarea name="query" class="monospace" rows="8" cols="96" placeholder="SQL-Abfrage hier eingeben"
required autofocus>{{ query }}</textarea>
</p>
<p><input type="submit" value="Ausführen"></p>
</form>
{% if result is not none and result.returns_rows %}
{% set result_rows = result.fetchall() %}
<h3>Ergebnis ({{ result_rows|length }} Zeilen):</h3>
<table class="monospace">
<thead>
<tr>
{% for col_name in result.keys() %}
<th>{{ col_name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in result_rows %}
<tr>
{% for value in row._mapping.values() %}
{% if value is none %}
<td class="detail">NULL</td>
{% else %}
<td>{{ value }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}
+67
View File
@@ -0,0 +1,67 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/auth/account.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Benutzereinstellungen{% endblock %}
{% block header %}Benutzereinstellungen{% endblock %}
{% block content %}
<form method="post">
<div class="table-aligned">
<div>
<div><label for="current-password-input">Aktuelles Passwort:</label></div>
<div>
<input type="password" name="current-password" id="current-password-input" autocomplete="current-password"
required autofocus>
</div>
</div>
<div>
<div><label for="new-email-input">E-Mail-Adresse:</label></div>
<div>
<input type="email" name="new-email" id="new-email-input"
value="{% if g.lehrer.email %}{{ g.lehrer.email }}{% endif %}">
</div>
{% if g.lehrer.email is not none %}
<div>
{% if g.lehrer.is_confirmed %}
<span class="positive-status" title="bestätigt"></span>
{% else %}
<span class="negative-status">nicht bestätigt</span>
{% endif %}
</div>
{% endif %}
</div>
<div>
<div><label for="new-password-input">Neues Passwort:</label></div>
<div>
<input type="password" name="new-password" id="new-password-input" autocomplete="new-password" minlength="6">
</div>
</div>
<div>
<div><label for="new-password-confirm-input">&#x21B3; wiederholen:</label></div>
<div>
<input type="password" name="new-password-confirm" id="new-password-confirm-input" autocomplete="new-password">
</div>
</div>
</div>
<p><input type="submit" value="Speichern"></p>
</form>
{% endblock %}
+48
View File
@@ -0,0 +1,48 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/auth/login.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Anmelden{% endblock %}
{% block header %}Anmelden{% endblock %}
{% block content %}
<form method="post">
<div class="table-aligned">
<div>
<div><label for="kuerzel-input">Lehrerkürzel:</label></div>
<div><input type="text" name="kuerzel" id="kuerzel-input" autocomplete="username" required autofocus></div>
</div>
<div>
<div><label for="password-input">Passwort:</label></div>
<div><input type="password" name="password" id="password-input" autocomplete="current-password" required></div>
</div>
<div>
<div><label for="remember-me-cb">Angemeldet bleiben:</label></div>
<div><input type="checkbox" name="remember-me" id="remember-me-cb"></div>
</div>
</div>
<p>
<input type="submit" value="Anmelden">
<a href="{{ url_for('auth.password_reset') }}">Passwort vergessen</a>
</p>
</form>
{% endblock %}
@@ -0,0 +1,48 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/auth/password-change.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Neues Passwort{% endblock %}
{% block header %}Neues Passwort{% endblock %}
{% block content %}
<p>Bitte geben Sie ein neues Passwort für Ihr Benutzerkonto ein.</p>
<form method="post">
<div class="table-aligned">
<div>
<div><label for="new-password-input">Neues Passwort:</label></div>
<div>
<input type="password" name="new-password" id="new-password-input" autocomplete="new-password" minlength="6"
required autofocus>
</div>
</div>
<div>
<div><label for="new-password-confirm-input">&#x21B3; wiederholen:</label></div>
<div>
<input type="password" name="new-password-confirm" id="new-password-confirm-input" autocomplete="new-password"
required>
</div>
</div>
</div>
<p><input type="submit" value="Speichern"></p>
</form>
{% endblock %}
@@ -0,0 +1,46 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/auth/password-reset-do.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Passwort zurücksetzen{% endblock %}
{% block header %}Passwort zurücksetzen{% endblock %}
{% block content %}
<form method="post">
<div class="table-aligned">
<div>
<div><label for="new-password-input">Neues Passwort:</label></div>
<div>
<input type="password" name="new-password" id="new-password-input" autocomplete="new-password" minlength="6"
required autofocus>
</div>
</div>
<div>
<div><label for="new-password-confirm-input">&#x21B3; wiederholen:</label></div>
<div>
<input type="password" name="new-password-confirm" id="new-password-confirm-input" autocomplete="new-password"
required>
</div>
</div>
</div>
<p><input type="submit" value="Passwort setzen"></p>
</form>
{% endblock %}
@@ -0,0 +1,43 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/auth/password-reset-send.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Passwort zurücksetzen{% endblock %}
{% block header %}Passwort zurücksetzen{% endblock %}
{% block content %}
<form method="post">
<div class="table-aligned">
<div>
<div><label for="lehrer-kuerzel-input">Lehrerkürzel:</label></div>
<div>
<input type="text" name="lehrer-kuerzel" id="lehrer-kuerzel-input" autocomplete="username" required autofocus>
</div>
</div>
<div>
<div><label for="email-address-input">E-Mail-Adresse:</label></div>
<div><input type="email" name="email-address" id="email-address-input" required></div>
</div>
</div>
<p><input type="submit" value="Absenden"></p>
</form>
{% endblock %}
+203
View File
@@ -0,0 +1,203 @@
<!DOCTYPE html>
{# von Niklas Elsbrock #}
{% macro zeitraum(klausur) -%}
{{- klausur.startperiod }}.
{%- if klausur.startperiod != klausur.endperiod -%}
&ndash;{{ klausur.endperiod }}.
{%- endif %}
{%- endmacro %}
<!-- generiert aus Template-Code von Niklas Elsbrock -->
<html lang="de">
<head>
<meta charset="utf-8">
<title>{% block title %}{% endblock %} &ndash; NateMan</title>
<link rel="icon" type="image/png" sizes="192x192"
href="{{ url_for('static', filename='img/logo.png') }}">
<link rel="apple-touch-icon" href="{{ url_for('static', filename='img/icon-apple.png') }}">
<!--[if !IE]><!-->
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<!--<![endif]-->
<script>
window.onload = function() {
{% for message in get_flashed_messages(with_categories=True, category_filter='alert') %}
alert({{ message[1] | tojson }});
{% endfor %}
{% block js_window_onload %}{% endblock %}
};
{% block js_head %}{% endblock %}
</script>
{% block head %}{% endblock %}
</head>
<body>
<header>
<a id="nateman-logo-container" href="{{ url_for('klausuren.mine' if g.lehrer is not none else 'index.index') }}">
<img id="nateman-logo" alt="NateMan Logo"
src="{{ url_for('static', filename='img/logo.png') }}" draggable="false">
</a>
<h1 class="header-text">NateMan<span class="optional">&nbsp;&ndash;&nbsp;Nachschreibtermin-Manager</span></h1>
</header>
<!--[if IE]>
<p style="color: #ff0000; font-size: 25px;">
Diese Seite wird im Internet Explorer nicht richtig angezeigt.<br>
Um sie richtig angezeigt zu bekommen, benutzen Sie einen anderen Browser.
</p>
<![endif]-->
<nav>
{% if g.lehrer is not none %}
<a href="{{ url_for('auth.logout') }}" data-icon="&#xf2f5;">
<span>
Angemeldet als <b>{{ g.lehrer.kuerzel }}</b><br>
<b>Abmelden</b>
</span>
</a>
{% else %}
<a href="{{ url_for('auth.login') }}" data-icon="&#xf2f6;">
<span>Anmelden</span>
</a>
<a href="{{ url_for('auth.password_reset') }}" data-icon="&#xf1cd;">
<span>Passwort vergessen</span>
</a>
{% endif %}
<hr>
{% if g.lehrer is not none and g.lehrer.pwd_changed %}
<a href="{{ url_for('klausuren.mine') }}" data-icon="&#xf015;">
<span>Meine Klausuren</span>
</a>
{% endif %}
{% if g.lehrer is none or g.lehrer.pwd_changed %}
{% for stufe in Stufe.query.all() %}
<a href="{{ url_for('klausuren.stufe', stufe_name=stufe.name) }}" data-icon="&#xf00b;">
<span>Klausuren {{ stufe.name }}</span>
</a>
{% endfor %}
{% endif %}
{% if g.lehrer is not none and g.lehrer.pwd_changed %}
{% if g.lehrer.can_access() %}
<a href="{{ url_for('schueler.versaeumnisse') }}" data-icon="&#xf5ae;">
<span>Versäumnisse</span>
</a>
{%
if Klausurteilnahme.query.join(Klausur)
.filter(Klausurteilnahme.versaeumt)
.filter(Klausurteilnahme.nachgeschrieben == false)
.filter(Klausur.stufe_name.in_(g.lehrer.accessible_stufen(names=True)))
.count() != 0
%}
<hr>
<a href="{{ url_for('fileio.export') }}" data-icon="&#xf56e;">
<span>Nachschreibplan exportieren</span>
</a>
{% elif g.lehrer.is_admin %}
<hr>
{% endif %}
{% if g.lehrer.is_admin %}
<a href="{{ url_for('fileio.import') }}" data-icon="&#xf56f;">
<span>Klausurpläne importieren</span>
</a>
{% endif %}
{% endif %}
<hr>
<a href="{{ url_for('auth.account') }}" data-icon="&#xf4fe;">
<span>Mein Konto</span>
</a>
{% if g.lehrer.is_admin %}
<a href="{{ url_for('admin.index') }}" data-icon="&#xf084;">
<span>Administration</span>
</a>
{% endif %}
{% endif %}
</nav>
<div id="flash-container">
{% for message in get_flashed_messages(with_categories=True) %}
{% if message[0] != 'alert' %}
<div class="flash flash-{{ message[0] }}" tabindex="0">
{{ message[1] | replace('\n', '<br>') }}
</div>
{% endif %}
{% endfor %}
</div>
<div id="page-section">
<div id="page">
<main>
<noscript>
<p class="warn">
JavaScript ist in Ihrem Browser deaktiviert bzw. nicht unterstützt.
Diese Seite benötigt JavaScript, um richtig zu funktionieren.
</p>
</noscript>
{% if g.lehrer and g.lehrer.pwd_changed %}
{% if g.lehrer.email is none %}
<p class="warn">{#
#}Sie haben keine E-Mail-Adresse festgelegt.
<a href="{{ url_for('auth.account') }}">Festlegen</a>
</p>
{% elif not g.lehrer.is_confirmed %}
<p class="warn">Sie haben Ihre E-Mail-Adresse noch nicht bestätigt.</p>
{% endif %}
{% endif %}
<h2 class="page-heading">{% block header %}{% endblock %}</h2>
{% block content %}{% endblock %}
</main>
<footer>
<div class="footer-left">
<a href="{{ nateman_config['schule']['website-url'] }}">
<img id="school-logo"
src="{{ nateman_config['schule'].get('schule.logo-url') or url_for('static', filename='img/school-logo.png') }}"
alt="Schullogo" draggable="false">
</a>
</div>
<div class="footer-right">
<span style="float: left">
<a href="{{ nateman_config['schule']['website-url'] }}">
{{ nateman_config['schule']['name'] }}
</a>
<br>
<a href="https://github.com/nelsbrock/NateMan">
NateMan&nbsp;&ndash;&nbsp;Nachschreibtermin-Manager
</a>
</span>
<span style="float: right">
<a href="{{ nateman_config['schule']['imprint-url'] }}">Impressum</a>
&middot;
<a href="{{ nateman_config['schule']['privacy-policy-url'] }}">Datenschutz</a>
&middot;
<a href="{{ url_for('info.licenses') }}">Font-Lizenzen</a>
</span>
</div>
</footer>
</div>
</div>
<script src="{{ url_for('static', filename='script.js') }}" charset="utf-8"></script>
<script>
{% block js_body_end %}{% endblock %}
</script>
</body>
</html>
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
{#
NateMan Nachschreibtermin-Manager
templates/email/base.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
<html lang="de">
<head>
<meta charset="utf-8">
</head>
<body>
<h2>{% block header %}{% endblock %}</h2>
{% block content %}{% endblock %}
<hr>
<aside style="color: #777777">
Diese E-Mail wurde automatisch versandt. Eine Antwort ist nicht nötig.
</aside>
</body>
</html>
@@ -0,0 +1,30 @@
{% extends 'email/base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/email/confirmation.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block header %}Bestätigung Ihrer E-Mail-Adresse für NateMan{% endblock %}
{% block content %}
<p>
Um die E-Mail-Adresse für Ihr Benutzerkonto beim Nachschreibtermin-Manager zu
bestätigen, klicken Sie <a href="{{ url_for('auth.confirm_email', token=token, _external=True) }}">hier</a>.
</p>
{% endblock %}
@@ -0,0 +1,31 @@
{% extends 'email/base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/email/password-reset.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block header %}Passwortzurücksetzung{% endblock %}
{% block content %}
<p>
Für Ihr Benutzerkonto beim Nachschreibtermin-Manager wurde eine Passwortzurücksetzung beantragt.<br>
Sie können Ihr Passwort <a href="{{ url_for('auth.password_reset', token=token, _external=True) }}">hier</a> ändern.
Der Link ist eine Stunde lang gültig.
</p>
{% endblock %}
+43
View File
@@ -0,0 +1,43 @@
{% extends 'email/base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/email/reminder.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block header %}Zur Erinnerung{% endblock %}
{% block content %}
<p>
Folgende Klausuren müssen noch bearbeitet werden:
<ul>
{% for k in not_edited_list %}
<li>
<a href="{{ url_for('klausuren.edit', klausur_id=k.id, _external=True) }}">
{{ k.kursname }} ({{ k.date_formatted() }}; {{ k.stufe.name }})
</a>
</li>
{% endfor %}
</ul>
</p>
<p>
Klicken Sie <a href="{{ url_for('klausuren.mine', _external=True) }}">hier</a>,
um alle Klausuren von Ihnen zu sehen.
</p>
{% endblock %}
+33
View File
@@ -0,0 +1,33 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/error/400.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Fehler{% endblock %}
{% block header %}Fehler{% endblock %}
{% block content %}
<p>Ihr Browser hat eine ungültige Anfrage gesendet.</p>
<p>
Dies kann passieren, wenn Sie versuchen Daten zu verändern,<br>
die in der Zwischenzeit von anderer Stelle verändert bzw. entfernt wurden.<br>
Versuchen Sie, die gerade ausgeführte Aktion zu wiederholen.
</p>
<p class="detail">400 BAD REQUEST</p>
{% endblock %}
+28
View File
@@ -0,0 +1,28 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/error/403.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Kein Zugriff{% endblock %}
{% block header %}Kein Zugriff{% endblock %}
{% block content %}
<p>Auf diese Seite haben Sie keinen Zugriff.</p>
<p class="detail">403 FORBIDDEN</p>
{% endblock %}
+28
View File
@@ -0,0 +1,28 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/error/404.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Fehler{% endblock %}
{% block header %}Fehler{% endblock %}
{% block content %}
<p>Diese Seite existiert nicht.</p>
<p class="detail">404 NOT FOUND</p>
{% endblock %}
+28
View File
@@ -0,0 +1,28 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/error/500.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Serverfehler{% endblock %}
{% block header %}Hoppala!{% endblock %}
{% block content %}
<p>Es ist ein serverseitiger Fehler aufgetreten.</p>
<p class="detail">500 INTERNAL SERVER ERROR</p>
{% endblock %}
+88
View File
@@ -0,0 +1,88 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/fileio/import.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Klausurpläne importieren{% endblock %}
{% block header %}Klausurpläne importieren{% endblock %}
{% set stufen_list = Stufe.query.all() %}
{% block js_head %}
var plan_delete_warn = "Durch das Löschen eines Plans werden alle importierten sowie nachträglich hinzugefügten\n"
+ "Daten der Stufe (Klausurtermine, Klausuren, Schüler(innen)) unwiderruflich gelöscht.\n"
+ "Lehrerkonten bleiben unberührt.\n\nWollen Sie wirklich fortfahren?";
var import_warn = "Durch das Importieren von Klausurplänen werden bestehende importierte sowie nachträglich "
+ "hinzugefügte\nDaten (Klausurtermine, Klausuren, Schüler(innen)) aller Stufen, für die neue Pläne "
+ "importiert wurden, unwiderruflich gelöscht.\nBestehende Lehrerkonten bleiben unberührt.\n\n"
+ "Durch das Importieren von Koopschüler(inne)n werden alle bestehenden Koopschüler(innen) "
+ "gelöscht.\n\nWollen Sie wirklich fortfahren?";
{% endblock %}
{% block js_body_end %}
document.getElementById("import-button").onclick = function () {
if (!confirm(import_warn)) {
return false;
}
this.disabled = true;
this.value = 'Bitte warten...';
this.form.submit();
return true;
}
{% endblock %}
{% block content %}
<form method="post" enctype="multipart/form-data">
<div class="table-aligned">
{% for stufe in stufen_list %}
<div>
<div><label for="plan_{{ stufe.name }}-input">Plan für {{ stufe.name }}:</label></div>
<div><input type="file" name="plan_{{ stufe.name }}" id="plan_{{ stufe.name }}-input" accept="text/xml"></div>
<div>
<input type="submit" name="del_{{ stufe.name }}" value="Plan löschen"
onclick="return confirm(plan_delete_warn)" {% if stufe.import_date is none %}disabled{% endif %}>
</div>
<div class="detail">
{% if stufe.import_date is none %}
nicht importiert
{% else %}
importiert am {{ stufe.import_date.strftime("%d.%m.%Y") }}
{% endif %}
</div>
</div>
{% endfor %}
</div>
<p>
<label>
Koopschüler(innen)liste:
<input type="file" name="koopschueler" id="koopschueler-input" accept=".xlsx,.xlsm,.xltx,.xltm">
</label>
</p>
<p>
<label>
Passwort für neu registrierte Lehrer(innen):
<input name="new-lehrer-password" type="text" id="new-lehrer-password-input"
value="{{ nateman_config['default-new-lehrer-password'] }}">
</label>
</p>
<p><input type="submit" value="Importieren" id="import-button"></p>
</form>
{% endblock %}
+35
View File
@@ -0,0 +1,35 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/index/index.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Startseite{% endblock %}
{% block header %}Startseite{% endblock %}
{% block content %}
<p>
Sie befinden sich auf der Startseite des Nachschreibtermin-Managers.<br>
Von hier aus können Sie die Klausurpläne für die Stufen
{% for stufe in Stufe.query.all() -%}
{%- if not loop.first -%}{%- if loop.last %} und {% else -%}, {% endif -%}{%- endif -%}
<a href="{{ url_for('klausuren.stufe', stufe_name=stufe.name) }}">{{ stufe.name }}</a>
{%- endfor %}
einsehen oder sich als Lehrer <a href="{{ url_for('auth.login') }}">anmelden</a>.
</p>
{% endblock %}
+38
View File
@@ -0,0 +1,38 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/info/licenses.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Lizenzen{% endblock %}
{% block header %}Lizenzen{% endblock %}
{% block content %}
<h3>Schriftart: Lato</h3>
<p>
Copyright (c) 2010-2015, Łukasz Dziedzic (dziedzic@typoland.com), with Reserved Font Name Lato.<br>
Licensed under the <a href="https://scripts.sil.org/OFL">SIL Open Font License, Version 1.1</a>.
</p>
<h3>Symbole (Icons): Font Awesome Free</h3>
<p>
Font Awesome Free 5.13.1 by @fontawesome - <a href="https://fontawesome.com">https://fontawesome.com</a><br>
License - <a href="https://fontawesome.com/license/free">https://fontawesome.com/license/free</a>
(Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
</p>
{% endblock %}
+78
View File
@@ -0,0 +1,78 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/klausuren/add.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Klausur hinzufügen{% endblock %}
{% block header %}Klausur hinzufügen{% endblock %}
{% block js_body_end %}
var startperiod_input = document.getElementById('startperiod-input');
var endperiod_input = document.getElementById('endperiod-input');
startperiod_input.onchange = function () {
endperiod_input.min = parseInt(startperiod_input.value);
}
// beim Laden der Seite einmal ausführen
startperiod_input.onchange();
{% endblock %}
{% block content %}
<form method="post">
<div class="table-aligned">
<div>
<div>Stufe:</div>
<div>{{ stufe.name }}</div>
</div>
<div>
<div><label for="kursname-input">Kursname:</label></div>
<div><input type="text" name="kursname" id="kursname-input" placeholder="z.B. M-GK3" required autofocus></div>
</div>
<div>
<div><label for="lehrer-select">Kurslehrer(in):</label></div>
<div>
<select name="lehrer" id="lehrer-select" required>
<option value="" selected disabled>Bitte auswählen</option>
{% for l in Lehrer.query.order_by(Lehrer.kuerzel).all() %}
<option value="{{ l.id }}">{{ l.kuerzel }}</option>
{% endfor %}
</select>
</div>
</div>
<div>
<div><label for="date-input">Klausurdatum:</label></div>
<div><input type="date" name="date" id="date-input" required></div>
</div>
<div>
<div>Klausurzeitraum:</div>
<div>
<input type="number" name="startperiod" id="startperiod-input" class="small" min="0" max="2147483647"
required>{#
#}. bis
<input type="number" name="endperiod" id="endperiod-input" class="small" min="0" max="2147483647"
required>{#
#}. Stunde
</div>
</div>
</div>
<p><input type="submit" value="Hinzufügen"></p>
</form>
{% endblock %}
+348
View File
@@ -0,0 +1,348 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/klausuren/edit.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}
Klausur: {{ klausur.kursname }}
({{ klausur.date_formatted() }}; {{ klausur.lehrer.kuerzel }}, {{ klausur.stufe.name }})
{% endblock %}
{% block header %}
Klausur: {{ klausur.kursname }}
({{ klausur.date_formatted() }}; {{ klausur.lehrer.kuerzel }}, {{ klausur.stufe.name }})
{% endblock %}
{# klausur #}
{# kt_list: Liste aller Klausurteilnahmen dieser Klausur #}
{# not_in_klausur_list: Liste aller Schüler dieser Stufe, die nicht in dieser Klausur sind #}
{% set lehrer_can_access = g.lehrer.can_access(klausur.stufe) %}
{% set is_bygone = klausur.is_bygone() %}
{% set no_edit = (klausur.edited or not is_bygone) and not lehrer_can_access %}
{% block js_body_end %}
var schuelerCBs = document.getElementsByClassName("schueler-cb");
for (scb of schuelerCBs) {
scb.onchange = function () {
if (this.checked) {
this.parentNode.classList.add("marked");
} else {
this.parentNode.classList.remove("marked");
}
}
// beim Laden der Seite einmal ausführen
scb.onchange();
}
{% if not no_edit %}
var noneVersaeumtCB = document.getElementById("none-versaeumt");
noneVersaeumtCB.onchange = function () {
for (scb of schuelerCBs) {
scb.disabled = this.checked;
if (this.checked) {
scb.checked = false;
scb.onchange();
}
}
};
// beim Laden der Seite einmal ausführen
noneVersaeumtCB.onchange();
{% if lehrer_can_access %}
var laengeSelect = document.getElementById("laenge-select");
var flagAsEditedCb = document.getElementById("flag-as-edited-cb");
flagAsEditedCb.onchange = function () {
laengeSelect.required = this.checked;
}
// beim Laden der Seite einmal ausführen
flagAsEditedCb.onchange();
{% endif %}
var editSubmit = document.getElementById("edit-submit");
editSubmit.onclick = function () {
if (!noneVersaeumtCB.checked) {
var ok = false;
for (scb of schuelerCBs) {
if (scb.checked) {
ok = true;
break;
}
}
if (!ok {% if lehrer_can_access %} && flagAsEditedCb.checked {% endif %}) {
alert("Bitte wählen Sie etwas aus.");
return false;
}
}
{% if not lehrer_can_access %}
return confirm("Wollen Sie wirklich speichern?\nSie können die Klausur danach nicht mehr bearbeiten.");
{% else %}
return true;
{% endif %}
};
var selectNode = document.getElementById("added-schueler");
var addNewKoopSchuelerFormNode = document.getElementById("add-new-schueler-form");
var nksNachnameInputNode = document.getElementById("new-schueler-nachname-input");
var nksVornameInputNode = document.getElementById("new-schueler-vorname-input");
selectNode.onchange = function() {
if (selectNode.value === "new-schueler") {
addNewKoopSchuelerFormNode.style.display = "";
nksNachnameInputNode.required = true;
nksVornameInputNode.required = true;
} else {
addNewKoopSchuelerFormNode.style.display = "none";
nksNachnameInputNode.required = false;
nksVornameInputNode.required = false;
}
};
// beim Laden der Seite einmal ausführen
selectNode.onchange();
{% endif %}
{% if lehrer_can_access %}
var new_startperiod_input = document.getElementById('new-startperiod-input');
var new_endperiod_input = document.getElementById('new-endperiod-input');
new_startperiod_input.onchange = function () {
new_endperiod_input.min = parseInt(new_startperiod_input.value);
}
// beim Laden der Seite einmal ausführen
new_startperiod_input.onchange();
{% endif %}
{% endblock %}
{% block content %}
{% if not is_bygone %}
<p class="warn">Diese Klausur hat noch nicht stattgefunden.</p>
{% endif %}
{% if klausur.edited %}
<p class="warn">Diese Klausur wurde bereits bearbeitet.</p>
{% endif %}
<p class="description">
{{ zeitraum(klausur) }} Stunde;
{{ Klausurteilnahme.query.filter_by(klausur_id=klausur.id).count() }} Schüler(innen)
</p>
<form method="post">
<input type="hidden" name="action" value="edit">
<p>
<label>
Länge der Klausur:
<select name="laenge" id="laenge-select" required {% if no_edit %} disabled {% endif %}>
<option value="" {% if klausur.laenge is none %} selected {% endif %}
{% if not lehrer_can_access %} disabled {% endif %}>Bitte auswählen</option>
{% for l in nateman_config['klausuren']['klausurlaengen'] %}
<option value="{{ l }}" {% if l == klausur.laenge %} selected {% endif %}>{{ l }} Minuten</option>
{% endfor %}
</select>
</label>
</p>
{% if not no_edit %}
<p>
Setzen Sie <i>entweder</i> ein Häkchen dafür, dass kein(e) Schüler(in) die Klausur versäumt hat<br>
<i>oder</i> setzen Sie ein Häkchen bei allen Schüler(inne)n, die die Klausur versäumt haben.<br>
Gehört ein(e) Schüler(in) <i>nicht</i> mehr zum Kurs, entfernen Sie diese(n) durch Anklicken von 'x'.<br>
Klicken Sie anschließend auf 'Speichern'.
</p>
{% endif %}
<p>
<label>
<input type="checkbox" id="none-versaeumt" {% if no_edit %} disabled {% endif %}
{%
if klausur.edited and Klausurteilnahme.query.filter_by(klausur=klausur).filter_by(versaeumt=True).count() == 0
%}
checked
{% endif %}>
<b>kein(e)</b> Schüler(in) hat versäumt
</label>
</p>
<p id="schueler-list">
{% for kt in kt_list %}
<label class="schueler-cb-container">
<input type="checkbox" name="s_{{ kt.schueler.id }}" id="s_{{ kt.schueler.id }}" class="schueler-cb"
{% if kt.versaeumt %} checked {% endif %} {% if no_edit %} disabled {% endif %}>
{{ kt.schueler.nachname }}, {{ kt.schueler.vorname }}
<span class="detail">
({% if kt.schueler.stammschule is not none %}{{ kt.schueler.stammschule.name }},
{% endif %}{{ kt.schueler.id }})
</span>
</label>
<input type="submit" form="remove-form" name="r_{{ kt.schueler.id }}" class="plain" value="&#xD7;"
title="entfernen" {% if no_edit %} disabled {% endif %}>
<br>
{% endfor %}
</p>
<p>
<label>
Bemerkung:
<input type="text" name="annotation" maxlength="{{ nateman_config['klausuren']['max-annotation-length'] }}"
value="{% if klausur.annotation %}{{ klausur.annotation }}{% endif %}" placeholder="optional"
{% if no_edit %} disabled {% endif %}>
</label>
</p>
{% if lehrer_can_access %}
<p>
<label>
<input type="checkbox" name="flag-as-edited" id="flag-as-edited-cb"
{% if is_bygone %} checked {% endif %}>
als bearbeitet markieren
</label>
</p>
{% endif %}
<p><input type="submit" id="edit-submit" value="Speichern" {% if no_edit %} disabled {% endif %}></p>
</form>
<form id="remove-form" method="post">
<input type="hidden" name="action" value="remove-schueler">
</form>
{% if not no_edit %}
<hr>
<form method="post">
<input type="hidden" name="action" value="add-schueler">
<p>
Fügen Sie eine(n) Schüler(in) hinzu, falls der/die Schüler(in) nicht bereits<br>
automatisch in der obigen Liste aufgeführt sein sollte.<br>
Nach dem Hinzufügen kann der/die Schüler(in) als versäumend markiert werden.
</p>
<h3>Schüler(in) hinzufügen:
<select name="added-schueler" id="added-schueler" required>
<option value="" selected disabled>Bitte auswählen</option>
<option value="new-schueler">Neue(n) Schüler(in) hinzufügen...</option>
{% for schueler in not_in_klausur_list %}
<option value="{{ schueler.id }}">{{ schueler.nachname }}, {{ schueler.vorname }}
({% if schueler.stammschule is not none %}{{ schueler.stammschule.name }}, {% endif %}{{ schueler.id }})
</option>
{% endfor %}
</select>
</h3>
<div id="add-new-schueler-form">
<p>
Bevor Sie eine(n) neue(n) Schüler(in) hinzufügen, überprüfen Sie bitte,
ob diese(r) nicht bereits in der obigen Auswahl vorhanden ist.<br>
<b>Tipp:</b> In den meisten Browsern können Sie bei geöffneter Auswahl
den Nachnamen eingeben, um nach einem/einer Schüler(in) zu suchen.
</p>
<div class="table-aligned">
<div>
<div><label for="new-schueler-nachname-input">Nachname:</label></div>
<div><input type="text" name="new-schueler-nachname" id="new-schueler-nachname-input"></div>
</div>
<div>
<div><label for="new-schueler-nachname-input">Vorname:</label></div>
<div><input type="text" name="new-schueler-vorname" id="new-schueler-vorname-input"></div>
</div>
<div>
<div><label for="new-schueler-stammschule-select">Stammschule:</label></div>
<div>
<select name="new-schueler-stammschule" id="new-schueler-stammschule-select">
<option value="" selected>(kein(e) Koop-Schüler(in))</option>
{% for ks in Koopschule.query.all() %}
<option value="{{ ks.kuerzel }}">{{ ks.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</div>
<fieldset>
<label><input type="radio" name="add-to" value="klausur">Hinzufügen zu dieser Klausur</label><br>
<label><input type="radio" name="add-to" value="kurs" checked>Hinzufügen zu allen Klausuren dieses Kurses</label>
</fieldset>
<p><input type="submit" value="Hinzufügen"></p>
</form>
{% if lehrer_can_access %}
<hr>
<h3>Erweiterte Einstellungen</h3>
<form method="post">
<input type="hidden" name="action" value="edit-advanced">
<div class="table-aligned">
<div>
<div><label for="new-lehrer-select">Kurslehrer(in):</label></div>
<div>
<select name="new-lehrer" id="new-lehrer-select">
{% for l in Lehrer.query.order_by(Lehrer.kuerzel).all() %}
<option value="{{ l.id }}" {% if l == klausur.lehrer %}selected{% endif %}>{{ l.kuerzel }}</option>
{% endfor %}
</select>
</div>
</div>
<div>
<div><label for="new-date-input">Klausurdatum:</label></div>
<div>
<input type="date" name="new-date" id="new-date-input"
value="{{ klausur.date.strftime('%Y-%m-%d') }}" required>
</div>
</div>
<div>
<div>Klausurzeitraum:</div>
<div>
<input type="number" name="new-startperiod" id="new-startperiod-input" class="small" min="0"
max="2147483647" value="{{ klausur.startperiod }}" required>{#
#}. bis
<input type="number" name="new-endperiod" id="new-endperiod-input" class="small" min="0" max="2147483647"
value="{{ klausur.endperiod }}" required>{#
#}. Stunde
</div>
</div>
</div>
<p><input type="submit" value="Speichern"></p>
</form>
<form method="post">
<input type="hidden" name="action" value="delete">
<p>
<input type="submit" value="Diese Klausur löschen"
onclick="return confirm('Soll diese Klausur wirklich gelöscht werden?')">
</p>
</form>
{% endif %}
{% endif %}
{% endblock %}
+91
View File
@@ -0,0 +1,91 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/klausuren/mine.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Meine Klausuren{% endblock %}
{% block header %}Meine Klausuren{% endblock %}
{# klausuren_anstehend #}
{# klausuren_vergangen #}
{% block content %}
<h3>vergangen:</h3>
{% if klausuren_vergangen|length == 0 %}
<p>keine</p>
{% else %}
<table>
<thead>
<tr>
<th>Datum</th>
<th>Stufe</th>
<th>Kurs</th>
<th>Zeitraum</th>
<th>bearbeitet</th>
</tr>
</thead>
<tbody>
{% for kv in klausuren_vergangen %}
<tr class="clickable" tabindex="0" data-href="{{ url_for('klausuren.edit', klausur_id=kv.id) }}">
<td>{{ kv.date_formatted() }}</td>
<td>{{ kv.stufe.name }}</td>
<td>{{ kv.kursname }}</td>
<td>{{ zeitraum(kv) }} Std.</td>
{% if kv.edited %}
<td class="positive-status">ja</td>
{% else %}
<td class="negative-status">nein</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<h3>anstehend:</h3>
{% if klausuren_anstehend|length == 0 %}
<p>keine</p>
{% else %}
<table>
<thead>
<tr>
<th>Datum</th>
<th>Stufe</th>
<th>Kurs</th>
<th>Zeitraum</th>
</tr>
</thead>
<tbody>
{% for ka in klausuren_anstehend %}
<tr class="clickable" tabindex="0" data-href="{{ url_for('klausuren.edit', klausur_id=ka.id) }}">
<td>{{ ka.date_formatted() }}</td>
<td>{{ ka.stufe.name }}</td>
<td>{{ ka.kursname }}</td>
<td>{{ zeitraum(ka) }} Std.</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}
+113
View File
@@ -0,0 +1,113 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/klausuren/stufe.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Klausuren {{ stufe.name }}{% endblock %}
{% block header %}Klausuren {{ stufe.name }}{% endblock %}
{# stufe #}
{# dates_anstehend #}
{# dates_vergangen #}
{% set lehrer_can_access = g.lehrer is not none and g.lehrer.can_access(stufe) %}
{% set klausur_count = dates_anstehend | length + dates_vergangen | length %}
{% set beratungslehrer_list = Lehrer.query.filter_by(beraet=stufe).all() %}
{% block content %}
<p class="description">
Beratungslehrer(innen):
{% if beratungslehrer_list|length == 0 %}
keine
{% else %}
{% for l in beratungslehrer_list %}
{{ l.kuerzel }}{% if l.email is not none %} &lt;<a href="mailto:{{ l.email }}">{{ l.email }}</a>&gt;{% endif %}<!--
-->{% if not loop.last %},{% endif %}
{% endfor %}
{% endif %}
</p>
{% if lehrer_can_access %}
<p><a href="{{ url_for('klausuren.add', stufe_name=stufe.name) }}" data-icon="&#xf0fe;">Klausur hinzufügen</a></p>
{% endif %}
{% if klausur_count != 0 %}
<p><a href="#heute" data-icon="&#xf103;">zu heute springen</a></p>
{% endif %}
{% if klausur_count == 0 %}
<p>keine</p>
{% else %}
{% for dates_list in (dates_anstehend, dates_vergangen) %}
{% if loop.index0 == 1 %}
<div id="heute" class="labeled-hr" data-icon="&#xf073;">heute ({{ util.format_date(datetime.now()) }})</div>
{% endif %}
{% for date in dates_list %}
{% set date_klausur_list = Klausur.query.filter_by(stufe=stufe, date=date).all() %}
{% set date_iso = date.strftime('%Y-%m-%d') %}
<h3>
<span>
{{ util.format_date(date) }}:
<a class="scroll-anchor" name="{{ date_iso }}" href="#{{ date_iso }}"></a>
</span>
</h3>
<table>
<thead>
<tr>
<th>Lehrer(in)</th>
<th>Kurs</th>
<th>Zeitraum</th>
{% if lehrer_can_access %}
<th>bearbeitet</th>
<th>Bemerkung</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for k in date_klausur_list %}
<tr {% if lehrer_can_access %} class="clickable" tabindex="0"
data-href="{{ url_for('klausuren.edit', klausur_id=k.id) }}" {% endif %}>
<td>{{ k.lehrer.kuerzel }}</td>
<td>{{ k.kursname }}</td>
<td>{{ zeitraum(k) }} Std.</td>
{% if lehrer_can_access %}
{% if k.edited %}
<td class="positive-status">ja</td>
{% else %}
<td class="negative-status">nein</td>
{% endif %}
{% if k.annotation is not none %}
<td class="description">{{ k.annotation }}</td>
{% else %}
<td class="detail">keine</td>
{% endif %}
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endfor %}
{% endif %}
{% endblock %}
@@ -0,0 +1,94 @@
{% extends 'base.html.j2' %}
{#
NateMan Nachschreibtermin-Manager
templates/schueler/versaeumnisse.html.j2
Copyright © 2020 Niklas Elsbrock
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Versäumnisse{% endblock %}
{% block header %}Versäumnisse{% endblock %}
{#
versaeumt_dict: Dictinonary mit jeweils eimem Tupel aus zwei Listen aller nicht nachgeschriebenen bzw.
nachgeschriebenen versäumten Klausurteilnahmen pro Stufe, auf die der angemeldete Lehrer Zugriff hat
#}
{% block content %}
<form method="post">
{% for stufe, versaeumt_listen in versaeumt_dict.items() %}
<h3>{{ stufe.name }}</h3>
{% for versaeumt_list in versaeumt_listen %}
<h4>
{% if loop.first %}
noch nicht nachgeschrieben:
{% else %}
bereits nachgeschrieben:
{% endif %}
</h4>
{% if versaeumt_list|length == 0 %}
<p>keine</p>
{% else %}
<table>
<thead>
<tr>
<th>Schüler(in)</th>
<th>Klausurdatum</th>
<th>Kurs</th>
<th>Lehrer</th>
<th>Länge</th>
<th>Bemerkung</th>
<th>attestiert</th>
<th>nachgeschrieben</th>
</tr>
</thead>
<tbody>
{% for kt in versaeumt_list %}
<tr class="clickable" tabindex="0" data-href="{{ url_for('klausuren.edit', klausur_id=kt.klausur.id) }}">
<td>{{ kt.schueler.nachname }}, {{ kt.schueler.vorname }}
<span class="detail">({% if kt.schueler.stammschule is not none %}{{ kt.schueler.stammschule.name }},
{% endif %}{{ kt.schueler.id }})</span>
</td>
<td>{{ kt.klausur.date_formatted() }}</td>
<td>{{ kt.klausur.kursname }}</td>
<td>{{ kt.klausur.lehrer.kuerzel }}</td>
<td>{{ kt.klausur.laenge }}</td>
{% if kt.klausur.annotation is not none %}
<td class="description">{{ kt.klausur.annotation }}</td>
{% else %}
<td class="detail">keine</td>
{% endif %}
<td><input type="checkbox" name="a_{{ kt.klausur.id }}:{{ kt.schueler.id }}"
onclick="event.stopPropagation()" {% if kt.attestiert %}checked{% endif %}></td>
<td><input type="checkbox" name="n_{{ kt.klausur.id }}:{{ kt.schueler.id }}"
onclick="event.stopPropagation()" {% if kt.nachgeschrieben %}checked{% endif %}></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endfor %}
<hr>
{% endfor %}
<p><input type="submit" value="Speichern"></p>
</form>
{% endblock %}