diff --git a/jdav_web/jdav_web/settings/components/base.py b/jdav_web/jdav_web/settings/components/base.py index f004e1d..bbb8945 100644 --- a/jdav_web/jdav_web/settings/components/base.py +++ b/jdav_web/jdav_web/settings/components/base.py @@ -46,6 +46,8 @@ INSTALLED_APPS = [ 'finance.apps.FinanceConfig', 'ludwigsburgalpin.apps.LudwigsburgalpinConfig', #'easy_select2', + 'markdownify.apps.MarkdownifyConfig', + 'markdownx', 'djcelery_email', 'nested_admin', 'django_celery_beat', @@ -146,3 +148,43 @@ PASSWORD_HASHERS = [ 'django.contrib.auth.hashers.Argon2PasswordHasher', 'django.contrib.auth.hashers.ScryptPasswordHasher', ] + +MARKDOWNIFY = { + 'default': { + "WHITELIST_TAGS": [ + 'img', + 'abbr', + 'acronym', + 'a', + 'b', + 'blockquote', + 'em', + 'i', + 'li', + 'ol', + 'p', + 'strong', + 'ul', + 'br', + 'code', + 'span', + 'div', 'class', + 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + ], + "WHITELIST_ATTRS": [ + 'src', + 'href', + 'style', + 'alt', + 'class', + ], + "LINKIFY_TEXT": { + "PARSE_URLS": True, + + # Next key/value-pairs only have effect if "PARSE_URLS" is True + "PARSE_EMAIL": True, + "CALLBACKS": [], + "SKIP_TAGS": [], + } + } +} diff --git a/jdav_web/jdav_web/urls.py b/jdav_web/jdav_web/urls.py index 581d4fc..53fdae7 100644 --- a/jdav_web/jdav_web/urls.py +++ b/jdav_web/jdav_web/urls.py @@ -34,10 +34,17 @@ urlpatterns += i18n_patterns( re_path(r'^members/', include('members.urls', namespace="members")), re_path(r'^LBAlpin/Programm(/)?(20)?[0-9]{0,2}', include('ludwigsburgalpin.urls', namespace="ludwigsburgalpin")), - re_path(r'^$', include('startpage.urls', namespace="startpage")), re_path(r'^_nested_admin/', include('nested_admin.urls')), + re_path(r'^', include('startpage.urls', namespace="startpage")), ) +urlpatterns += [ + re_path(r'^markdownx/', include('markdownx.urls')), +] + +handler404 = 'startpage.views.handler404' +handler500 = 'startpage.views.handler500' + # TODO: django serving from MEDIA_URL should be disabled in production stage # see # http://stackoverflow.com/questions/5871730/need-a-minimal-django-file-upload-example diff --git a/jdav_web/members/admin.py b/jdav_web/members/admin.py index 755e279..879600c 100644 --- a/jdav_web/members/admin.py +++ b/jdav_web/members/admin.py @@ -159,6 +159,7 @@ class MemberAdmin(CommonAdminMixin, admin.ModelAdmin): 'medication', 'tetanus_vaccination', 'photos_may_be_taken', 'legal_guardians', ('good_conduct_certificate_presented_date', 'good_conduct_certificate_presentation_needed'), 'iban', 'has_key', 'has_free_ticket_gym', 'gets_newsletter', 'registered', 'registration_form', + 'image', 'active', 'echoed', ('join_date', 'leave_date'), 'comments', 'technical_comments', @@ -456,7 +457,7 @@ class GroupAdminForm(forms.ModelForm): class GroupAdmin(CommonAdminMixin, admin.ModelAdmin): - fields = ['name', 'year_from', 'year_to', 'leiters'] + fields = ['name', 'description', 'year_from', 'year_to', 'leiters', 'show_website'] form = GroupAdminForm list_display = ('name', 'year_from', 'year_to') inlines = [RegistrationPasswordInline, PermissionOnGroupInline] diff --git a/jdav_web/members/migrations/0012_member_image_group_description.py b/jdav_web/members/migrations/0012_member_image_group_description.py new file mode 100644 index 0000000..91130af --- /dev/null +++ b/jdav_web/members/migrations/0012_member_image_group_description.py @@ -0,0 +1,29 @@ +# Generated by Django 4.0.1 on 2023-04-09 11:46 + +from django.db import migrations, models +import utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0011_alter_freizeit_date_alter_freizeit_end'), + ] + + operations = [ + migrations.AddField( + model_name='group', + name='description', + field=models.TextField(blank=True, default='', verbose_name='description'), + ), + migrations.AddField( + model_name='group', + name='show_website', + field=models.BooleanField(default=False, verbose_name='show on website'), + ), + migrations.AddField( + model_name='member', + name='image', + field=utils.RestrictedFileField(blank=True, upload_to='people', verbose_name='image'), + ), + ] diff --git a/jdav_web/members/models.py b/jdav_web/members/models.py index aad93fe..a59bd80 100644 --- a/jdav_web/members/models.py +++ b/jdav_web/members/models.py @@ -55,6 +55,8 @@ class Group(models.Model): e.g: J1, J2, Jugendleiter, etc. """ name = models.CharField(max_length=50, verbose_name=_('name')) # e.g: J1 + description = models.TextField(verbose_name=_('description'), default='', blank=True) + show_website = models.BooleanField(verbose_name=_('show on website'), default=False) year_from = models.IntegerField(verbose_name=_('lowest year'), default=2010) year_to = models.IntegerField(verbose_name=_('highest year'), default=2011) leiters = models.ManyToManyField('members.Member', verbose_name=_('youth leaders'), @@ -214,6 +216,13 @@ class Member(Person): 'image/jpeg', 'image/png', 'image/gif']) + image = RestrictedFileField(verbose_name=_('image'), + upload_to='people', + blank=True, + max_upload_size=5242880, + content_types=['image/jpeg', + 'image/png', + 'image/gif']) echo_key = models.CharField(max_length=32, default="") echo_expire = models.DateTimeField(default=timezone.now) echoed = models.BooleanField(default=True, verbose_name=_('Echoed')) diff --git a/jdav_web/members/templates/members/register_waiting_list.html b/jdav_web/members/templates/members/register_waiting_list.html index a178316..a9668e6 100644 --- a/jdav_web/members/templates/members/register_waiting_list.html +++ b/jdav_web/members/templates/members/register_waiting_list.html @@ -10,9 +10,17 @@ -

{% trans "Register for waiting list" %}

+

Anmeldung

-

{% trans "Here you can register for the waiting list." %}

+

+Da wir durch das Engagment unserer ehrenamtlichen Jugendleitern, aber auch die Kletterhalle sowie Ausrüstung limitiert sind können wir nur eine begrenzte Anzahl an Plätzen in den Gruppen anbieten. Damit alle eine faire Changce auf einen Gruppenplatz bekommen, führen wir für die jüngeren Klettergruppen eine gemeinsame Liste. Soblad Plätze frei werden oder eine neue Gruppe gegründet wird seid ihr an der Reihe! Dennoch kann die Wartezeit leider zwischen wenigen Wochen und über einem Jahr variieren. +

+ +

+Die Anmeldung für die Gruppen JuMa, +Klettertreff und +Mountainbike laufen separat. +

{% if error_message %}

{{ error_message }}

diff --git a/jdav_web/members/views.py b/jdav_web/members/views.py index 0b5cd97..158095a 100644 --- a/jdav_web/members/views.py +++ b/jdav_web/members/views.py @@ -1,4 +1,4 @@ -from django.shortcuts import render +from startpage.views import render from django.utils.translation import gettext_lazy as _ from django.http import HttpResponseRedirect from django.forms import ModelForm, TextInput, DateInput diff --git a/jdav_web/startpage/admin.py b/jdav_web/startpage/admin.py index 8c38f3f..c1dcd06 100644 --- a/jdav_web/startpage/admin.py +++ b/jdav_web/startpage/admin.py @@ -1,3 +1,26 @@ from django.contrib import admin -# Register your models here. +from .models import Post, Image, Section, MemberOnPost + + +class ImageInline(admin.TabularInline): + model = Image + extra = 0 + + +class MemberOnPostInline(admin.TabularInline): + model = MemberOnPost + extra = 0 + + +@admin.register(Post) +class PostAdmin(admin.ModelAdmin): + inlines = [ImageInline, MemberOnPostInline] + list_display = ['title', 'date', 'section', 'absolute_urlname'] + list_filter = ['section'] + search_fields = ['title'] + + +@admin.register(Section) +class SectionAdmin(admin.ModelAdmin): + list_display = ['title', 'absolute_urlname'] diff --git a/jdav_web/startpage/migrations/0001_initial.py b/jdav_web/startpage/migrations/0001_initial.py new file mode 100644 index 0000000..a867c0f --- /dev/null +++ b/jdav_web/startpage/migrations/0001_initial.py @@ -0,0 +1,77 @@ +# Generated by Django 4.0.1 on 2023-04-09 12:11 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import markdownx.models +import utils + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('members', '0012_member_image_group_description'), + ] + + operations = [ + migrations.CreateModel( + name='Section', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=50, verbose_name='Title')), + ('urlname', models.CharField(max_length=25, verbose_name='URL')), + ('website_text', markdownx.models.MarkdownxField(blank=True, default='', verbose_name='website text')), + ], + options={ + 'verbose_name': 'Section', + 'verbose_name_plural': 'Sections', + 'unique_together': {('urlname',)}, + }, + ), + migrations.CreateModel( + name='Post', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(default='', max_length=50, verbose_name='Title')), + ('urlname', models.CharField(default='', max_length=50, verbose_name='URL')), + ('date', models.DateField(blank=True, default=django.utils.timezone.localdate, null=True, verbose_name='Date')), + ('website_text', markdownx.models.MarkdownxField(blank=True, default='', verbose_name='website text')), + ('detailed', models.BooleanField(default=False, verbose_name='detailed')), + ('groups', models.ManyToManyField(blank=True, to='members.Group', verbose_name='Groups')), + ('section', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='startpage.section', verbose_name='section')), + ], + options={ + 'verbose_name': 'Post', + 'verbose_name_plural': 'Posts', + 'unique_together': {('section', 'urlname')}, + }, + ), + migrations.CreateModel( + name='MemberOnPost', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.TextField(blank=True, default='', verbose_name='Description')), + ('tag', models.CharField(blank=True, default='', max_length=20, verbose_name='Tag')), + ('members', models.ManyToManyField(blank=True, to='members.Member', verbose_name='Member')), + ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='people', to='startpage.post', verbose_name='Member')), + ], + options={ + 'verbose_name': 'Person', + 'verbose_name_plural': 'Persons', + }, + ), + migrations.CreateModel( + name='Image', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('f', utils.RestrictedFileField(blank=True, upload_to='images', verbose_name='file')), + ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='startpage.post')), + ], + options={ + 'verbose_name': 'image', + 'verbose_name_plural': 'images', + }, + ), + ] diff --git a/jdav_web/startpage/migrations/__init__.py b/jdav_web/startpage/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/jdav_web/startpage/models.py b/jdav_web/startpage/models.py index 71a8362..01fda7a 100644 --- a/jdav_web/startpage/models.py +++ b/jdav_web/startpage/models.py @@ -1,3 +1,102 @@ +import os + from django.db import models +from django.utils.translation import gettext_lazy as _ +from django.utils import timezone +from django.urls import reverse +from utils import RestrictedFileField +from members.models import Group, Member + +from markdownx.models import MarkdownxField + + +class Section(models.Model): + """ + A section of the website. + """ + title = models.CharField(verbose_name=_('Title'), max_length=50) + urlname = models.CharField(verbose_name=_('URL'), max_length=25) + website_text = MarkdownxField(verbose_name=_('website text'), default='', blank=True) + + class Meta: + verbose_name = _('Section') + verbose_name_plural = _('Sections') + unique_together = ['urlname'] + + def __str__(self): + return self.title + + def absolute_urlname(self): + return reverse('startpage:section', args=(self.urlname,)) + absolute_urlname.short_description = 'URL' + + +class Post(models.Model): + """ + A post with title, markdown and images. + """ + title = models.CharField(verbose_name=_('Title'), default='', max_length=50) + urlname = models.CharField(verbose_name=_('URL'), default='', max_length=50) + date = models.DateField(default=timezone.localdate, verbose_name=_('Date'), null=True, blank=True) + website_text = MarkdownxField(verbose_name=_('website text'), default='', blank=True) + + groups = models.ManyToManyField(Group, verbose_name=_('Groups'), blank=True) + detailed = models.BooleanField(verbose_name=_('detailed'), default=False) + + section = models.ForeignKey(Section, verbose_name=_('section'), on_delete=models.SET_NULL, null=True, blank=True) + + def __str__(self): + """String represenation""" + return self.title + + class Meta: + verbose_name = _("Post") + verbose_name_plural = _("Posts") + unique_together = ['section', 'urlname'] + + def absolute_section(self): + if self.section is None: + return 'Aktuelles' + else: + return self.section.title + absolute_section.short_description = _('Section') + + def absolute_urlname(self): + if self.section is None: + return reverse('startpage:post', args=('aktuelles', self.urlname)) + else: + return reverse('startpage:post', args=(self.section.urlname, self.urlname)) + absolute_urlname.short_description = 'URL' + + +class Image(models.Model): + """ + An image on a post. + """ + post = models.ForeignKey(Post, on_delete=models.CASCADE) + # file (not naming it file because of builtin) + f = RestrictedFileField(_('file'), + upload_to='images', + blank=True, + max_upload_size=10485760) + + def __str__(self): + return os.path.basename(self.f.name) if self.f.name else _("Empty") + + class Meta: + verbose_name = _('image') + verbose_name_plural = _('images') + + +class MemberOnPost(models.Model): + """ + One or multiple members on a post. + """ + members = models.ManyToManyField(Member, verbose_name=_('Member'), blank=True) + post = models.ForeignKey(Post, verbose_name=_('Member'), on_delete=models.CASCADE, related_name='people') + description = models.TextField(_('Description'), default='', blank=True) + tag = models.CharField(_('Tag'), max_length=20, default='', blank=True) -# Create your models here. + class Meta: + verbose_name = _("Person") + verbose_name_plural = _("Persons") diff --git a/jdav_web/startpage/templates/startpage/404.html b/jdav_web/startpage/templates/startpage/404.html new file mode 100644 index 0000000..1e1880c --- /dev/null +++ b/jdav_web/startpage/templates/startpage/404.html @@ -0,0 +1,13 @@ +{% extends "startpage/base_subsite.html" %} + +{% block content %} +

Seite nicht gefunden

+ +

+Bitte entschuldigen Sie, wir konnten die gewünschte Seite nicht finden. +

+

+Zurück zur Startseite. +

+ +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/500.html b/jdav_web/startpage/templates/startpage/500.html new file mode 100644 index 0000000..7eb0c41 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/500.html @@ -0,0 +1,11 @@ +{% extends "startpage/base_subsite.html" %} + +{% block content %} +

Interner Fehler aufgetreten

+ +

+Bitte entschuldigen Sie, bei Ihrer Anfrage ist leider ein unerwarteter Fehler aufgetreten. Der Serveradministrator +wurde bereits verständigt. +

+ +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/aktuelles.html b/jdav_web/startpage/templates/startpage/aktuelles.html new file mode 100644 index 0000000..d33b37c --- /dev/null +++ b/jdav_web/startpage/templates/startpage/aktuelles.html @@ -0,0 +1,21 @@ +{% extends "startpage/base_subsite.html" %} +{% load static %} +{% load markdownify %} +{% load markdown_extras %} + +{% block content %} +

Aktuelles

+ +{% for post in posts %} + +
+

{{ post.title }}

+

+ {{ post.website_text|markdownify|truncatechars:200 }} + weiterlesen +

+
+ +{% endfor %} + +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/base.html b/jdav_web/startpage/templates/startpage/base.html new file mode 100644 index 0000000..05414ba --- /dev/null +++ b/jdav_web/startpage/templates/startpage/base.html @@ -0,0 +1,27 @@ +{% load static %} + + + + {% block title %}{% endblock %} + + + + + + + + {% include "startpage/navigation.html" %} + +
+ {% block header %} + {% include "startpage/header.html" %} + {% endblock %} + +
+ {% block content %}{% endblock %} +
+
+ + {% include "startpage/footer.html" %} + + diff --git a/jdav_web/startpage/templates/startpage/base_subsite.html b/jdav_web/startpage/templates/startpage/base_subsite.html new file mode 100644 index 0000000..d498ef5 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/base_subsite.html @@ -0,0 +1,5 @@ +{% extends "startpage/base.html" %} + +{% block header %} +{% include "startpage/header_small.html" %} +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/footer.html b/jdav_web/startpage/templates/startpage/footer.html new file mode 100644 index 0000000..765c1fa --- /dev/null +++ b/jdav_web/startpage/templates/startpage/footer.html @@ -0,0 +1,5 @@ + diff --git a/jdav_web/startpage/templates/startpage/gruppen.html b/jdav_web/startpage/templates/startpage/gruppen.html new file mode 100644 index 0000000..ae94fc5 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/gruppen.html @@ -0,0 +1,21 @@ +{% extends "startpage/base_subsite.html" %} + +{% block content %} +

Gruppen

+ +

+Die JDAV Heidelberg bietet verschiedene Gruppen für die Jugend bis 27 Jahre an. Die meisten Gruppen klettern regelmäßig in der Halle und Draußen, aber auch allgemeine Ausfahrten, Wintersport, Hochtouren und Mountenbiken gehöhren zu den Aktivitäten. Nachfolgend findest du eine Übersicht aller Gruppen. Die Teilnahme an den Gruppen erfordert generell eine vorherigen Anmledung, auch wenn Zeit und Ort bekannt sein sollte bitten wir dich nicht einfach dort zu erscheinen. +

+ +

Zur Zeit bieten wir die Folgenden Gruppen an:

+ + + + +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/gruppen/detail.html b/jdav_web/startpage/templates/startpage/gruppen/detail.html new file mode 100644 index 0000000..fdd63d2 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/gruppen/detail.html @@ -0,0 +1,14 @@ +{% extends "startpage/base_subsite.html" %} + +{% block content %} +

{{ group.name }}

+ +

+{{ group.description }} +

+ +

Gruppenleitung

+ +{% include "startpage/people_grid.html" %} + +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/gruppen/faq.html b/jdav_web/startpage/templates/startpage/gruppen/faq.html new file mode 100644 index 0000000..1dc29cc --- /dev/null +++ b/jdav_web/startpage/templates/startpage/gruppen/faq.html @@ -0,0 +1,44 @@ +{% extends "startpage/base_subsite.html" %} + +{% block content %} +

FAQ

+ +

Ab welchem Alter kann ich mein Kind zu den Jugendgruppen anmelden?

+ +

Unsere Jugendgruppen sind ab einem Alter von 9 Jahren. Sie können ihr Kind gerne bereits früher auf die Liste setzen, um die Wartezeit zu verkürzen, sobald ihr Kind das entsprechende Alter erreicht hat.

+ +

Wie lange sind die Wartezeiten?

+ +

+Leider haben wir eine sehr große Nachfrage, der wir mit unseren Jugendleiter:innen und unseren Gruppenplätzen nicht nachkommen können. Die Wartezeiten sind sehr unterscheidlich und hängen vom Alter und den verfügbaren Gruppenplätzen ab. Die Wartezeiten kann zwischen einigen Wochen und mehr als einem Jahr liegen. +

+ +

Muss mein Kind DAV Mitglied sein?

+ +

+Ja. Sobald ihr Kind regelmäßig an den Gruppenstunden teilnimmt, muss es Mitglied im DAV Heidelberg sein. Für die Aufnahme in die Warteliste ist keine Mitgliedschaft notwenig. +

+ +

Was kostet die Teilnahme an den Jugendgruppen?

+ +

+Die Jugendgruppen an sich sind kostenlos, allerdings ist eine Vereinsmitgliedschaft und der Halleneintritt nötig. Der Beitrag setzt sich aus zwei Teilen zusammen: +

+ +

+

+

+ +

Benötigt mein Kind eine Ausrüstung?

+ +

+Während der Gruppenstunden können die Kinder das Material (Klettergurt, Schuhe, Sicherungsgerät, … ) ohne zusätzliche Kosten von der Jugend des DAV Heidelberg ausleihen. +

+ +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/header.html b/jdav_web/startpage/templates/startpage/header.html new file mode 100644 index 0000000..02ab273 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/header.html @@ -0,0 +1,9 @@ +
+ + + +
+
Jugend des deutschen Alpenvereins
+
Sektion Heidelberg
+
+
diff --git a/jdav_web/startpage/templates/startpage/header_small.html b/jdav_web/startpage/templates/startpage/header_small.html new file mode 100644 index 0000000..0651a69 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/header_small.html @@ -0,0 +1,8 @@ +
+ + + +
+
Jugend des deutschen Alpenvereins
+
+
diff --git a/jdav_web/startpage/templates/startpage/impressum.html b/jdav_web/startpage/templates/startpage/impressum.html new file mode 100644 index 0000000..eb31dc1 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/impressum.html @@ -0,0 +1,369 @@ +{% extends "startpage/base_subsite.html" %} +{% load static %} + +{% block content %} + +

Impressum

+ +

Anbieter

+ +

+Deutscher Alpenverein Sektion Heidelberg 1869 e.V.
+Jugendreferat
+Harbigweg 20
+69124 Heidelberg, Deutschland
+Tel.: +49 (62 21) 48 40 76
+Fax: +49 (62 21) 43 73 38
+E-Mail: geschaeftsstelle@alpenverein-heidelberg.de
+URL: www.alpenverein-heidelberg.de
+

+ +

Vertretungsberechtigter

+ +

+Der Deutsche Alpenverein Sektion Heidelberg 1869 wird durch den ersten Vorsitzenden, den zweiten Vorsitzenden und den Schatzmeister vertreten: +

+ +

+Dr. Ulf Gieseler (1. Vorsitzender), Paul Jonas (2. Vorsitzender), Marc von der Heydt (Schatzmeister) +(gemäß § 14 Satz der Satzung des Deutschen Alpenvereins Sektion Heidelberg 1869) +

+ +

Vereinsregister

+ +

+Der Deutsche Alpenverein Sektion Heidelberg 1869 e.V. ist im Vereinsregister des Amtsgerichts Heidelberg unter der Registernummer VR 486 eingetragen. +

+ +

Jugendreferat

+ +

+Leitung: Eva Engelmann und Robert Scheffler (kommissarisch)
+E-Mail: jugend@alpenverein-heidelberg.de
+URL: www.jdav-hd.de ; www.jdav-heidelberg.de +

+ +

+Haftungsausschluss; Disclaimer +

+ + +

Datenschutzerklärung

+ +

1. Wer für Ihre personenbezogenen Daten verantwortlich ist:

+ +

+Diese Datenschutz-Information gilt für die Datenverarbeitung durch: +

+ +

+Verantwortlicher: Deutscher Alpenverein Sektion Heidelberg 1869 e.V.
+Harbigweg 20, 69124 Heidelberg
+Email: alpenverein-heidelberg@t-online.de
+Telefon: +49 6221 484076 +

+ +

+Zur Auftragsverarbeitung für die jdav Heidelberg ist die Firma reeweb AG Wettsteinplatz 74058 Basel Schweiz beauftragt. Die Datenverarbeitung erfolgt in Rechenzentren in der Schweiz oder Staaten des Europäischen Wirtschaftsraums (EWR). +

+ +

+2. Welche personenbezogenen Daten wir von Ihnen erheben und zu welchem Zweck das geschieht: +

+ +

+Beim Aufrufen unserer Website jdav-hd.merten.dev werden durch den auf Ihrem Endgerät zum Einsatz kommenden Browser automatisch Informationen an den Server unserer Website gesendet. Diese Informationen werden temporär in einem sog. Logfile gespeichert. Folgende Informationen werden dabei ohne Ihr Zutun erfasst und bis zur automatischen Löschung gespeichert: +

+ +

+

+

+ +

+Die genannten Daten werden durch uns zu folgenden Zwecken verarbeitet: +

+ + +

+Die Rechtsgrundlage für die Datenverarbeitung ist Art. 6 Abs. 1 S. 1 lit. f DSGVO. Unser berechtigtes Interesse folgt aus oben aufgelisteten Zwecken zur Datenerhebung. In keinem Fall verwenden wir die erhobenen Daten zu dem Zweck, Rückschlüsse auf Ihre Person zu ziehen. +

+ +

+Darüber hinaus setzen wir beim Besuch unserer Website Cookies ein. Nähere Erläuterungen dazu erhalten Sie unter den Ziff. 4 dieser Datenschutzerklärung. +

+ +

3. Welche Daten wir zu welchem Zweck weitergeben:

+ +

+Eine Übermittlung Ihrer persönlichen Daten an Dritte zu anderen als den im Folgenden aufgeführten Zwecken findet nicht statt. +

+ +a) Weitergabe von Daten, die wir im Rahmen Ihres Besuchs unserer Website erheben: + +

