1 Commits

Author SHA1 Message Date
90d7eea59e init crazy experiment 2022-10-04 16:16:25 +00:00
7 changed files with 792 additions and 81 deletions

View File

@@ -167,3 +167,31 @@ class PostSearchForm(forms.Form):
self.fields["year"].choices = year_choices self.fields["year"].choices = year_choices
except: except:
pass pass
class PostUpdateForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"title",
"image",
"body",
"is_pinned",
"status",
]
labels = {
"title": "Titel",
"image": "Hintergrundbild",
"body": "Text",
"is_pinned": "Event anheften",
}
widgets = {"body": CKEditorUploadingWidget(config_name="default")}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set

View File

@@ -138,7 +138,7 @@ class Post(models.Model):
) )
def get_absolute_url(self): def get_absolute_url(self):
return reverse("posts:show", kwargs={"id": self.slug}) return reverse("posts:show", kwargs={"slug": self.slug})
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# save the post with some defaults # save the post with some defaults

View File

@@ -10,7 +10,8 @@ urlpatterns = [
path("", views.index, name="index"), path("", views.index, name="index"),
# fet calendar (path have to be ahead show) # fet calendar (path have to be ahead show)
path("fet_calendar.ics", views.calendar, name="calendar"), path("fet_calendar.ics", views.calendar, name="calendar"),
path("<str:id>", views.show, name="show"), path("<slug:slug>", views.PostDetailView.as_view(), name="show"),
path("<slug:slug>/update", views.PostUpdateView.as_view(), name="post-update"),
re_path( re_path(
r"^(?P<id>[-\w]+)/agenda.pdf$", r"^(?P<id>[-\w]+)/agenda.pdf$",
views.show_pdf_agenda, views.show_pdf_agenda,

View File

@@ -1,15 +1,19 @@
import logging import logging
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.shortcuts import render from django.shortcuts import render
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils import timezone from django.utils import timezone
from django.views.generic.edit import UpdateView
from django.views.generic.detail import DetailView
from authentications.decorators import authenticated_user from authentications.decorators import authenticated_user
from documents.etherpadlib import add_ep_cookie from documents.etherpadlib import add_ep_cookie
from fet2020.utils import add_log_action
from members.models import Member from members.models import Member
from .forms import PostSearchForm from .forms import PostSearchForm, PostUpdateForm
from .models import Event, FileUpload, Post from .models import Event, FileUpload, Post
from .utils import render_to_pdf from .utils import render_to_pdf
@@ -103,41 +107,84 @@ def __get_post_object(id=None, public=True):
return post return post
def show(request, id=None): def post_next(post=None, public=True):
public_only = not request.user.is_authenticated """
post = __get_post_object(id, public_only) Helper function for getting next post
"""
posts = None
d = post.slug
# files if post:
files = FileUpload.objects.filter(post=post) posts = Post.objects.date_sorted_list(public).filter(post_type=post.post_type)
# author if posts:
author = None for k, v in enumerate(posts):
author_image = None if post.slug == v.slug:
post_author = Member.all_members.filter(username=post.author).first() if (k + 1) < len(posts):
if post_author: d = posts[k + 1].slug
author = post_author else:
author_image = post_author.image["avatar"].url d = posts[0].slug
break
related_posts = post.tags.similar_objects() return d
# list of non 'is_hidden' posts for related_posts
for obj in related_posts:
if not obj.published:
related_posts.remove(obj)
context = {
"post": post,
"files": files,
"author": author,
"author_image": author_image,
"next": __next(post, public_only),
"previous": __previous(post, public_only),
"related_posts": related_posts[:4],
}
response = render(request, "posts/show.html", context) def post_previous(post=None, public=True):
"""
Helper function for getting previous post
"""
posts = None
d = post.slug
if post:
posts = Post.objects.date_sorted_list(public).filter(post_type=post.post_type)
if posts:
for k, v in enumerate(posts):
if post.slug == v.slug:
if k < 1:
d = posts[len(posts) - 1].slug
else:
d = posts[k - 1].slug
break
return d
class PostUpdateView(LoginRequiredMixin, UpdateView):
model = Post
def form_valid(self, form):
add_log_action(self.request, form, "posts", "post", False)
return super().form_valid(form)
def get_form_class(self):
form_class = PostUpdateForm
if self.object.post_type == "E":
form_class = PostUpdateForm
elif self.object.post_type == "F":
form_class = PostUpdateForm
return form_class
def get_template_names(self):
template_name = "posts/news_update.html"
if self.object.post_type == "E":
template_name = "posts/news_update.html"
elif self.object.post_type == "F":
template_name = "posts/news_update.html"
return template_name
class PostDetailView(DetailView):
model = Post
def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs)
# check if etherpad server works # check if etherpad server works
if post.agenda_link or post.protocol_link: if self.post.agenda_link or self.post.protocol_link:
try: try:
response = add_ep_cookie(request, response) response = add_ep_cookie(request, response)
except Exception as e: except Exception as e:
@@ -145,6 +192,54 @@ def show(request, id=None):
return response return response
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
public_only = not self.request.user.is_authenticated
self.post = self.object
# files
files = FileUpload.objects.filter(post=self.post)
# author
author = None
author_image = None
post_author = Member.all_members.filter(username=self.post.author).first()
if post_author:
author = post_author
author_image = post_author.image["avatar"].url
related_posts = self.post.tags.similar_objects()
# list of non 'is_hidden' posts for related_posts
for obj in related_posts:
if not obj.published:
related_posts.remove(obj)
context = {
"post": self.post,
"files": files,
"author": author,
"author_image": author_image,
"next": post_next(self.post, public_only),
"previous": post_previous(self.post, public_only),
"related_posts": related_posts[:4],
}
return context
def get_queryset(self):
public_only = not self.request.user.is_authenticated
return Post.objects.published(public_only)
def get_template_names(self):
template_name = "posts/show.html"
if self.post.post_type == "E":
template_name = "posts/event_detail.html"
elif self.post.post_type == "F":
template_name = "posts/fet_meeting_detail.html"
return template_name
def show_pdf(request, html, filename): def show_pdf(request, html, filename):
rendered = render_to_string( rendered = render_to_string(
@@ -185,47 +280,3 @@ def show_pdf_protocol(request, id):
html = post.protocol_html html = post.protocol_html
return show_pdf(request, html, post.slug + "-protokoll") return show_pdf(request, html, post.slug + "-protokoll")
def __next(post=None, public=True):
"""
Helper function for getting next post
"""
posts = None
d = post.slug
if post:
posts = Post.objects.date_sorted_list(public).filter(post_type=post.post_type)
if posts:
for k, v in enumerate(posts):
if post.slug == v.slug:
if (k + 1) < len(posts):
d = posts[k + 1].slug
else:
d = posts[0].slug
break
return d
def __previous(post=None, public=True):
"""
Helper function for getting previous post
"""
posts = None
d = post.slug
if post:
posts = Post.objects.date_sorted_list(public).filter(post_type=post.post_type)
if posts:
for k, v in enumerate(posts):
if post.slug == v.slug:
if k < 1:
d = posts[len(posts) - 1].slug
else:
d = posts[k - 1].slug
break
return d

View File

@@ -0,0 +1,229 @@
{% extends 'base.html' %}
{% load flatpages %}
{% load post_helpers %}
{% block title %}{{ post.title }}{% endblock %}
{% block extraheader %}
<meta content="{{ post.imageurl }}" property="og:image">
<meta content="{{ post.title }}" property="og:title">
<meta content="article" property="og:type">
<meta content="" property="og:url">
{% endblock %}
{% block content %}
<!-- Main Content -->
<main class="container mx-auto w-full flex-1 my-8 sm:flex flex-col sm:px-4">
<a href="{% url 'posts:show' previous %}" class="hidden z-20 fixed left-0 top-1/2 -mt-8 p-2 xl:flex items-center text-gray-400 dark:text-gray-300 rounded-md"
x-data="{ showPrevArticleButton : false }"
@mouseleave="showPrevArticleButton = false"
@mouseover="showPrevArticleButton = true"
>
<i class="fa-solid fa-chevron-left text-5xl -m-2 p-2 bg-gray-100 dark:bg-gray-700 rounded-md"></i>
<span class="text-gray-600 dark:text-gray-300 font-medium bg-gray-100 dark:bg-gray-700 -m-2 p-2 rounded-r-md origin-left"
x-show="showPrevArticleButton"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 bg-opacity-0 transform scale-90"
x-transition:enter-end="opacity-100 transform scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 transform scale-100"
x-transition:leave-end="opacity-0 bg-opacity-0 transform scale-100"
>Vorheriges<br>Event</span>
</a>
<a href="{% url 'posts:show' next %}" class="hidden z-20 fixed right-0 top-1/2 -mt-8 p-2 xl:flex items-center text-gray-400 dark:text-gray-300 rounded-md"
x-data="{ showNextArticleButton : false }"
@mouseleave="showNextArticleButton = false"
@mouseover="showNextArticleButton = true"
>
<span class="z-30 text-gray-600 dark:text-gray-300 font-medium bg-gray-100 dark:bg-gray-700 -m-2 p-2 rounded-l-md text-right origin-right"
x-show="showNextArticleButton"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 bg-opacity-0 transform scale-90"
x-transition:enter-end="opacity-100 transform scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 transform scale-100"
x-transition:leave-end="opacity-0 bg-opacity-0 transform scale-100"
>Nächstes<br>Event</span>
<i class="fa-solid fa-chevron-right text-5xl -m-2 p-2 bg-gray-100 dark:bg-gray-700 rounded-md"></i>
</a>
<section>
<div class="mb-4 flex flex-col sm:flex-col gap-2 mx-auto">
<ul class="px-4 sm:px-0 mb-2 flex flex-row justify-center gap-2 sm:gap-4 flex-wrap text-sky-700 dark:text-blue-200 text-sm uppercase tracking-wide sm:font-medium">
{% for t in post.tag_names %}
<li class="inline-block py-1 px-2 bg-sky-100 dark:bg-sky-900 rounded-full"><a href="{% url 'posts:tags' t %}">#{{ t }}</a></li>
{% endfor %}
</ul>
<h1 class="px-4 sm:px-0 text-lg sm:text-xl lg:text-3xl text-center sm:text-left font-medium text-gray-900 dark:text-gray-100 font-serif tracking-wider leading-normal" style="line-height: 1.5;">{{ post.title|tags_to_url }}</h1>
<div class="mx-auto max-w-max sm:mx-0 sm:max-w-none sm:flex justify-between items-center">
<div class="max-w-max flex flex-row justify-center sm:justify-start gap-2 self-center md:self-start">
{% if author_image and author %}
<img class="hidden sm:block w-12 rounded-full" src="{{ author_image }}" alt="Portraitfoto von {{ author.firstname }}">
<div class="sm:flex flex-col justify-evenly text-gray-600 dark:text-gray-300 text-sm sm:text-base">
<a href="{% url 'member' author.id %}" class="underline">{{ author.firstname }}</a>
<span class="sm:hidden"> am </span>
<span>{{ post.date|date:"d. F Y" }}</span>
</div>
{% elif post.author %}
<div class="sm:flex flex-col justify-evenly text-gray-600 dark:text-gray-300 text-sm sm:text-base">
<a class="underline">{{ post.author|capfirst }}</a>
<span class="sm:hidden"> am </span>
<span>{{ post.date|date:"d. F Y" }}</span>
</div>
{% else %}
<div class="sm:flex flex-col justify-evenly text-gray-600 dark:text-gray-300 text-sm sm:text-base">
<a class="underline">fet.at Redaktion</a>
<span class="sm:hidden"> am </span>
<span>{{ post.date|date:"d. F Y" }}</span>
</div>
{% endif %}
</div>
{% if request.user.is_authenticated %}
<a href="{% url 'admin:posts_event_change' post.id %}" class="hidden sm:block btn-small btn-primary">
<i class="fa-solid fa-pen-to-square mr-1"></i>Event bearbeiten
</a>
{% endif %}
</div>
</div>
<!-- <img src="img/article-cover-3.jpg" alt="" class="h-44 sm:h-56 lg:h-64 xl:h-80 w-full object-cover sm:rounded-md max-w-5xl mx-auto"> -->
<div class="relative w-full h-44 sm:h-56 md:h-60 lg:h-64 xl:h-96 bg-center bg-no-repeat bg-cover sm:rounded-md mx-auto" style="background-image: url('{{ post.imageurl }}');">
<div class="hidden lg:block absolute top-0 right-0 bg-white dark:bg-gray-900 rounded-bl p-2 bg-opacity-80 dark:bg-opacity-70 gap-2">
<div class="items-center lg:flex gap-2">
<i class="flex-none fa-solid fa-calendar-clock fa-fw text-gray-800 dark:text-gray-200"></i>
<span class="flex-1 text-sm text-gray-800 dark:text-gray-200">
Event-Start: {{ post.event_start|date }} um {{ post.event_start|time }} Uhr<br>
Event-Ende: {{ post.event_end|date }} um {{ post.event_end|time }} Uhr
</span>
</div>
{% if post.event_place %}
<div class="items-center lg:flex gap-2">
<i class="flex-none fa-solid fa-location-dot fa-fw text-gray-800 dark:text-gray-200"></i>
<span class="flex-1 text-sm text-gray-800 dark:text-gray-200">
Event-Ort: {{ post.event_place }}
</span>
</div>
{% endif %}
</div>
<div class="hidden absolute top-0 right-0 bg-white dark:bg-gray-900 rounded-bl p-2 bg-opacity-80 dark:bg-opacity-70 items-center gap-2">
<i class="flex-none fa-solid fa-calendar-clock text-gray-800 dark:text-gray-200"></i>
<span class="flex-1 text-sm text-gray-800 dark:text-gray-200">
Event-Start: {{ post.event_start|date }} um {{ post.event_start|time }} Uhr<br>
Event-Ende: {{ post.event_end|date }} um {{ post.event_end|time }} Uhr<br>
{% if post.event_place %}
Event-Ort: {{ post.event_place }}
{% endif %}
</span>
</div>
</div>
</section>
<section class="mx-4 z-10">
<article class="p-4 mt-4 sm:-mt-16 xl:-mt-24 w-full max-w-prose mx-auto bg-white dark:bg-gray-900 rounded dark:border-2 dark:border-gray-800">
<!-- <div class="w-full flex justify-end">
<div class="hidden lg:block max-w-max text-sm text-gray-600">
Event-Start: 23. August 2021 um 18:00 Uhr<br>
Event-Ende: 23. August 2021 um 20:00 Uhr
</div>
</div> -->
<div class="db-page-content-left big-first-letter">
<!-- Content from DB here: -->
{{ post.body|safe|tags_to_url }}
</div>
<hr class="lg:hidden -mx-4 border-gray-200 dark:border-gray-800 dark:border my-4">
<div class="lg:hidden">
<h2 class="text-gray-800 dark:text-gray-200 font-medium"><i class="fa-solid fa-calendar-days mr-2 text-gray-400 dark:text-gray-500"></i>Termindetails:</h2>
<ul class="text-base text-gray-700 dark:text-gray-300 my-1">
<li>Start: {{ post.event_start|date }} um {{ post.event_start|time }} Uhr</li>
<li>Ende: {{ post.event_end|date }} um {{ post.event_end|time }} Uhr</li>
{% if post.event_place %}
<li>Ort: {{ post.event_place }}</li>
{% endif %}
</ul>
</div>
{% if files %}
<hr class="-mx-4 border-gray-200 dark:border-gray-800 dark:border my-4">
<h2 class="text-gray-800 dark:text-gray-200 font-medium"><i class="fa-solid fa-inbox mr-2 text-gray-400 dark:text-gray-500"></i>Dokument(e):</h2>
{% endif %}
{% for file in files %}
<div class="w-full my-2 flex items-center gap-4 text-gray-700 dark:text-gray-300" x-data="{ showOptions: false }">
<span class="flex-1">{{ file.title }}</span>
<div class="relative">
<button class="sm:hidden px-2 py-1 border border-gray-300 dark:border-gray-700 rounded" @click="showOptions = true">
<i class="fa-solid fa-ellipsis-vertical fa-fw"></i>
</button>
<ul class="z-10 absolute top-0 right-0 sm:flex flex-row sm:static flex-none border dark:border-2 border-gray-300 dark:border-gray-700 rounded divide-y-2 sm:divide-y-0 sm:divide-x divide-gray-300 dark:divide-gray-700 bg-gray-100 dark:bg-gray-800 shadow sm:bg-transparent sm:shadow-none"
@click.outside="showOptions = false"
x-show="showOptions || $screen('sm')"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="transform origin-right opacity-0 scale-95"
x-transition:enter-end="transform origin-right opacity-100 scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="transform origin-right opacity-100 scale-100"
x-transition:leave-end="transform origin-right opacity-0 scale-95"
>
<li class="block sm:inline-block group hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-gray-200">
<a href="{{ file.file_field.url }}" class="inline-flex items-center px-2 py-1" target="_blank">
<i class="fa-solid fa-file-pdf fa-fw text-red-800 dark:text-red-500 md:text-inherit group-hover:text-red-800 dark:group-hover:text-red-500"></i>
<span class="ml-2 sm:ml-1">Download</span>
</a>
</li>
</ul>
</div>
</div>
{% endfor %}
<hr class="-mx-4 border-gray-200 dark:border-gray-800 dark:border my-4">
<div class="-m-4 flex divide-x divide-gray-200 dark:divide-gray-800 dark:divide-x-2 text-sm sm:text-base">
<a href="{% url 'posts:show' previous %}" class="w-1/2 p-4 flex items-center gap-2">
<i class="fa-solid fa-chevron-left text-gray-600 dark:text-gray-400"></i>
<span class="text-gray-700 dark:text-gray-300 font-medium">Vorheriges Event</span>
</a>
<a href="{% url 'posts:show' next %}" class="w-1/2 p-4 flex flex-row-reverse items-center gap-2">
<i class="fa-solid fa-chevron-right text-gray-600 dark:text-gray-400"></i>
<span class="text-gray-700 dark:text-gray-300 font-medium">Nächstes Event</span>
</a>
</div>
</article>
{% if request.user.is_authenticated %}
<a href="{% url 'admin:posts_event_change' post.id %}" class="sm:hidden block w-full btn btn-primary mt-4">
<i class="fa-solid fa-pen-to-square mr-1"></i>Event bearbeiten
</a>
{% endif %}
</section>
{% if related_posts %}
<section class="mx-auto w-full px-4">
<h2 class="my-4 sm:my-8 text-proprietary dark:text-proprietary-lighter text-xl text-center uppercase tracking-wider">Weiterlesen</h2>
<div class="flex justify-evenly flex-wrap gap-4">
{% for post in related_posts %}
{% if forloop.counter0 == 2 %}
<a href="{{ post.get_absolute_url }}" class="w-full sm:w-auto sm:flex-1 hidden lg:block rounded-md bg-white dark:bg-gray-500 shadow-md bg-no-repeat bg-center aspect-video transition-all ease-in-out duration-500 bg-scale-100 hover:bg-scale-120" style="background-image: url('{{ post.imageurl }}');">
{% include 'posts/partials/_posts_related.html' %}
</a>
{% elif forloop.last %}
<a href="{{ post.get_absolute_url }}" class="w-full sm:w-auto sm:flex-1 hidden 2xl:block rounded-md bg-white dark:bg-gray-500 shadow-md bg-no-repeat bg-center aspect-video transition-all ease-in-out duration-500 bg-scale-100 hover:bg-scale-120" style="background-image: url('{{ post.imageurl }}');">
{% include 'posts/partials/_posts_related.html' %}
</a>
{% else %}
<a href="{{ post.get_absolute_url }}" class="w-full sm:w-auto sm:flex-1 block rounded-md bg-white dark:bg-gray-500 shadow-md bg-no-repeat bg-center aspect-video transition-all ease-in-out duration-500 bg-scale-100 hover:bg-scale-120" style="background-image: url('{{ post.imageurl }}');">
{% include 'posts/partials/_posts_related.html' %}
</a>
{% endif %}
{% endfor %}
</div>
</section>
{% endif %}
</main>
{% endblock %}

View File

@@ -0,0 +1,315 @@
{% extends 'base.html' %}
{% load flatpages %}
{% load post_helpers %}
{% block title %}{{ post.title }}{% endblock %}
{% block extraheader %}
<meta content="{{ post.imageurl }}" property="og:image">
<meta content="{{ post.title }}" property="og:title">
<meta content="article" property="og:type">
<meta content="" property="og:url">
{% endblock %}
{% block content %}
<!-- Main Content -->
<main class="container mx-auto w-full flex-1 my-8 sm:flex flex-col sm:px-4">
<a href="{% url 'posts:show' previous %}" class="hidden z-20 fixed left-0 top-1/2 -mt-8 p-2 xl:flex items-center text-gray-400 dark:text-gray-300 rounded-md"
x-data="{ showPrevArticleButton : false }"
@mouseleave="showPrevArticleButton = false"
@mouseover="showPrevArticleButton = true"
>
<i class="fa-solid fa-chevron-left text-5xl -m-2 p-2 bg-gray-100 dark:bg-gray-700 rounded-md"></i>
<span class="text-gray-600 dark:text-gray-300 font-medium bg-gray-100 dark:bg-gray-700 -m-2 p-2 rounded-r-md origin-left"
x-show="showPrevArticleButton"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 bg-opacity-0 transform scale-90"
x-transition:enter-end="opacity-100 transform scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 transform scale-100"
x-transition:leave-end="opacity-0 bg-opacity-0 transform scale-100"
>Vorherige<br>Fachschaftssitzung</span>
</a>
<a href="{% url 'posts:show' next %}" class="hidden z-20 fixed right-0 top-1/2 -mt-8 p-2 xl:flex items-center text-gray-400 dark:text-gray-300 rounded-md"
x-data="{ showNextArticleButton : false }"
@mouseleave="showNextArticleButton = false"
@mouseover="showNextArticleButton = true"
>
<span class="z-30 text-gray-600 dark:text-gray-300 font-medium bg-gray-100 dark:bg-gray-700 -m-2 p-2 rounded-l-md text-right origin-right"
x-show="showNextArticleButton"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 bg-opacity-0 transform scale-90"
x-transition:enter-end="opacity-100 transform scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 transform scale-100"
x-transition:leave-end="opacity-0 bg-opacity-0 transform scale-100"
>Nächste<br>Fachschaftssitzung</span>
<i class="fa-solid fa-chevron-right text-5xl -m-2 p-2 bg-gray-100 dark:bg-gray-700 rounded-md"></i>
</a>
<section>
<div class="mb-4 flex flex-col sm:flex-col gap-2 mx-auto">
<ul class="px-4 sm:px-0 mb-2 flex flex-row justify-center gap-2 sm:gap-4 flex-wrap text-sky-700 dark:text-blue-200 text-sm uppercase tracking-wide sm:font-medium">
{% for t in post.tag_names %}
<li class="inline-block py-1 px-2 bg-sky-100 dark:bg-sky-900 rounded-full"><a href="{% url 'posts:tags' t %}">#{{ t }}</a></li>
{% endfor %}
</ul>
<h1 class="px-4 sm:px-0 text-lg sm:text-xl lg:text-3xl text-center sm:text-left font-medium text-gray-900 dark:text-gray-100 font-serif tracking-wider leading-normal" style="line-height: 1.5;">{{ post.title|tags_to_url }}</h1>
<div class="mx-auto max-w-max sm:mx-0 sm:max-w-none sm:flex justify-between items-center">
<div class="max-w-max flex flex-row justify-center sm:justify-start gap-2 self-center md:self-start">
{% if author_image and author %}
<img class="hidden sm:block w-12 rounded-full" src="{{ author_image }}" alt="Portraitfoto von {{ author.firstname }}">
<div class="sm:flex flex-col justify-evenly text-gray-600 dark:text-gray-300 text-sm sm:text-base">
<a href="{% url 'member' author.id %}" class="underline">{{ author.firstname }}</a>
<span class="sm:hidden"> am </span>
<span>{{ post.date|date:"d. F Y" }}</span>
</div>
{% elif post.author %}
<div class="sm:flex flex-col justify-evenly text-gray-600 dark:text-gray-300 text-sm sm:text-base">
<a class="underline">{{ post.author|capfirst }}</a>
<span class="sm:hidden"> am </span>
<span>{{ post.date|date:"d. F Y" }}</span>
</div>
{% else %}
<div class="sm:flex flex-col justify-evenly text-gray-600 dark:text-gray-300 text-sm sm:text-base">
<a class="underline">fet.at Redaktion</a>
<span class="sm:hidden"> am </span>
<span>{{ post.date|date:"d. F Y" }}</span>
</div>
{% endif %}
</div>
{% if request.user.is_authenticated %}
<a href="{% url 'admin:posts_fetmeeting_change' post.id %}" class="hidden sm:block btn-small btn-primary">
<i class="fa-solid fa-pen-to-square mr-1"></i>Fachschaftssitzung bearbeiten
</a>
{% endif %}
</div>
</div>
<!-- <img src="img/article-cover-3.jpg" alt="" class="h-44 sm:h-56 lg:h-64 xl:h-80 w-full object-cover sm:rounded-md max-w-5xl mx-auto"> -->
<div class="relative w-full h-44 sm:h-56 md:h-60 lg:h-64 xl:h-96 bg-center bg-no-repeat bg-cover sm:rounded-md mx-auto" style="background-image: url('{{ post.imageurl }}');">
<div class="hidden lg:block absolute top-0 right-0 bg-white dark:bg-gray-900 rounded-bl p-2 bg-opacity-80 dark:bg-opacity-70 gap-2">
<div class="items-center lg:flex gap-2">
<i class="flex-none fa-solid fa-calendar-clock fa-fw text-gray-800 dark:text-gray-200"></i>
<span class="flex-1 text-sm text-gray-800 dark:text-gray-200">
Event-Start: {{ post.event_start|date }} um {{ post.event_start|time }} Uhr<br>
Event-Ende: {{ post.event_end|date }} um {{ post.event_end|time }} Uhr
</span>
</div>
{% if post.event_place %}
<div class="items-center lg:flex gap-2">
<i class="flex-none fa-solid fa-location-dot fa-fw text-gray-800 dark:text-gray-200"></i>
<span class="flex-1 text-sm text-gray-800 dark:text-gray-200">
Event-Ort: {{ post.event_place }}
</span>
</div>
{% endif %}
</div>
<div class="hidden absolute top-0 right-0 bg-white dark:bg-gray-900 rounded-bl p-2 bg-opacity-80 dark:bg-opacity-70 items-center gap-2">
<i class="flex-none fa-solid fa-calendar-clock text-gray-800 dark:text-gray-200"></i>
<span class="flex-1 text-sm text-gray-800 dark:text-gray-200">
Event-Start: {{ post.event_start|date }} um {{ post.event_start|time }} Uhr<br>
Event-Ende: {{ post.event_end|date }} um {{ post.event_end|time }} Uhr<br>
{% if post.event_place %}
Event-Ort: {{ post.event_place }}
{% endif %}
</span>
</div>
</div>
</section>
<section class="mx-4 z-10">
<article class="p-4 mt-4 sm:-mt-16 xl:-mt-24 w-full max-w-prose mx-auto bg-white dark:bg-gray-900 rounded dark:border-2 dark:border-gray-800">
<!-- <div class="w-full flex justify-end">
<div class="hidden lg:block max-w-max text-sm text-gray-600">
Event-Start: 23. August 2021 um 18:00 Uhr<br>
Event-Ende: 23. August 2021 um 20:00 Uhr
</div>
</div> -->
<div class="db-page-content-left big-first-letter">
<!-- Content from DB here: -->
{% if post.has_agenda %}
<h2>Agenda</h2>
{{ post.agenda_html|safe }}
{% endif %}
{% if request.user.is_authenticated and post.has_protocol %}
<hr>
<h2>Protokoll</h2>
{{ post.protocol_html|safe }}
{% endif %}
</div>
<hr class="lg:hidden -mx-4 border-gray-200 dark:border-gray-800 dark:border my-4">
<div class="lg:hidden">
<h2 class="text-gray-800 dark:text-gray-200 font-medium"><i class="fa-solid fa-calendar-days mr-2 text-gray-400 dark:text-gray-500"></i>Termindetails:</h2>
<ul class="text-base text-gray-700 dark:text-gray-300 my-1">
<li>Start: {{ post.event_start|date }} um {{ post.event_start|time }} Uhr</li>
<li>Ende: {{ post.event_end|date }} um {{ post.event_end|time }} Uhr</li>
{% if post.event_place %}
<li>Ort: {{ post.event_place }}</li>
{% endif %}
</ul>
</div>
{% if post.has_agenda or post.has_protocol %}
{% if request.user.is_authenticated %}
<hr class="-mx-4 border-gray-200 dark:border-gray-800 dark:border my-4">
<h2 class="text-gray-800 dark:text-gray-200 font-medium"><i class="fa-solid fa-inbox mr-2 text-gray-400 dark:text-gray-500"></i>Dokument(e):</h2>
{% endif %}
{% endif %}
{% if request.user.is_authenticated %}
{% if post.has_agenda %}
<div class="w-full my-2 flex items-center gap-4 text-gray-700 dark:text-gray-300" x-data="{ showOptions: false }">
<span class="flex-1">Agenda</span>
<div class="relative">
<button class="sm:hidden px-2 py-1 border border-gray-300 dark:border-gray-700 rounded" @click="showOptions = true">
<i class="fa-solid fa-ellipsis-vertical fa-fw"></i>
</button>
<ul class="z-10 absolute top-0 right-0 sm:flex flex-row sm:static flex-none border dark:border-2 border-gray-300 dark:border-gray-700 rounded divide-y-2 sm:divide-y-0 sm:divide-x divide-gray-300 dark:divide-gray-700 bg-gray-100 dark:bg-gray-800 shadow sm:bg-transparent sm:shadow-none"
@click.outside="showOptions = false"
x-show="showOptions || $screen('sm')"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="transform origin-right opacity-0 scale-95"
x-transition:enter-end="transform origin-right opacity-100 scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="transform origin-right opacity-100 scale-100"
x-transition:leave-end="transform origin-right opacity-0 scale-95"
>
<li class="block sm:inline-block group hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-gray-200">
<a href="{{ post.agenda_link }}" class="inline-flex items-center px-2 py-1">
<i class="fa-solid fa-file-signature fa-fw text-proprietary dark:text-proprietary-light md:text-inherit group-hover:text-proprietary dark:group-hover:text-proprietary-light"></i>
<span class="ml-2 sm:ml-1">Bearbeiten</span>
</a>
</li>
{% if post.filename_agenda %}
<li class="block sm:inline-block group hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-gray-200">
<a href="{% url 'posts:show_pdf_agenda' post.slug %}" class="inline-flex items-center px-2 py-1">
<i class="fa-solid fa-file-pdf fa-fw text-red-800 dark:text-red-500 md:text-inherit group-hover:text-red-800 dark:group-hover:text-red-500"></i>
<span class="ml-2 sm:ml-1">Download</span>
</a>
</li>
{% endif %}
</ul>
</div>
</div>
{% endif %}
{% if post.has_protocol %}
<div class="w-full my-2 flex items-center gap-4 text-gray-700 dark:text-gray-300" x-data="{ showOptions: false }">
<span class="flex-1">Protokoll</span>
<div class="relative">
<button class="sm:hidden px-2 py-1 border border-gray-300 dark:border-gray-700 rounded" @click="showOptions = true">
<i class="fa-solid fa-ellipsis-vertical fa-fw"></i>
</button>
<ul class="z-10 absolute top-0 right-0 sm:flex flex-row sm:static flex-none border dark:border-2 border-gray-300 dark:border-gray-700 rounded divide-y-2 sm:divide-y-0 sm:divide-x divide-gray-300 dark:divide-gray-700 bg-gray-100 dark:bg-gray-800 shadow sm:bg-transparent sm:shadow-none"
@click.outside="showOptions = false"
x-show="showOptions || $screen('sm')"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="transform origin-right opacity-0 scale-95"
x-transition:enter-end="transform origin-right opacity-100 scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="transform origin-right opacity-100 scale-100"
x-transition:leave-end="transform origin-right opacity-0 scale-95"
>
<li class="block sm:inline-block group hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-gray-200">
<a href="{{ post.protocol_link }}" class="inline-flex items-center px-2 py-1"><i class="fa-solid fa-file-signature fa-fw text-proprietary dark:text-proprietary-light md:text-inherit group-hover:text-proprietary dark:group-hover:text-proprietary-light"></i>
<span class="ml-2 sm:ml-1">Bearbeiten</span>
</a>
</li>
{% if post.filename_protocol %}
<li class="block sm:inline-block group hover:bg-gray-200 dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-gray-200">
<a href="{% url 'posts:show_pdf_protocol' post.slug %}" class="inline-flex items-center px-2 py-1">
<i class="fa-solid fa-file-pdf fa-fw text-red-800 dark:text-red-500 md:text-inherit group-hover:text-red-800 dark:group-hover:text-red-500"></i>
<span class="ml-2 sm:ml-1">Download</span>
</a>
</li>
{% endif %}
</ul>
</div>
</div>
{% endif %}
{% get_flatpages '/bs/' for user as pages %}
{% if pages %}
<div class="w-full my-2 flex items-center gap-4 text-gray-700 dark:text-gray-300" x-data="{ showOptions: false }">
<span class="flex-1">{{ pages.first.title }}</span>
<div class="relative">
<button class="sm:hidden px-2 py-1 border border-gray-300 dark:border-gray-700 rounded" @click="showOptions = true">
<i class="fa-solid fa-ellipsis-vertical fa-fw"></i>
</button>
<ul class="z-10 absolute top-0 right-0 sm:flex flex-row sm:static flex-none border dark:border-2 border-gray-300 dark:border-gray-700 rounded divide-y-2 sm:divide-y-0 sm:divide-x divide-gray-300 dark:divide-gray-700 bg-gray-100 dark:bg-gray-800 shadow sm:bg-transparent sm:shadow-none"
@click.outside="showOptions = false"
x-show="showOptions || $screen('sm')"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="transform origin-right opacity-0 scale-95"
x-transition:enter-end="transform origin-right opacity-100 scale-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="transform origin-right opacity-100 scale-100"
x-transition:leave-end="transform origin-right opacity-0 scale-95"
>
<li class="block sm:inline-block group hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-800 dark:hover:text-gray-200">
<a href="{{ pages.first.url }}" class="inline-flex items-center px-2 py-1"><i class="fa-solid fa-file-lines fa-fw text-proprietary dark:text-proprietary-light md:text-inherit group-hover:text-proprietary dark:group-hover:text-proprietary-light"></i>
<span class="ml-2 sm:ml-1">Übersicht</span>
</a>
</li>
</ul>
</div>
</div>
{% endif %}
{% endif %}
<hr class="-mx-4 border-gray-200 dark:border-gray-800 dark:border my-4">
<div class="-m-4 flex divide-x divide-gray-200 dark:divide-gray-800 dark:divide-x-2 text-sm sm:text-base">
<a href="{% url 'posts:show' previous %}" class="w-1/2 p-4 flex items-center gap-2">
<i class="fa-solid fa-chevron-left text-gray-600 dark:text-gray-400"></i>
<span class="text-gray-700 dark:text-gray-300 font-medium">Vorherige Fachschaftssitzung</span>
</a>
<a href="{% url 'posts:show' next %}" class="w-1/2 p-4 flex flex-row-reverse items-center gap-2">
<i class="fa-solid fa-chevron-right text-gray-600 dark:text-gray-400"></i>
<span class="text-gray-700 dark:text-gray-300 font-medium">Nächste Fachschaftssitzung</span>
</a>
</div>
</article>
{% if request.user.is_authenticated %}
<a href="{% url 'admin:posts_fetmeeting_change' post.id %}" class="sm:hidden block w-full btn btn-primary mt-4">
<i class="fa-solid fa-pen-to-square mr-1"></i>Fachschaftssitzung bearbeiten
</a>
{% endif %}
</section>
{% if related_posts %}
<section class="mx-auto w-full px-4">
<h2 class="my-4 sm:my-8 text-proprietary dark:text-proprietary-lighter text-xl text-center uppercase tracking-wider">Weiterlesen</h2>
<div class="flex justify-evenly flex-wrap gap-4">
{% for post in related_posts %}
{% if forloop.counter0 == 2 %}
<a href="{{ post.get_absolute_url }}" class="w-full sm:w-auto sm:flex-1 hidden lg:block rounded-md bg-white dark:bg-gray-500 shadow-md bg-no-repeat bg-center aspect-video transition-all ease-in-out duration-500 bg-scale-100 hover:bg-scale-120" style="background-image: url('{{ post.imageurl }}');">
{% include 'posts/partials/_posts_related.html' %}
</a>
{% elif forloop.last %}
<a href="{{ post.get_absolute_url }}" class="w-full sm:w-auto sm:flex-1 hidden 2xl:block rounded-md bg-white dark:bg-gray-500 shadow-md bg-no-repeat bg-center aspect-video transition-all ease-in-out duration-500 bg-scale-100 hover:bg-scale-120" style="background-image: url('{{ post.imageurl }}');">
{% include 'posts/partials/_posts_related.html' %}
</a>
{% else %}
<a href="{{ post.get_absolute_url }}" class="w-full sm:w-auto sm:flex-1 block rounded-md bg-white dark:bg-gray-500 shadow-md bg-no-repeat bg-center aspect-video transition-all ease-in-out duration-500 bg-scale-100 hover:bg-scale-120" style="background-image: url('{{ post.imageurl }}');">
{% include 'posts/partials/_posts_related.html' %}
</a>
{% endif %}
{% endfor %}
</div>
</section>
{% endif %}
</main>
{% endblock %}

View File

@@ -0,0 +1,87 @@
{% extends 'base.html' %}
{% block title %}{{ object.title }} bearbeiten{% endblock %}
{% block content %}
<!-- Main Content -->
<main class="container mx-auto w-full px-4 my-8 flex-1">
<h1 class="page-title">News '{{ object.title }}' bearbeiten</h1>
<div class="w-full h-full flex-1 flex justify-center items-center">
<form action="" method="POST" class="w-full max-w-prose sm:px-28 sm:py-4 grid grid-cols-1 gap-y-3 sm:gap-y-6 text-gray-900">
{% csrf_token %}
{% if form.non_field_errors %}
<div class="alert alert-danger">
<i class="alert-icon fa-solid fa-check-circle"></i>
<h2 class="alert-title">Fehler:</h2>
<div class="alert-body">{{ form.non_field_errors }}</div>
</div>
{% endif %}
<label>
<span class="text-gray-700 dark:text-gray-200">{{ form.assigned_to.label }}</span>
{% if form.assigned_to.errors %}
<div class="alert alert-danger">
<div class="alert-body">{{ form.assigned_to.errors }}</div>
</div>
{% endif %}
<select id="id_assigned_to" name="assigned_to" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
{% for elem in form.assigned_to %}
{% if forloop.first %}
<option value="">Alle</option>
{% else %}
{{ elem }}
{% endif %}
{% endfor %}
</select>
</label>
<label>
<span class="text-gray-700 dark:text-gray-200">{{ form.due_date.label }}</span>
{% if form.due_date.errors %}
<div class="alert alert-danger">
<div class="alert-body">{{ form.due_date.errors }}</div>
</div>
{% endif %}
<input type="date" id="id_due_date" name="due_date" value="{{ task.due_date|date:"Y-m-d" }}" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
</label>
<label>
<span class="text-gray-700 dark:text-gray-200">{{ form.completed_date.label }}</span>
{% if form.completed_date.errors %}
<div class="alert alert-danger">
<div class="alert-body">{{ form.completed_date.errors }}</div>
</div>
{% endif %}
<input type="date" id="id_completed_date" name="completed_date" value="{{ task.completed_date|date:"Y-m-d" }}" class="block w-full mt-1 rounded-md border-gray-300 dark:border-none shadow-sm focus:border-none focus:ring focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
</label>
<label>
<input type="checkbox" id="id_completed" name="completed" value="{{ task.id }}" {% if task.completed %}checked{% endif %} class="rounded border-gray-300 dark:border-none text-proprietary shadow-sm focus:border-blue-300 focus:ring focus:ring-offset-0 focus:ring-blue-200 dark:focus:ring-sky-700 focus:ring-opacity-50">
<span class="text-gray-700 dark:text-gray-200">{{ form.completed.label }}</span>
{% if form.completed.errors %}
<div class="alert alert-danger">
<div class="alert-body">{{ form.completed.errors }}</div>
</div>
{% endif %}
</label>
<label class="block">
<span class="text-gray-700 dark:text-gray-200">{{ form.note.label }}</span>
{% if form.note.errors %}
<div class="alert alert-danger">
<div class="alert-body">{{ form.note.errors }}</div>
</div>
{% endif %}
{{ form.media }}
{{ form.note }}
</label>
<div class="flex flex-col-reverse sm:flex-row gap-3 justify-end pt-4 sm:pt-0">
<a href="{% url 'admin:posts_news_change' object.id %}" class="block btn btn-secondary-proprietary">News im Admin bearbeiten</a>
<input type="submit" class="block btn btn-primary" value="Bearbeiten">
</div>
</form>
</div>
</main>
{% endblock %}