Skip to content
Snippets Groups Projects
Commit 3d456744 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Merge

parents fee41082 cd08aa41
No related branches found
No related tags found
1 merge request!86Merge school-apps
Showing
with 562 additions and 53 deletions
......@@ -9,4 +9,6 @@ class.pdf
class.tex
.idea/
media/
node_modules/
\ No newline at end of file
node_modules/
latex/
staticcollect/
<?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
# Generated by Django 2.1.5 on 2019-04-10 12:16
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('aub', '0011_merge_20190318_2004'),
]
operations = [
migrations.AlterField(
model_name='aub',
name='created_by',
field=models.ForeignKey(default=3, on_delete=models.SET(3), related_name='aubs',
to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='aub',
name='status',
field=models.ForeignKey(default=5, on_delete=models.SET(5), related_name='aubs', to='aub.Status'),
),
]
# Generated by Django 2.2 on 2019-04-11 10:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('aub', '0012_auto_20190410_1416'),
]
operations = [
migrations.AlterField(
model_name='aub',
name='status',
field=models.ForeignKey(default=1, on_delete=models.SET(1), related_name='aubs', to='aub.Status'),
),
]
# Generated by Django 2.2.1 on 2019-05-02 15:08
import datetime
from django.conf import settings
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('aub', '0013_auto_20190411_1203'),
]
operations = [
migrations.AlterModelOptions(
name='aub',
options={'permissions': (
('apply_for_aub', 'Apply for a AUB'), ('cancel_aub', 'Cancel a AUB'),
('allow1_aub', 'First permission'),
('allow2_aub', 'Second permission'), ('check1_aub', 'Check a AUB'), ('check2_aub', 'Check a AUB'),
('view_archive', 'View AUB archive')), 'verbose_name': 'AUB', 'verbose_name_plural': 'AUBs'},
),
migrations.AlterField(
model_name='aub',
name='created_at',
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Erstellungszeitpunkt'),
),
migrations.AlterField(
model_name='aub',
name='created_by',
field=models.ForeignKey(default=3, on_delete=models.SET(3), related_name='aubs',
to=settings.AUTH_USER_MODEL, verbose_name='Erstellt von'),
),
migrations.AlterField(
model_name='aub',
name='from_date',
field=models.DateField(default=datetime.date.today, verbose_name='Startdatum'),
),
migrations.AlterField(
model_name='aub',
name='from_time',
field=models.TimeField(default=django.utils.timezone.now, verbose_name='Startzeit'),
),
migrations.AlterField(
model_name='aub',
name='status',
field=models.IntegerField(
choices=[(0, 'In Bearbeitung 1'), (1, 'In Bearbeitung 2'), (2, 'Genehmigt'), (3, 'Abgelehnt')],
default=0, verbose_name='Status'),
),
migrations.AlterField(
model_name='aub',
name='to_date',
field=models.DateField(default=datetime.date.today, verbose_name='Enddatum'),
),
migrations.AlterField(
model_name='aub',
name='to_time',
field=models.TimeField(default=django.utils.timezone.now, verbose_name='Endzeit'),
),
migrations.DeleteModel(
name='Status',
),
]
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})
......@@ -41,6 +41,7 @@ ALLOWED_HOSTS = [
INSTALLED_APPS = [
'django_pdb',
'dashboard.apps.DashboardConfig',
"debug.apps.DebugConfig",
'aub.apps.AubConfig',
'untisconnect.apps.UntisconnectConfig',
'timetable.apps.TimetableConfig',
......@@ -56,6 +57,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
'material',
'django_react_templatetags',
'martor',
'widget_tweaks',
]
......@@ -150,6 +152,7 @@ USE_TZ = True
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "staticcollect")
# Redirect to home URL after login (Default redirects to /accounts/profile/)
LOGIN_REDIRECT_URL = '/'
......@@ -232,3 +235,5 @@ logger.setLevel(logging.DEBUG)
# Media
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
DBSETTINGS_USE_CACHE = False
......@@ -62,6 +62,7 @@ urlpatterns = [
#########
# Admin #
#########
path("debug/", include("debug.urls")),
path('settings/', include('dbsettings.urls')),
path('admin/', admin.site.urls),
......@@ -75,7 +76,9 @@ urlpatterns = [
#######
path('faq/', include('faq.urls')),
path("pwabuilder-sw.js", serviceworker)
path("pwabuilder-sw.js", serviceworker),
path('martor/', include('martor.urls')),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
......
......@@ -102,9 +102,16 @@ $(document).ready(function () {
window.print();
});
//Initialize Collapsible [MAT]
// Initialize Collapsible [MAT]
$('.collapsible').collapsible();
//Initialize FABs [MAT]
// Initialize FABs [MAT]
$('.fixed-action-btn').floatingActionButton();
// Initialize delete button
$(".delete-button").click(function (e) {
if (!confirm("Wirklich löschen?")) {
e.preventDefault();
}
})
});
\ No newline at end of file
......@@ -12,7 +12,7 @@ body {
background-color: #da1f3d !important;
}
.primary-color-text {
.primary-color-text, .primary-color-text a {
color: #da1f3d !important;
}
......@@ -103,22 +103,14 @@ span.badge.new {
height: 26px;
}
span.badge.no-float {
span.badge.new.no-float {
float: none;
padding: 3px 6px;
}
/*span.badge {*/
/*width: 9em;*/
/*line-height: 4ex;*/
/*height: 4ex;*/
/*}*/
/*span.badge::after {*/
/*content: "";*/
/*}*/
/*span.item-text {*/
/*line-height: 4ex;*/
/*vertical-align: bottom;*/
/*}*/
span.badge .material-icons {
font-size: 0.9rem;
}
/*+++++++++++*/
/* Timetable */
......@@ -166,23 +158,23 @@ span.badge.no-float {
width: 100%;
}
.timetable-mobile-title-card{
.timetable-mobile-title-card {
margin-top: 50px;
margin-bottom: .60rem;
}
.timetable-mobile-title-card:first-child{
.timetable-mobile-title-card:first-child {
margin-top: -10px;
margin-bottom: .60rem;
}
.timetable-mobile-title-card .card-content{
.timetable-mobile-title-card .card-content {
padding: 10px;
text-align: center;
width: 100%;
}
.timetable-mobile-title-card .card-content .card-title{
.timetable-mobile-title-card .card-content .card-title {
font-weight: bold;
}
......@@ -199,7 +191,7 @@ table.substitutions td, table.substitutions th {
margin: 0;
}
.lesson-card a {
.lesson-card a, .substitutions a {
color: black;
}
......@@ -235,7 +227,11 @@ table.substitutions td, table.substitutions th {
}
.no-margin {
margin: 0;
margin: 0 !important;
margin-left: 0 !important;
margin-right: 0 !important;
margin-top: 0 !important;
margin-bottom: 0 !important;
}
/* Table*/
......@@ -306,26 +302,36 @@ table.striped > tbody > tr:nth-child(odd) {
}
}
.alert p {
.alert ul, .alert p {
margin: 0;
}
.alert p:first-child, .alert div:first-child {
margin: 10px;
padding: 10px;
border-left: 5px solid;
}
.alert.success p {
.alert.success p, .alert.success div {
background-color: #c5e1a5;
border-color: #4caf50;
}
.alert.error p {
.alert.error p, .alert.error div {
background-color: #ef9a9a;
border-color: #b71c1c;
}
main .alert p {
.alert.primary p, .alert.primary div {
background-color: #eca4af;
border-color: #da1f3d;
}
main .alert p:first-child, main .alert div:first-child {
margin-left: -10px;
margin-right: -10px;
}
.btn, .btn-large, .btn-small {
background-color: #282E3F;
}
......@@ -349,52 +355,92 @@ FEEDBACK
}
@media only screen and (max-width: 992px) {
.rating{
.rating {
margin-top: 12px;
min-height: 40px;
justify-content: space-around;
}
´
}
.rating label {
display: flex;
flex: 1;
position: relative;
cursor: pointer;
display: flex;
flex: 1;
position: relative;
cursor: pointer;
}
.rating label:after {
font-family: 'Material Icons';
-webkit-font-feature-settings: 'liga';
position: absolute;
color: #777;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
font-size: 40px;
content: 'star_border';
font-family: 'Material Icons';
-webkit-font-feature-settings: 'liga';
position: absolute;
color: #777;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
font-size: 40px;
content: 'star_border';
}
.rating input {
display: none!important;
display: none !important;
}
.rating > input:checked + label:after,
.rating > input:checked ~ label:after {
content: "star";
color: #FFD700;
content: "star";
color: #FFD700;
}
.rating > input:hover + label:after,
.rating > input:hover ~ label:after {
content: "star";
color: #FFD700;
content: "star";
color: #FFD700;
}
.support-input-mobile label {
line-height: 1rem;
line-height: 1rem;
}
.span-info {
width: 24px;
vertical-align: middle;
}
i.collapsible-trigger {
margin-right: -10px;
}
.collapsible .collapsible-trigger::before {
content: 'arrow_downward';
}
.collapsible .collapsible-trigger.v2::before {
content: 'more_vert';
}
.collapsible .active .collapsible-trigger::before {
content: 'arrow_upward';
}
.scroll-fix {
max-height: 300px;
overflow: scroll;
}
.waves-effect.waves-katharineum .waves-ripple {
background-color: rgba(218, 31, 61, 0.65);
}
.span-info{
width: 24px;
vertical-align: middle;
.card .card-action a:not(.btn):not(.btn-large):not(.btn-small):not(.btn-large):not(.btn-floating) {
color: #da1f3d;
}
.card .card-action a:not(.btn):not(.btn-large):not(.btn-small):not(.btn-large):not(.btn-floating):hover {
color: #ea4661;
}
\ No newline at end of file
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