+Wir geben Ihre persönlichen Daten nur an Dritte weiter, wenn: +

+ + + +b) Weitergabe Ihrer Daten im Rahmen unserer Vereinstätigkeit + +

+Zur Weitergabe der Daten im Rahmen einer Mitgliedschaft im Alpenverein Heidelberg beachten Sie bitte auch die Datenschutzerklärung der Sektion unter www.alpenverein-heidelberg.de/datenschutz. +

+ +

+Die jdav Heidelberg hat die Firma reeweb AG Wettsteinplatz 74058 Basel Schweiz beauftragt die Daten ihrer Mitglieder zu verwalten. Diese Datenverarbeitung erfolgt in Rechenzentren in der Schweiz oder Staaten des Europäischen Wirtschaftsraums (EWR). +

+ +

+Die von Ihnen in Ihrer Beitrittserklärung angegebenen Daten über Ihre persönlichen und sachlichen Verhältnisse (sogenannte personenbezogene Daten) werden gleichermaßen auf Datenverarbeitungs-Systemen der Sektion, der Sie beitreten, wie auch des Bundesverbandes des Deutschen Alpenvereins (DAV) gespeichert und für Verwaltungszwecke der Sektion, bzw. des Bundesverbandes verarbeitet und genutzt werden. Verantwortliche Stelle im Sinne des § 3 (7) BDSG bzw. Art. 4 lit 7. DSGVO ist dabei die Sektion, der Sie beitreten. +

