intern implementation

This commit is contained in:
2021-02-28 00:29:26 +00:00
committed by Patrick Mayr
parent 59191a0909
commit 7da778189d
15 changed files with 543 additions and 1 deletions

View File

@@ -85,6 +85,7 @@ INSTALLED_APPS = [
"blackboard.apps.BlackboardConfig",
"tasks.apps.TasksConfig",
"gallery.apps.GalleryConfig",
"intern.apps.InternConfig",
]
MIDDLEWARE = [

View File

@@ -42,6 +42,7 @@ urlpatterns = [
path("member/", include(member_urlpatterns), name="member"),
path("posts/", include("posts.urls")),
path("tasks/", include("tasks.urls"), name="tasks"),
path("intern/", include("intern.urls"), name="intern"),
path(
"discord/",
RedirectView.as_view(url="https://discord.com/invite/7qRuuMA"),

View File

57
fet2020/intern/admin.py Normal file
View File

@@ -0,0 +1,57 @@
from django.contrib import admin
from .models import TopicGroup, Topic, Documentation
from .forms import TopicGroupAdminForm, TopicAdminForm
class DocumentationInline(admin.TabularInline):
model = Documentation
extra = 0
verbose_name = "Dokument"
verbose_name_plural = "Dokument-Übersicht"
class TopicInline(admin.TabularInline):
model = Topic
extra = 0
verbose_name = "Topic"
verbose_name_plural = "Topic-Übersicht"
class TopicGroupAdmin(admin.ModelAdmin):
form = TopicGroupAdminForm
model = TopicGroup
search_fields = ("title",)
inlines = (TopicInline,)
def save_model(self, request, obj, form, change):
obj.created_by = request.user
super().save_model(request, obj, form, change)
class TopicAdmin(admin.ModelAdmin):
form = TopicAdminForm
model = Topic
search_fields = ("title",)
inlines = (DocumentationInline,)
def save_model(self, request, obj, form, change):
obj.created_by = request.user
super().save_model(request, obj, form, change)
"""
class DocumentationAdmin(admin.ModelAdmin):
form = DocumentationAdminForm
model = Documentation
list_display = ["title", "topic"]
def save_model(self, request, obj, form, change):
obj.created_by = request.user
super().save_model(request, obj, form, change)
"""
admin.site.register(TopicGroup, TopicGroupAdmin)
admin.site.register(Topic, TopicAdmin)
# admin.site.register(Documentation, DocumentationAdmin)

5
fet2020/intern/apps.py Normal file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class InternConfig(AppConfig):
name = "intern"

49
fet2020/intern/forms.py Normal file
View File

@@ -0,0 +1,49 @@
from django import forms
from django.utils.translation import gettext_lazy as _
from ckeditor_uploader.widgets import CKEditorUploadingWidget
from .models import TopicGroup, Topic, Documentation, Document
class TopicGroupAdminForm(forms.ModelForm):
class Meta:
model = TopicGroup
fields = [
"title",
]
class TopicAdminForm(forms.ModelForm):
class Meta:
model = Topic
fields = [
"title",
"description",
"topic_group",
]
widgets = {"description": CKEditorUploadingWidget(config_name="default")}
class DocumentationAdminForm(forms.ModelForm):
class Meta:
model = Documentation
fields = [
"title",
"description",
"topic",
]
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = [
"title",
]
labels = {
"title": _("Titel des Protokolls"),
}

101
fet2020/intern/models.py Normal file
View File

@@ -0,0 +1,101 @@
import logging
from django.db import models
from django.utils.text import slugify
from documents import createPadifNotExists
from urllib.request import URLError
logger = logging.getLogger(__name__)
class TopicGroup(models.Model):
title = models.CharField(max_length=128)
slug = models.SlugField(unique=True, blank=True)
objects = models.Manager()
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def __str__(self):
return self.title
class Topic(models.Model):
title = models.CharField(max_length=128)
slug = models.SlugField(unique=True, blank=True)
description = models.TextField(null=True, blank=True)
topic_group = models.ForeignKey(TopicGroup, on_delete=models.CASCADE)
objects = models.Manager()
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def __str__(self):
return self.title
class Documentation(models.Model):
title = models.CharField(max_length=128)
slug = models.SlugField(unique=True, blank=True)
description = models.TextField(null=True, blank=True)
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
objects = models.Manager()
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def __str__(self):
return self.title
class Document(models.Model):
title = models.CharField(max_length=128)
etherpad_key = models.CharField(max_length=128, null=True, blank=True)
documentation = models.ForeignKey(Documentation, on_delete=models.CASCADE)
objects = models.Manager()
def save(self, *args, **kwargs):
try:
self.etherpad_key = createPadifNotExists(
self.documentation.topic.slug
+ "-"
+ self.documentation.slug
+ "-"
+ slugify(self.title)
)
except URLError as error:
logger.info(
"Can't create a Etherpad '%s' from the slug. Error: %s",
slugify(self.title),
error,
)
self.etherpad_key = None
super().save(*args, **kwargs)
def __str__(self):
return self.title
class Protocol(Document):
event_start = models.DateTimeField(null=True, blank=True)
event_end = models.DateTimeField(null=True, blank=True)

3
fet2020/intern/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

10
fet2020/intern/urls.py Normal file
View File

@@ -0,0 +1,10 @@
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="intern"),
path("<str:slug>", views.show_topic, name="topic"),
path("<str:slug>/<str:foo>", views.show_docu, name="docu"),
]

85
fet2020/intern/views.py Normal file
View File

@@ -0,0 +1,85 @@
import logging
from django.http import HttpResponseRedirect
from django.shortcuts import render
from documents.api import get_pad_link
from collections import deque
from .forms import DocumentForm
from .models import TopicGroup, Topic, Documentation, Document
logger = logging.getLogger(__name__)
def index(request):
topic_group = deque(TopicGroup.objects.all())
topic = Topic.objects.all()
context = {
"topic_group": topic_group,
"topic": topic,
}
return render(request, "intern/index.html", context)
def show_topic(request, slug=None):
topic_group = deque(TopicGroup.objects.all())
topic = deque(Topic.objects.all())
active_topic = Topic.objects.filter(slug=slug).first()
docu = deque(Documentation.objects.filter(topic__slug=slug))
context = {
"topic_group": topic_group,
"topic": topic,
"active_topic": active_topic,
"docus": docu,
}
return render(request, "intern/topic.html", context)
def show_docu(request, slug=None, foo=None):
active_docu = Documentation.objects.filter(slug=foo).first()
active_topic = Topic.objects.filter(slug=slug).first()
if request.method == "POST":
if "btn_input" in request.POST:
form = DocumentForm(request.POST)
if form.is_valid():
docu = form.save(commit=False)
docu.created_by = request.user
docu.documentation = active_docu
docu.save()
return HttpResponseRedirect(request.path)
form = DocumentForm()
docus = deque(Document.objects.filter(documentation=active_docu))
documents = deque([])
for elem in docus:
try:
documents.append(
{
"title": elem.title,
"etherpad_key": get_pad_link(elem.etherpad_key),
}
)
except Exception as e:
logger.error(
"Can't get the agenda link from '%s'. Error: %s", elem.etherpad_key, e
)
context = {
"formset": form,
"active_topic": active_topic,
"active_docu": active_docu,
"documents": documents,
}
return render(request, "intern/docu.html", context)

75
fet2020/static/intern.css Normal file
View File

@@ -0,0 +1,75 @@
.intern-topic {
border-radius: 5px;
margin-top: 1rem !important;
margin-bottom: 1rem !important;
height: 100px; }
@media print, screen and (min-width: 40em) {
.intern-topic {
height: 15vh; } }
@media print, screen and (min-width: 64em) {
.intern-topic {
height: 15vh; } }
.intern-topic, .intern-topic-large {
background-color: #444;
position: relative;
background-size: cover;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
vertical-align: middle;
text-align: left;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
width: 100%; }
.intern-topic .intern-topic-text, .intern-topic-large .intern-topic-text {
color: #fefefe;
text-shadow: 1px 1px 2px #0a0a0a; }
.internheader {
border-radius: 5px;
margin-top: 1rem !important;
margin-bottom: 1rem !important;
height: 30px; }
@media print, screen and (min-width: 40em) {
.internheader {
height: 5vh; } }
@media print, screen and (min-width: 64em) {
.internheader {
height: 5vh; } }
.internheader, .internheader-large {
background-color: grey;
position: relative;
background-size: cover;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
vertical-align: middle;
text-align: left;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
width: 100%; }
.internheader, .internheader-large {
color: #fefefe;
text-shadow: 1px 1px 2px #0a0a0a; }
.intern-hero {
background-color: white;
}

View File

@@ -0,0 +1,75 @@
{% extends "layout.html" %}
{% block content %}
<div class="grid-container">
<div class="grid-x grid-padding-x padding-top-1">
<div class="cell large-2 medium-4 small-6">
<a href="{% url 'intern' %}">
<div class="internheader">
{{ active_topic.topic_group.title }}
</div>
</a>
</div>
<div class="cell large-2 medium-4 small-6">
<a href="{% url 'topic' active_topic.slug %}">
<div class="internheader">
{{ active_topic.title }}
</div>
</a>
</div>
<div class="cell large-2 medium-4 small-6">
<a href="{% url 'docu' active_topic.slug active_docu.slug %}">
<div class="internheader">
{{ active_docu.title }}
</div>
</a>
</div>
</div>
<div class="intern-hero">
{{ active_docu.description|safe }}
<div class="grid-x grid-padding-x">
<ul>
{% for document in documents %}
<li><a href="{{ document.etherpad_key }}">{{ document.title }}</a></li>
{% endfor %}
</ul>
</div>
<hr>
<h2>Neues Protokoll hinzufügen</h2>
<form action="" method="post">
{% csrf_token %}
<div class="grid-x grid-margin-x">
{{ formset.management_form }}
{% for form in formset %}
<div class="cell medium-3 large-2 small-10">
{{ form.label }}
{{ form }}
</div>
{% endfor %}
<div class="cell medium-3 large-2 small-10 align-self-bottom">
<input type="submit" class="button" name="btn_input" value="Hinzufügen">
</div>
</div>
</form>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,29 @@
{% extends "layout.html" %}
{% block content %}
<div class="grid-container">
{% regroup topic by topic_group as topic_list %}
{% for topic in topic_list %}
<div class="internheader">
{{ topic.grouper.title }}
</div>
<div class="grid-x grid-padding-x">
{% for tp in topic.list %}
<div class="cell large-2 medium-4 small-6">
<a href="{% url 'topic' tp.slug %}">
<div class="intern-topic">
<div class="intern-topic-text">
{{ tp.title }}
</div>
</div>
</a>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endblock %}

View File

@@ -0,0 +1,49 @@
{% extends "layout.html" %}
{% block content %}
<div class="grid-container">
<div class="grid-x grid-padding-x padding-top-1">
<div class="cell large-2 medium-4 small-6">
<a href="{% url 'intern' %}">
<div class="internheader">
{{ active_topic.topic_group.title }}
</div>
</a>
</div>
<div class="cell large-2 medium-4 small-6">
<a href="{% url 'topic' active_topic.slug %}">
<div class="internheader">
{{ active_topic.title }}
</div>
</a>
</div>
</div>
<div class="intern-hero">
{{ active_topic.description|safe }}
<div class="grid-x grid-padding-x padding-top-1">
{% for docu in docus %}
<div class="cell large-2 medium-4 small-6">
<a href="{% url 'docu' active_topic.slug docu.slug %}">
<div class="intern-topic">
<div class="intern-topic-text">
{{ docu.title }}
</div>
</div>
</a>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}

View File

@@ -11,6 +11,7 @@
<link rel="shortcut icon" type="image/png" href="{% static 'img/fet_logo_white.png' %}"/>
<link rel="stylesheet" href="{% static 'app.css' %}">
<link rel="stylesheet" href="{% static 'fet.css' %}">
<link rel="stylesheet" href="{% static 'intern.css' %}">
<link href="{% static 'fontawesomefree/css/all.min.css' %}" rel="stylesheet" type="text/css">
{% block galleryheader %}
{% endblock %}
@@ -55,7 +56,8 @@
</li>
<li><a class="button header-intern-btn header-intern-link" href="{% url 'admin:index' %}">Admin</a></li>
<li><a class="button header-intern-btn header-intern-link" href="{% url 'tasks' %}">Tasks</a></li>
<li><a class="button header-intern-btn header-intern-link" href="https://legacy.fet.at/home/intern">Intern</a></li>
<li><a class="button header-intern-btn header-intern-link" href="{% url 'intern' %}">Intern</a></li>
<li><a class="button header-intern-btn header-intern-link" href="https://legacy.fet.at/home/intern">Legacy</a></li>
{% endif %}
<li><a class="button header-btn header-link" href="{% url 'posts:posts.index' %}">News</a></li>
<!-- show active members first -->