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

Merge branch 'dev' into dev-1.0.1

parents 41b2b4d3 487cd22b
No related branches found
No related tags found
1 merge request!86Merge school-apps
Showing
with 441 additions and 9 deletions
......@@ -10,6 +10,10 @@ class.tex
.idea/
media/
node_modules/
latex/
staticcollect/
.idea
dynselect2/src/*
dynselect2/bundle.js
package-lock.json
\ No newline at end of file
package-lock.json
schoolapps/latex/
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="NodePackageJsonFileManager">
<packageJsonPaths />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (school-apps)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
![](https://katharineum-zu-luebeck.de/wp-content/uploads/2017/05/Logo_aktuell_2-2.png)
# SchoolApps
![](https://user-images.githubusercontent.com/24552951/62492340-a02d9a80-b7ce-11e9-836d-f3846908641a.png)
## Apps
siehe Wiki
## Installation
......@@ -81,7 +80,6 @@ python3 schoolapps/manage.py runserver
1. Zu den [Einstellungen](localhost:8000/settings) navigieren (/settings)
2. Die richtigen E-Mailadressen eintragen
## LDAP (info.katharineum.de)
**WICHTIG:** LDAP funktioniert nur mit Nutzern, die folgende Gruppe haben: `info-admins`
......
......@@ -8,4 +8,5 @@ django-filter
django_react_templatetags
kanboard
PyPDF2
martor
\ No newline at end of file
martor
django_widget_tweaks
\ No newline at end of file
from django.contrib import admin
from .models import DebugLogGroup, DebugLog
class DebugLogAdmin(admin.ModelAdmin):
readonly_fields = ["id", "group", "return_code", "filename", "updated_at"]
class DebugLogGroupAdmin(admin.ModelAdmin):
readonly_fields = ["id"]
# Register your models here.
admin.site.register(DebugLogGroup, DebugLogGroupAdmin)
admin.site.register(DebugLog, DebugLogAdmin)
from django.apps import AppConfig
class DebugConfig(AppConfig):
name = 'debug'
# Generated by Django 2.2.1 on 2019-05-23 13:59
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='DebugLogGroup',
fields=[
('id', models.CharField(max_length=100, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200, verbose_name='Name')),
('desc_as_pre',
models.CharField(blank=True, max_length=250, verbose_name='Beschreibung, dargestellt als HTML-PRE')),
],
options={
'verbose_name': 'Debug-Log-Gruppe',
'verbose_name_plural': 'Debug-Log-Gruppen',
},
),
migrations.CreateModel(
name='DebugLog',
fields=[
('id', models.CharField(max_length=100, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200, verbose_name='Name')),
('return_code', models.IntegerField(blank=True, null=True, verbose_name='UNIX-Rückgabecode')),
('filename', models.FilePathField(match='.*.log', path='/home/wethjo/dev/school-apps/schoolapps/latex',
verbose_name='Dateiname zur Logdatei')),
('updated_at',
models.DateTimeField(default=django.utils.timezone.now, verbose_name='Aktualisierungszeitpunkt')),
('group',
models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL,
related_name='logs', to='debug.DebugLogGroup', verbose_name='Gruppe')),
],
options={
'verbose_name': 'Debug-Log',
'verbose_name_plural': 'Debug-Logs',
},
),
]
# Generated by Django 2.2.1 on 2019-05-23 14:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('debug', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='debuglog',
name='log_text',
field=models.TextField(blank=True, verbose_name='Log-Text (falls nicht Datei)'),
),
migrations.AlterField(
model_name='debuglog',
name='filename',
field=models.FilePathField(blank=True, match='.*.log', path='/home/wethjo/dev/school-apps/schoolapps/latex',
verbose_name='Dateiname zur Logdatei (falls nicht Log-Text)'),
),
]
import os
import traceback
from django.db import models
from django.utils import timezone
from schoolapps.settings import BASE_DIR
class DebugLogGroup(models.Model):
# Meta
id = models.CharField(primary_key=True, blank=False, max_length=100, verbose_name="ID")
name = models.CharField(blank=False, max_length=200, verbose_name="Name")
desc_as_pre = models.CharField(blank=True, max_length=250, verbose_name="Beschreibung, dargestellt als HTML-PRE")
class Meta:
verbose_name = "Debug-Log-Gruppe"
verbose_name_plural = "Debug-Log-Gruppen"
def __str__(self):
return self.name or self.id
def is_successful(self):
"""
:return: Were all operations in this group successful?
"""
successful = True
for log in self.logs.all():
if not log.is_successful():
successful = False
return successful
DEBUG_LOG_DIR = os.path.join(BASE_DIR, "latex")
class DebugLog(models.Model):
# Meta
id = models.CharField(primary_key=True, blank=False, max_length=100, verbose_name="ID")
name = models.CharField(blank=False, max_length=200, verbose_name="Name")
group = models.ForeignKey(DebugLogGroup, on_delete=models.SET_NULL, default=None, null=True, blank=True,
related_name="logs", verbose_name="Gruppe") # If null, it wouldn't be displayed
# Data
return_code = models.IntegerField(blank=True, null=True, verbose_name="UNIX-Rückgabecode")
filename = models.FilePathField(path=DEBUG_LOG_DIR, match=".*.log",
verbose_name="Dateiname zur Logdatei (falls nicht Log-Text)", blank=True)
log_text = models.TextField(verbose_name="Log-Text (falls nicht Datei)", blank=True)
updated_at = models.DateTimeField(blank=False, default=timezone.now, verbose_name="Aktualisierungszeitpunkt")
class Meta:
verbose_name = "Debug-Log"
verbose_name_plural = "Debug-Logs"
def __str__(self):
return self.name or self.id
def get_file_content(self):
"""
:return: The log text (file or DB)
"""
if self.filename:
print(self.filename)
f = open(os.path.join(DEBUG_LOG_DIR, self.filename), "r")
content = f.read()
f.close()
return content
elif self.log_text:
return self.log_text
else:
return ""
def is_successful(self):
"""
:return: Was the last operation successful?
"""
return self.return_code == 0
def get_log_group_by_id(id):
"""
Get a log group from DB by given id
:param id: ID of log group
:return:
"""
p, _ = DebugLogGroup.objects.get_or_create(id=id)
return p
def register_log_with_filename(id, group_id, filename, return_code):
"""
Register a operation in debugging tool with a log file
:param id: id of operation
:param group_id: id of group
:param filename: file path (based on latex dir)
:param return_code: UNIX return code
"""
p, _ = DebugLog.objects.get_or_create(id=id)
group = get_log_group_by_id(group_id)
p.group = group
p.return_code = return_code
p.filename = filename
p.updated_at = timezone.now()
p.save()
def register_return_0(id, group_id):
"""
Register a operation in debugging tool with an return code of 0 (success) and no log text/log file
:param id: id of operation
:param group_id: id of group
"""
p, _ = DebugLog.objects.get_or_create(id=id)
group = get_log_group_by_id(group_id)
p.group = group
p.return_code = 0
p.log_text = ""
p.updated_at = timezone.now()
p.save()
def register_traceback(id, group_id):
"""
Register a operation in debugging tool with an return code of 1 (error) and a log text
:param id: id of operation
:param group_id: id of group
"""
msg = traceback.format_exc()
p, _ = DebugLog.objects.get_or_create(id=id)
group = get_log_group_by_id(group_id)
p.group = group
p.return_code = 1
p.log_text = msg
p.updated_at = timezone.now()
p.save()
{% include 'partials/header.html' %}
{% load material_form %}
{% load martortags %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static "css/highlight.min.css" %}">
<script src="{% static "js/highlight.min.js" %}"></script>
<script>hljs.initHighlightingOnLoad();</script>
<style>
.debug-li {
line-height: 2;
}
.debug-icon {
font-size: 2.5rem;
}
</style>
<main>
<a class="btn-flat waves-effect waves-teal right btn-flat-medium" href="{% url "debug_logs" %}"><i
class="material-icons refresh center">refresh</i></a>
<h4>Debuggingtool</h4>
<h5>Schnellüberblick</h5>
<div class="row">
{% for group in groups %}
<div class="col s12 m4">
<div class="card">
<div class="card-content">
<i class="material-icons right {{ group.is_successful|yesno:"green,red" }}-text debug-icon">{{ group.is_successful|yesno:"check_circle,error" }}</i>
<span class="card-title">{{ group.name }}</span>
<ul>
{% for log in group.logs.all %}
<li class="debug-li">
<i class="material-icons right {{ log.is_successful|yesno:"green,red" }}-text">{{ log.is_successful|yesno:"check_circle,error" }}</i>
{{ log.name }}
</li>
{% endfor %}
</ul>
</div>
<div class="card-action">
<a href="#{{ group.id }}">
Log anzeigen
</a>
</div>
</div>
</div>
{% endfor %}
</div>
<h5>Logs</h5>
{% for group in groups %}
<div class="card" id="{{ group.id }}">
<div class="card-content">
<i class="material-icons right {{ group.is_successful|yesno:"green,red" }}-text medium">{{ group.is_successful|yesno:"check_circle,error" }}</i>
<span class="card-title">{{ group.name }}</span>
<pre>{{ group.desc_as_pre|default:" " }}</pre>
{% for log in group.logs.all %}
<div>
<i class="material-icons right {{ log.is_successful|yesno:"green,red" }}-text small">{{ log.is_successful|yesno:"check_circle,error" }}</i>
<h5>{{ log.name }} </h5>
<p><i class="material-icons left">access_time</i> {{ log.updated_at }}</p>
<pre><code class="plaintext scroll-fix">RETURN CODE: {{ log.return_code }}
{{ log.get_file_content }}
</code></pre>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</main>
{% include 'partials/footer.html' %}
from django.test import TestCase
# Create your tests here.
from django.urls import path
from . import views
urlpatterns = [
path("", views.debugging_tool),
path("logs/", views.debugging_tool, name="debug_logs")
]
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from debug.models import DebugLogGroup
@login_required
# @permission_required("timetable.")
def debugging_tool(request):
groups = DebugLogGroup.objects.all()
return render(request, "debug/debug.html", {"groups": groups})
from django.contrib import admin
from faq.models import Question, FAQQuestion
from faq.models import Question, FAQQuestion, FAQSection
from django.utils.html import format_html
# Register your models here.
def show(modeladmin, request, queryset):
queryset.update(show=True)
show.short_description = "Ausgewählte Fragen veröffentlichen"
def hide(modeladmin, request, queryset):
queryset.update(show=False)
hide.short_description = "Ausgewählte Fragen nicht mehr veröffentlichen"
class QuestionAdmin(admin.ModelAdmin):
list_display = ("question_text", "pub_date", "user", "answered")
list_filter = ("answered",)
admin.site.register(Question, QuestionAdmin)
class FAQSectionAdmin(admin.ModelAdmin):
list_display = ("name", "_icon")
class Media:
css = {
'all': ('/static/css/materialdesignicons-webfont/material-icons.css',)
}
def _icon(self, obj):
return format_html(u'<i style="color: {};" class="material-icons">{}<i/>', obj.icon_color, obj.icon)
class FAQQuestionAdmin(admin.ModelAdmin):
list_display = ("question_text", "icon", "show")
list_display = ("question_text", "section", "_icon", "show")
actions = [show, hide]
admin.site.register(FAQQuestion, FAQQuestionAdmin)
\ No newline at end of file
class Media:
css = {
'all': ('/static/css/materialdesignicons-webfont/material-icons.css',)
}
def _icon(self, obj):
return format_html(u'<i class="material-icons">{}<i/>', obj.icon)
admin.site.register(FAQQuestion, FAQQuestionAdmin)
admin.site.register(FAQSection, FAQSectionAdmin)
......@@ -3,3 +3,4 @@ from django.apps import AppConfig
class FaqConfig(AppConfig):
name = 'faq'
verbose_name = "FAQ"
......@@ -2,4 +2,4 @@ from django import forms
class FAQForm(forms.Form):
question = forms.CharField(widget=forms.Textarea(),
label='Bitte geben sie ihre Frage hier ein…', required=True)
\ No newline at end of file
label='Deine Frage', required=True)
# Generated by Django 2.2.3 on 2019-07-22 11:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('faq', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='FAQSection',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('icon', models.CharField(blank=True, default='question_answer', max_length=20)),
],
),
migrations.AlterField(
model_name='faqquestion',
name='answer_text',
field=models.TextField(blank=True, help_text='Bei den Antworten funktioniert auch HTML-Syntax!<br> Aus Gründen des verwendeten CSS-Frameworks muss der Tag <strong>&lt;ul&gt;</strong> die CSS-Klasse <em>browser-default</em> besitzen!'),
),
migrations.AddField(
model_name='faqquestion',
name='section',
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to='faq.FAQSection'),
preserve_default=False,
),
]
# Generated by Django 2.2.3 on 2019-07-22 12:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('faq', '0002_auto_20190722_1336'),
]
operations = [
migrations.AlterModelOptions(
name='faqsection',
options={'verbose_name': 'FAQ-Abschnitt', 'verbose_name_plural': 'FAQ-Abschnitte'},
),
migrations.AddField(
model_name='faqsection',
name='icon_color',
field=models.CharField(choices=[('red', 'red'), ('pink', 'pink'), ('purple', 'purple'), ('deep-purple', 'deep-purple'), ('indigo', 'indigo'), ('blue', 'blue'), ('light-blue', 'light-blue'), ('cyan', 'cyan'), ('teal', 'teal'), ('green', 'green'), ('light-green', 'light-green'), ('lime', 'lime'), ('yellow', 'yellow'), ('amber', 'amber'), ('orange', 'orange'), ('deep-orange', 'deep-orange'), ('brown', 'brown'), ('grey', 'grey'), ('blue-grey', 'blue-grey'), ('black', 'black'), ('white', 'white'), ('transparent', 'transparent')], default='black', max_length=10),
),
]
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