+ +

+Eine Übermittlung von Teilen dieser Daten an die jeweiligen Landes- und Sportfachverbände findet nur im Rahmen der in den Satzungen der Landes- und Sportfachverbände festgelegten Zwecke statt. Diese Datenübermittlungen sind notwendig zum Zwecke der Organisation eines Spiel- bzw. Wettkampfbetriebes und zum Zwecke der Einwerbung von öffentlichen Fördermitteln. +

+ +

+Wir sichern Ihnen zu, Ihre personenbezogenen Daten vertraulich zu behandeln und nicht an Stellen außerhalb des DAV, weder außerhalb der Sektion, noch außerhalb des Bundesverbandes und der jeweiligen Landes- und Sportfachverbände weiterzugeben. Sie können jederzeit schriftlich Auskunft über die bezüglich Ihrer Person gespeicherten Daten erhalten und Korrektur verlangen, soweit die bei der Sektion und der Bundesgeschäftsstelle gespeicherten Daten unrichtig sind. Sollten die gespeicherten Daten für die Abwicklung der Geschäftsprozesse der Sektion, bzw. des Bundesverbandes nicht erforderlich sein, so können Sie auch eine Sperrung, gegebenenfalls auch eine Löschung Ihrer personenbezogenen Daten verlangen. +

+ +

+Nach einer Beendigung der Mitgliedschaft werden Ihre personenbezogenen Daten gelöscht, soweit sie nicht, entsprechend der steuerrechtlichen Vorgaben, aufbewahrt werden müssen. +

+ +

+Eine Nutzung Ihrer personenbezogenen Daten für Werbezwecke findet weder durch die Sektion, den Bundesverband, Kooperationspartner des Bundesverbandes des Deutschen Alpenvereins noch durch die jeweiligen Landes- und Sportfachverbände statt. +

+ +

+Die Datenverarbeitung erfolgt auf Grundlage des Art. 6 Abs. 1 S. 1 lit. b DSGVO. +

+ +

4. Wir setzen Cookies ein:

+ +

+Wir setzen auf unserer Seite Cookies ein. Hierbei handelt es sich um kleine Dateien, die Ihr Browser automatisch erstellt und die auf Ihrem Endgerät (Laptop, Tablet, Smartphone o.ä.) gespeichert werden, wenn Sie unsere Seite besuchen. Cookies richten auf Ihrem Endgerät keinen Schaden an, enthalten keine Viren, Trojaner oder sonstige Schadsoftware. +

+ +

+In dem Cookie werden Informationen abgelegt, die sich jeweils im Zusammenhang mit dem spezifisch eingesetzten Endgerät ergeben. Dies bedeutet jedoch nicht, dass wir dadurch unmittelbar Kenntnis von Ihrer Identität erhalten. +

+ +

+Der Einsatz von Cookies dient einerseits dazu, die Nutzung unseres Angebots für Sie angenehmer zu gestalten. So setzen wir sogenannte Session-Cookies ein, um zu erkennen, dass Sie einzelne Seiten unserer Website bereits besucht haben. Diese werden nach Verlassen unserer Seite automatisch gelöscht. +

+ +

+Darüber hinaus setzen wir ebenfalls zur Optimierung der Benutzerfreundlichkeit temporäre Cookies ein, die für einen bestimmten festgelegten Zeitraum auf Ihrem Endgerät gespeichert werden. Besuchen Sie unsere Seite erneut, um unsere Dienste in Anspruch zu nehmen, wird automatisch erkannt, dass Sie bereits bei uns waren und welche Eingaben und Einstellungen Sie getätigt haben, um diese nicht noch einmal eingeben zu müssen. +

+ +

+Die durch Cookies verarbeiteten Daten sind für die genannten Zwecke zur Wahrung unserer berechtigten Interessen sowie der Dritter nach Art. 6 Abs. 1 S. 1 lit. f DSGVO erforderlich. +

+ +

+Die meisten Browser akzeptieren Cookies automatisch. Sie können Ihren Browser jedoch so konfigurieren, dass keine Cookies auf Ihrem Computer gespeichert werden oder stets ein Hinweis erscheint, bevor ein neuer Cookie angelegt wird. Die vollständige Deaktivierung von Cookies kann jedoch dazu führen, dass Sie nicht alle Funktionen unserer Website nutzen können. +

+ +

5. Das geschieht im Falle einer elektronischen Kontaktaufnahme:

+ +

+a) Beschreibung und Umfang der Datenverarbeitung +

+ +

+Auf unserer Internetseite sind Kontaktformulare vorhanden, welche für die elektronische Kontaktaufnahme genutzt werden können. Nimmt ein Nutzer diese Möglichkeit wahr, so werden die in der Eingabemaske eingegeben Daten an uns übermittelt und gespeichert. Diese Daten sind: +

+ +

+Name, Email-Adresse, Betreff und Inhalt Ihrer Nachricht. +

+ +

+Im Zeitpunkt der Absendung der Nachricht werden zudem folgende Daten gespeichert +

+ +

+

+

+ +

+Für die Verarbeitung der Daten wird im Rahmen des Absendevorgangs Ihre Einwilligung eingeholt und auf diese Datenschutzerklärung verwiesen. +

+ +

+Alternativ ist eine Kontaktaufnahme über die bereitgestellte Email-Adresse möglich. In diesem Fall werden Ihre mit der E-Mail übermittelten personenbezogenen Daten gespeichert. +

+ +

+Es erfolgt in diesem Zusammenhang keine Weitergabe der Daten an Dritte. Die Daten werden ausschließlich für die Verarbeitung der Konversation verwendet. +

+ +

+Falls im Formular angegeben erfolgt eine Weiterleitung aller eingegeben Daten an die private E-Mail-Adresse der verantwortlichen Jugendleiter. In diesem Fall kann je nach E-Mail Provider des Jugendleiters eine Weitergabe der Daten an Dritte nicht ausgeschlossen werden. +

+ +

b) Rechtsgrundlage für die Datenverarbeitung

+ +

+Rechtsgrundlage für die Verarbeitung der Daten ist bei Vorliegen Ihrer Einwilligung Art. 6 Abs. 1 lit. a DSGVO. +

+ +

+Rechtsgrundlage für die Verarbeitung der Daten, die im Zuge einer Übersendung einer Email übermittelt werden, ist Art. 6 Abs. 1 lit. f DSGVO. Zielt der Email-Kontakt auf den Abschluss eines Vertrages, so ist zusätzliche Rechtsgrundlage für die Verarbeitung Art. 6 Abs. 1 lit. b DSGVO. +

+ +

c) Zweck der Datenverarbeitung

+ +

+Die Verarbeitung der personenbezogenen Daten aus der Eingabemaske dient uns allein zur Bearbeitung der Kontaktaufnahme. Im Falle einer Kontaktaufnahme per E-Mail liegt hierin auch das erforderliche berechtigte Interesse an der Verarbeitung der Daten. +

+ +

+Die sonstigen während des Absendevorgangs verarbeiteten personenbezogenen Daten dienen dazu, einen Missbrauch des Kontaktformulars zu verhindern und die Sicherheit unserer informationstechnischen Systeme sicherzustellen. +

+ +

d) Dauer der Speicherung

+ +

+Die Daten werden gelöscht, sobald sie für die Erreichung des Zweckes ihrer Erhebung nicht mehr erforderlich sind. Für die personenbezogenen Daten aus der Eingabemaske des Kontaktformulars und diejenigen, die per E-Mail übersandt wurden, ist dies dann der Fall, wenn die jeweilige Konversation mit dem Nutzer beendet ist. Beendet ist die Konversation dann, wenn sich aus den Umständen entnehmen lässt, dass der betroffene Sachverhalt abschließend geklärt ist. +

+ +

+Die während des Absendevorgangs zusätzlich erhobenen personenbezogenen Daten werden spätestens nach einer Frist von sieben Tagen gelöscht. +

+ +

6. Das geschieht, wenn Sie Online-Anmeldeformulare nutzen:

+ +

+Auf unserer Internetseite sind Anmeldeformulare vorhanden, welches für die elektronische Anmeldung zu Jugendgruppen, Kursen und Veranstaltungen unseres Vereins genutzt werden kann. Nimmt ein Nutzer diese Möglichkeit wahr, so werden die in der Eingabemaske eingegeben Daten an uns übermittelt und gespeichert. Für diese Datenverarbeitung ist die Firma reeweb AG Wettsteinplatz 74058 Basel Schweiz beauftragt. Diese Daten sind: +

+ +

+Name, Email-Adresse, Telefonnummer, gewählter Kurs, Informationen zu DAV-Mitgliedschaft, Mitgliedsnummer, Alter bzw. Geburtsdatum, Adresse, Informationen zur Verfügbarkeit für Jugendgruppen ggfs. Informationen zur Lawinenausbildung, allfällig übermittelte Bemerkungen. +

+ +

+Im Zeitpunkt der Absendung der Nachricht werden zudem folgende Daten gespeichert: +

+ +

+

+

+ +

+Für die Verarbeitung der Daten wird im Rahmen des Absendevorgangs Ihre Einwilligung eingeholt und auf diese Datenschutzerklärung verwiesen. +

+ +

+Die gespeicherten Daten werden spätestens ein Jahr nach Durchführung der Veranstaltung gelöscht, sofern nicht steuerliche Vorschriften eine längere Speicherdauer vorgeben. Daten auf der unserer Warteliste für Jugendgruppen werden ohne Frist gespeichert und auf Nachfrage bei anmeldung.jdav@alpenverein-heidelberg.de gelöscht werden. +

+ +

7. Das geschieht, wenn Sie Downloads vornehmen:

+ +

+Auf unserer Internetseite sind Download-Angebote eingestellt. Nimmt ein Nutzer einen Download vor, so werden Daten an uns übermittelt und gespeichert. Diese Daten sind: +

+ +

+

+

+ +

+Rechtsgrundlage für diese Speicherung ist Art. 6 Abs. 1 lit. f. DSGVO. +

+ +

+Die gespeicherten Daten werden mit Ende des Besuchs unserer Website gelöscht. +

+ +

8. Ihre Betroffenenrechte:

+ +

+Sie haben das Recht: +

+ +

+

+

+ +

9. Ihre Widerspruchsrechte:

+ +

+Sofern Ihre personenbezogenen Daten auf Grundlage von berechtigten Interessen gemäß Art. 6 Abs. 1 S. 1 lit. f DSGVO verarbeitet werden, haben Sie das Recht, gemäß Art. 21 DSGVO Widerspruch gegen die Verarbeitung Ihrer personenbezogenen Daten einzulegen, soweit dafür Gründe vorliegen, die sich aus Ihrer besonderen Situation ergeben oder sich der Widerspruch gegen Direktwerbung richtet. Im letzten Fall haben Sie ein generelles Widerspruchsrecht, das ohne Angabe einer besonderen Situation von uns umgesetzt wird. +

+ +

+Möchten Sie von Ihrem Widerrufs- oder Widerspruchsrecht Gebrauch machen, genügt eine Email an +jugend@alpenverein-heidelberg.de oder +alpenverein-heidelberg@t-online.de. +

+ +

10. Die Sicherheit Ihrer Daten:

+ +

+Wir bedienen uns geeigneter technischer und organisatorischer Sicherheitsmaßnahmen, um Ihre Daten gegen zufällige oder vorsätzliche Manipulationen, teilweisen oder vollständigen Verlust, Zerstörung oder gegen den unbefugten Zugriff Dritter zu schützen. Unsere Sicherheitsmaßnahmen werden entsprechend der technologischen Entwicklung fortlaufend verbessert. +

+ +

11. Aktualität und Änderung dieser Datenschutzerklärung

+ +

+Diese Datenschutzerklärung ist aktuell gültig und hat den Stand April 2020. +

+ +

+Durch die Weiterentwicklung unserer Website und Angebote darüber oder aufgrund geänderter gesetzlicher beziehungsweise behördlicher Vorgaben kann es notwendig werden, diese Datenschutzerklärung zu ändern. Die jeweils aktuelle Datenschutzerklärung kann jederzeit auf der Website unter +www.jdav-hd.de/impressum#datenschutz von Ihnen aufgerufen und falls gewünscht ausgedruckt werden. +

+ +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/index.html b/jdav_web/startpage/templates/startpage/index.html index 390893c..35d6f44 100644 --- a/jdav_web/startpage/templates/startpage/index.html +++ b/jdav_web/startpage/templates/startpage/index.html @@ -1,2 +1,30 @@ -{% load i18n %} -{% trans "Awesome JDAV website being able to do a lot!" %} +{% extends "startpage/base.html" %} +{% load static %} + +{% block title %} +Startseite +{% endblock %} + +{% block content %} + +
+
+

Herzlich Willkommen

+

+ Herzlich Willkommen auf unserer Webseite. Hier finden Sie alle + Informationen über die jdav Heidelberg. Viel Spaß beim Surfen! +

+
+
+

Aktuelles

+ +
+
+ +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/jugendleiterinnen.html b/jdav_web/startpage/templates/startpage/jugendleiterinnen.html new file mode 100644 index 0000000..04d375a --- /dev/null +++ b/jdav_web/startpage/templates/startpage/jugendleiterinnen.html @@ -0,0 +1,8 @@ +{% extends "startpage/base_subsite.html" %} + +{% block content %} +

Unsere Jugendleiter*innen

+ +{% include "startpage/people_grid.html" %} + +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/navigation.html b/jdav_web/startpage/templates/startpage/navigation.html new file mode 100644 index 0000000..87df48b --- /dev/null +++ b/jdav_web/startpage/templates/startpage/navigation.html @@ -0,0 +1,126 @@ +{% load static %} + + + + + + diff --git a/jdav_web/startpage/templates/startpage/people_grid.html b/jdav_web/startpage/templates/startpage/people_grid.html new file mode 100644 index 0000000..9b17f1a --- /dev/null +++ b/jdav_web/startpage/templates/startpage/people_grid.html @@ -0,0 +1,23 @@ +{% load static %} + +
+
+ {% for member in people %} +
+
+ {% if member.image %} + + {% else %} + + {% endif %} +
+
{{ member.name }}
+ {% if member.extra %} +
{{ member.extra }}
+ {% endif %} +
+
+
+ {% endfor %} +
+
diff --git a/jdav_web/startpage/templates/startpage/post.html b/jdav_web/startpage/templates/startpage/post.html new file mode 100644 index 0000000..0f41401 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/post.html @@ -0,0 +1,19 @@ +{% extends "startpage/base_subsite.html" %} +{% load static markdown_extras markdownify %} + +{% block content %} +

{{ post.title }}

+ +{% render_as_template "post.website_text" as result %} + +{{ result|markdownify }} + +{% if post.detailed %} + {% include 'startpage/post_people_detail.html' %} +{% else %} + {% include 'startpage/post_people_grid.html' %} +{% endif %} + +{% include 'startpage/people_grid.html' %} + +{% endblock %} diff --git a/jdav_web/startpage/templates/startpage/post_people_detail.html b/jdav_web/startpage/templates/startpage/post_people_detail.html new file mode 100644 index 0000000..62d7d65 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/post_people_detail.html @@ -0,0 +1,26 @@ +{% load static %} +{% load markdownify %} + + + {% for person in post.people.all %} + + + {% for member in person.members.all %} + + {% endfor %} + + {% endfor %} +
+ {{ person.description|markdownify }} + +
+ {% if member.image %} + + {% else %} + + {% endif %} +
+
{{ member.name }}
+
+
+
diff --git a/jdav_web/startpage/templates/startpage/post_people_grid.html b/jdav_web/startpage/templates/startpage/post_people_grid.html new file mode 100644 index 0000000..fcbaad1 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/post_people_grid.html @@ -0,0 +1,25 @@ +{% load static %} + +
+
+ {% for person in post.people.all %} + {% for member in person.members.all %} +
+
+ {% if member.image %} + + {% else %} + + {% endif %} +
+
{{ member.name }}
+ {% if person.description %} +
{{ person.description }}
+ {% endif %} +
+
+
+ {% endfor %} + {% endfor %} +
+
diff --git a/jdav_web/startpage/templates/startpage/section.html b/jdav_web/startpage/templates/startpage/section.html new file mode 100644 index 0000000..bca9a70 --- /dev/null +++ b/jdav_web/startpage/templates/startpage/section.html @@ -0,0 +1,11 @@ +{% extends "startpage/base_subsite.html" %} +{% load static markdown_extras markdownify %} + +{% block content %} +

{{ section.title }}

+ +{% render_as_template "section.website_text" as result %} + +{{ result|markdownify }} + +{% endblock %} diff --git a/jdav_web/startpage/templatetags/markdown_extras.py b/jdav_web/startpage/templatetags/markdown_extras.py new file mode 100644 index 0000000..00ae99e --- /dev/null +++ b/jdav_web/startpage/templatetags/markdown_extras.py @@ -0,0 +1,49 @@ +from django import template +from django.urls import reverse +from django.utils.safestring import mark_safe +from django.template import Template, Variable, TemplateSyntaxError + +import re + +register = template.Library() + + +class RenderAsTemplateNode(template.Node): + """ + Renders passed content as template. This is probably dangerous and should only be exposed + to admins! + """ + def __init__(self, item_to_be_rendered, var_name): + self.item_to_be_rendered = Variable(item_to_be_rendered) + self.var_name = var_name + + def render(self, context): + try: + actual_item = self.item_to_be_rendered.resolve(context) + context[self.var_name] = Template(actual_item).render(context) + return "" + except template.VariableDoesNotExist: + return '' + + +def render_as_template(parser, token): + # This version uses a regular expression to parse tag contents. + try: + # Splitting by None == splitting by spaces. + tag_name, arg = token.contents.split(None, 1) + except ValueError: + raise template.TemplateSyntaxError( + "%r tag requires arguments" % token.contents.split()[0] + ) + m = re.search(r"(.*?) as (\w+)", arg) + if not m: + raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name) + format_string, var_name = m.groups() + if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): + raise template.TemplateSyntaxError( + "%r tag's argument should be in quotes" % tag_name + ) + return RenderAsTemplateNode(format_string[1:-1], var_name) + + +render_as_template = register.tag(render_as_template) diff --git a/jdav_web/startpage/urls.py b/jdav_web/startpage/urls.py index 2d313ca..70fe2ec 100644 --- a/jdav_web/startpage/urls.py +++ b/jdav_web/startpage/urls.py @@ -4,5 +4,13 @@ from . import views app_name = "startpage" urlpatterns = [ - re_path(r'^$', views.index, name='index') + re_path(r'^$', views.index, name='index'), + re_path(r'^impressum/?$', views.static_view('startpage/impressum.html'), name='impressum'), + re_path(r'^aktuelles/?$', views.aktuelles, name='aktuelles'), + re_path(r'^jugendleiterinnen/?$', views.jugendleiterinnen, name='jugendleiterinnen'), + re_path(r'^gruppen/?$', views.static_view('startpage/gruppen.html'), name='gruppen'), + re_path(r'^gruppen/faq/?$', views.static_view('startpage/gruppen/faq.html'), name='faq'), + re_path(r'^gruppen/(?P[\w\-:]+)/?$', views.gruppe_detail, name='gruppe_detail'), + re_path(r'^(?P[\w\-:]+)/(?P[\w\-:]+)/?$', views.post, name='post'), + re_path(r'^(?P[\w\-:]+)/?$', views.section, name='section'), ] diff --git a/jdav_web/startpage/views.py b/jdav_web/startpage/views.py index f0cd9a9..113239d 100644 --- a/jdav_web/startpage/views.py +++ b/jdav_web/startpage/views.py @@ -1,7 +1,97 @@ -from django.shortcuts import redirect +from django.shortcuts import redirect, get_object_or_404 +from django import shortcuts from django.conf import settings +from django.urls import reverse +from django.http import HttpResponseNotFound, Http404 +from itertools import chain + +from members.models import Group +from .models import Post, Section + + +# render shortcut adding additional context variables, needed for navbar +def render(request, template_path, context={}): + context['groups'] = Group.objects.filter(show_website=True) + context['sections'] = Section.objects.all() + return shortcuts.render(request, template_path, context) -# Create your views here. def index(request): - return redirect(settings.STARTPAGE_REDIRECT_URL) + context = { + 'posts': Post.objects.filter(section=None) + } + return render(request, 'startpage/index.html', context) + + +# static view factory +def static_view(template_path): + def view(request): + return render(request, template_path) + return view + + +def jugendleiterinnen(request): + group = get_object_or_404(Group, name='Jugendleiter') + people = group.member_set.all() + context = { + 'people': people + } + return render(request, 'startpage/jugendleiterinnen.html', context) + + +def gruppe_detail(request, group_name): + try: + group = Group.objects.get(name=group_name) + except Group.DoesNotExist: + raise Http404 + if not group.show_website: + raise Http404 + + context = { + 'group': group, + 'people': group.leiters.all(), + } + return render(request, 'startpage/gruppen/detail.html', context) + + +def aktuelles(request): + posts = Post.objects.filter(section=None) + context = { + 'posts': posts, + } + return render(request, 'startpage/aktuelles.html', context) + + +def post(request, section_name, post_name): + if section_name == 'aktuelles': + section = None + else: + section = get_object_or_404(Section, urlname=section_name) + post = get_object_or_404(Post, section=section, urlname=post_name) + context = { + 'post': post, + 'section': section, + 'people': [m for group in post.groups.all() for m in group.member_set.all()], + } + return render(request, 'startpage/post.html', context) + + +def section(request, section_name): + assert section_name != 'aktuelles' + section = get_object_or_404(Section, urlname=section_name) + context = { + 'section': section, + } + return render(request, 'startpage/section.html', context) + + +def handler404(request, exception): + response = render(request, 'startpage/404.html') + response.status_code = 404 + return response + + +def handler500(request): + response = render(request, 'startpage/500.html') + response.status_code = 500 + return response diff --git a/jdav_web/static/startpage/css/base.css b/jdav_web/static/startpage/css/base.css new file mode 100644 index 0000000..f66376e --- /dev/null +++ b/jdav_web/static/startpage/css/base.css @@ -0,0 +1,342 @@ +html { + height: 100%; + margin: 0; + padding: 0; +} + +body { + height: 100%; + margin: 0; + padding: 0; +} + +h5 { + color: white; + font-family: Oswald, sans-serif; + font-size: 120px; + font-weight: 700; + font-style: normal; + text-decoration: none; + overflow-wrap: break-word; + text-transform: none; + padding-top: 50px; + padding-left: 40px; + padding-right: 40px; + margin: 0; +} + +h6 { + color: white; + font-family: Oswald, sans-serif; + font-size: 56px; + font-weight: 200; + font-style: normal; + text-decoration: none; + text-align: left; + line-height: 100px; + text-transform: none; + margin: 10px 0; + overflow-wrap: break-word; +} + +.main { + margin-bottom: -50px; + box-sizing: border-box; + padding: 0 0 50px 0; + width: 100%; + min-height: 100%; +} + +.image { + position: absolute; + background-image: url('../img/background.jpeg'); + top: 0; + left: 0; + right: 0; + bottom: 0; + display: block; + background-size: cover; + background-origin: margin-box; + z-index: -2; + background-position: center center; +} + +.header { + position: relative; + width: 100%; +} + +.header-extra { +} + + +.footer { + position: relative; + bottom: 0; + left: 0; + width: 100%; + clear: both; + /* + border-top: 1px solid #C2D1E1; + color: #a0acba; + background: #f5f9ff;*/ + padding: 4px 0px; + height: 50px; + font-family: var(--sans); + font-size: 0.75em; + vertical-align: middle; + text-align: center; + line-height: 31px; + overflow: hidden; + box-sizing: border-box; +} + +.content { + width: 70%; + margin: 0 auto; + overflow: hidden; + position: relative; + padding-top: 40px; + padding-bottom: 40px; +} + +.column { + float: left; + width: 50%; + padding: 0 20px; +} + +/* Clear floats after the columns */ +.row:after { + content: ""; + clear: both; +} + +.footer a { + text-decoration: none; + color: rgba(87,171,39,1.0); +} + +.footer a:hover { + text-decoration: underline; +} + +.navigation { + position: fixed; + z-index: 1; + width: 100%; + left: 0; + top: 0; +} + + /* Navbar container */ +.navbar { + overflow: hidden; + font-family: Arial; + background-color: rgba(255, 255, 255, 0); + transition: background-color 0.15s linear; + padding-top: 10px; + padding-left: 10px; + padding-right: 10px; + padding-bottom: 5px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.overlay { + background-color: rgba(255, 255, 255, 0.9); + transition: background-color 0.15s linear; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); +} + +/* Links inside the navbar */ +.navbar a.nav { + float: right; + font-size: 16px; + color: black; + text-align: center; + padding: 11px 17px; + text-decoration: none; + border: 1px solid black; + border-radius: 25px; + vertical-align: middle; + margin-left: auto; +} + +/* The dropdown container */ +.dropdown { + float: left; + overflow: hidden; +} + +/* Dropdown button */ +.dropbtn { + font-size: 19px; + border: none; + outline: none; + color: black; + padding: 14px 16px; + background-color: rgba(255, 255, 255, 0); + font: inherit; /* Important for vertical align on mobile phones */ + margin: 0; /* Important for vertical align on mobile phones */ + float: right; + cursor: pointer; +} + +/* Add a red background color to navbar links on hover */ +.navbar a.nav:hover, .dropdown:hover .dropbtn { + background-color: rgba(87,171,39,1.0); + color: rgba(255,255,255,1.0); + border-color: white; +} + +/* Dropdown content (hidden by default) */ +.dropdown-content { + display: block; + position: absolute; + background-color: #f9f9f9; + width: 100%; + left: 0; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-out; +} + +.menu-level-1 { + float: right; +} + +.dropdown-content ul { + list-style-type: none; + margin: 0; + padding: 0; +} + +.dropdown-content .menu-level-1 > ul { + display: flex; + flex-flow: row; + flex-wrap: wrap; +} + +.dropdown-content li { + display: block; +} + +/* Create three equal columns that floats next to each other */ +.dropdown-content .column { + float: right; + max-width: 19%; + padding: 10px; + height: 250px; +} + +.dropdown-content .menu-level-1 a { + font-family: Roboto, sans-serif; + font-size: 24px; + font-weight: 700; + font-style: normal; + text-decoration: none; + text-align: left; + text-transform: none; + margin: 10px 20px; + overflow-wrap: break-word; + color: rgba(102,102,102,1.0); +} + +.dropdown-content .menu-level-1 a, .menu-level-2 a { + display: inline-block; +} + +a, a:visited { + text-transform: none; + text-decoration: none; +} + +/* Style links inside the columns */ +.dropdown-content .menu-level-2 a { + font-family: Roboto, sans-serif; + font-size: 16px; + font-weight: 400; + font-style: normal; + text-decoration: none; + text-align: left; + text-transform: none; + margin: 5px 20px; + overflow-wrap: break-word; + color: rgba(102,102,102,1.0); +} + +.dropdown-content a:hover { + color: rgba(87,171,39,1.0); +} + +.dropdown-content a.active { + color: rgba(87,171,39,1.0); +} + +.show { + max-height: 1000px; + transition: max-height 0.4s ease-in; +} + +p { + font-family: Open Sans, sans-serif; + font-size: 16px; + font-weight: 400; + font-style: normal; + text-decoration: none; + text-align: left; + line-height: 1.4; + text-transform: none; + margin: 20px 0; + overflow-wrap: break-word; +} + +h2 { + font-family: Roboto, sans-serif; + font-size: 40px; + font-weight: 700; + font-style: normal; + text-decoration: none; + text-align: left; + text-transform: none; + margin: 20px 0 10px 0; + overflow-wrap: break-word; + color: rgba(51,51,51,1.0); +} + +html, td, div { + font-family: Open Sans, sans-serif; + font-size: 16px; + font-weight: 400; + font-style: normal; + text-align: left; + line-height: 1.4; + text-transform: none; + overflow-wrap: break-word; +} + +*, ::before, ::after { + box-sizing: inherit; +} + +h1 { + font-family: Roboto, sans-serif; + font-size: 52px; + font-weight: 700; + font-style: normal; + text-decoration: none; + text-align: left; + text-transform: none; + margin: 30px 0 30px 0; + overflow-wrap: break-word; +} + +a, a:visited { + color: rgba(87,171,39,1.0); + text-transform: none; + text-decoration: none; +} diff --git a/jdav_web/static/startpage/css/fonts.css b/jdav_web/static/startpage/css/fonts.css new file mode 100644 index 0000000..e376599 --- /dev/null +++ b/jdav_web/static/startpage/css/fonts.css @@ -0,0 +1,27 @@ +/* oswald-regular - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Oswald'; + font-style: normal; + font-weight: 400; + src: url('../fonts/oswald-v49-latin-regular.eot'); /* IE9 Compat Modes */ + src: url('../fonts/oswald-v49-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/oswald-v49-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/oswald-v49-latin-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/oswald-v49-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/oswald-v49-latin-regular.svg#Oswald') format('svg'); /* Legacy iOS */ +} + +/* roboto-regular - latin */ +@font-face { + font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: url('../fonts/roboto-v30-latin-regular.eot'); /* IE9 Compat Modes */ + src: url('../fonts/roboto-v30-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/roboto-v30-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/roboto-v30-latin-regular.woff') format('woff'), /* Modern Browsers */ + url('../fonts/roboto-v30-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ + url('../fonts/roboto-v30-latin-regular.svg#Roboto') format('svg'); /* Legacy iOS */ +} diff --git a/jdav_web/static/startpage/css/people_grid.css b/jdav_web/static/startpage/css/people_grid.css new file mode 100644 index 0000000..faf762a --- /dev/null +++ b/jdav_web/static/startpage/css/people_grid.css @@ -0,0 +1,49 @@ +.grid-container { + display: grid; + grid-gap: 10px; + grid-template-columns: repeat(4, 1fr); + padding: 15px; +} + +.people .grid-item { + display: inline-grid; +} + +.portrait { + transition: transform .2s; + line-height: 1; +} + +.portrait img { + padding: 0; + margin: 0; + width: 100%; + max-height: 250px; + display: block; + object-fit: cover; +} + +.portrait .namebox { + background-color: rgba(87,171,39,1.0); + margin: 0; + padding: 15px; + text-align: center; + color: white; +} + +.portrait .namebox .name { + font-size: 16px; + text-align: center; + font-weight: 700; +} + +.portrait .namebox .extra { + margin-top: 5px; + font-size: 12px; + text-align: center; +} + +.portrait:hover { + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + transform: scale(1.02); +} diff --git a/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.eot b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.eot new file mode 100644 index 0000000..1ca824b Binary files /dev/null and b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.eot differ diff --git a/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.svg b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.svg new file mode 100644 index 0000000..7a25add --- /dev/null +++ b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.svg @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.ttf b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.ttf new file mode 100644 index 0000000..b5cb25d Binary files /dev/null and b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.ttf differ diff --git a/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.woff b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.woff new file mode 100644 index 0000000..aab7cdd Binary files /dev/null and b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.woff differ diff --git a/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.woff2 b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.woff2 new file mode 100644 index 0000000..7ef4f1d Binary files /dev/null and b/jdav_web/static/startpage/fonts/oswald-v49-latin-regular.woff2 differ diff --git a/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.eot b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.eot new file mode 100644 index 0000000..c244b08 Binary files /dev/null and b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.eot differ diff --git a/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.svg b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.svg new file mode 100644 index 0000000..627f5a3 --- /dev/null +++ b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.ttf b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.ttf new file mode 100644 index 0000000..d0e6325 Binary files /dev/null and b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.ttf differ diff --git a/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.woff b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.woff new file mode 100644 index 0000000..9eaa94f Binary files /dev/null and b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.woff differ diff --git a/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.woff2 b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.woff2 new file mode 100644 index 0000000..020729e Binary files /dev/null and b/jdav_web/static/startpage/fonts/roboto-v30-latin-regular.woff2 differ diff --git a/jdav_web/static/startpage/img/background.jpeg b/jdav_web/static/startpage/img/background.jpeg new file mode 100644 index 0000000..10be4e1 Binary files /dev/null and b/jdav_web/static/startpage/img/background.jpeg differ diff --git a/jdav_web/static/startpage/img/jdav_logo.png b/jdav_web/static/startpage/img/jdav_logo.png new file mode 100644 index 0000000..3fa59b7 Binary files /dev/null and b/jdav_web/static/startpage/img/jdav_logo.png differ diff --git a/jdav_web/static/startpage/img/placeholder.jpg b/jdav_web/static/startpage/img/placeholder.jpg new file mode 100644 index 0000000..8b29218 Binary files /dev/null and b/jdav_web/static/startpage/img/placeholder.jpg differ diff --git a/jdav_web/templates/general/base.html b/jdav_web/templates/general/base.html index 0c0c1ef..b5cbc95 100644 --- a/jdav_web/templates/general/base.html +++ b/jdav_web/templates/general/base.html @@ -1,43 +1 @@ -{% load i18n %} -{% load static %} - - - - - {% block title %} - {% endblock %} - - - - - - - - - - - - - -
- {% block content %} - {% endblock %} -
- - - - +{% extends "startpage/base_subsite.html" %}