feat: add announcements
This commit is contained in:
parent
8295716f07
commit
e5a5fd5a10
@ -5,7 +5,7 @@ from django.utils.html import format_html
|
|||||||
from .models import User, Language, Text, ReportComment, ReportAdoptionNotice
|
from .models import User, Language, Text, ReportComment, ReportAdoptionNotice
|
||||||
|
|
||||||
from .models import Animal, Species, RescueOrganization, AdoptionNotice, Location, Rule, Image, ModerationAction, \
|
from .models import Animal, Species, RescueOrganization, AdoptionNotice, Location, Rule, Image, ModerationAction, \
|
||||||
Member, Comment, Report
|
Member, Comment, Report, Announcement
|
||||||
|
|
||||||
|
|
||||||
# Define an inline admin descriptor for Employee model
|
# Define an inline admin descriptor for Employee model
|
||||||
@ -62,3 +62,4 @@ admin.site.register(Image)
|
|||||||
admin.site.register(ModerationAction)
|
admin.site.register(ModerationAction)
|
||||||
admin.site.register(Language)
|
admin.site.register(Language)
|
||||||
admin.site.register(Text)
|
admin.site.register(Text)
|
||||||
|
admin.site.register(Announcement)
|
||||||
|
41
src/fellchensammlung/migrations/0005_announcement.py
Normal file
41
src/fellchensammlung/migrations/0005_announcement.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-05 04:21
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("fellchensammlung", "0004_alter_report_reported_broken_rules"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Announcement",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"text_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="fellchensammlung.text",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("logged_in_only", models.BooleanField(default=False)),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
(
|
||||||
|
"publish_start_time",
|
||||||
|
models.DateTimeField(verbose_name="Veröffentlichungszeitpunk"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"publish_end_time",
|
||||||
|
models.DateTimeField(verbose_name="Veröffentlichungsende"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
bases=("fellchensammlung.text",),
|
||||||
|
),
|
||||||
|
]
|
26
src/fellchensammlung/migrations/0006_announcement_type.py
Normal file
26
src/fellchensammlung/migrations/0006_announcement_type.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 5.0.6 on 2024-06-05 06:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("fellchensammlung", "0005_announcement"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="announcement",
|
||||||
|
name="type",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("important", "important"),
|
||||||
|
("warning", "warning"),
|
||||||
|
("info", "info"),
|
||||||
|
],
|
||||||
|
default="info",
|
||||||
|
max_length=100,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -4,6 +4,7 @@ from django.db import models
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from django.utils import timezone
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
@ -371,6 +372,55 @@ class Text(models.Model):
|
|||||||
return f"{self.title} ({self.language})"
|
return f"{self.title} ({self.language})"
|
||||||
|
|
||||||
|
|
||||||
|
class Announcement(Text):
|
||||||
|
"""
|
||||||
|
Class to store announcements that should be displayed for all users
|
||||||
|
"""
|
||||||
|
logged_in_only = models.BooleanField(default=False)
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
publish_start_time = models.DateTimeField(verbose_name="Veröffentlichungszeitpunk")
|
||||||
|
publish_end_time = models.DateTimeField(verbose_name="Veröffentlichungsende")
|
||||||
|
IMPORTANT = "important"
|
||||||
|
WARNING = "warning"
|
||||||
|
INFO = "info"
|
||||||
|
TYPES = {
|
||||||
|
IMPORTANT: "important",
|
||||||
|
WARNING: "warning",
|
||||||
|
INFO: "info",
|
||||||
|
}
|
||||||
|
type = models.CharField(choices=TYPES, max_length=100, default=INFO)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_active(self):
|
||||||
|
return self.publish_start_time < timezone.now() < self.publish_end_time
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"[{'🟢' if self.is_active else '🔴'}]{self.title} ({self.language})"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_active_announcements(logged_in=False, language=None):
|
||||||
|
if logged_in:
|
||||||
|
all_active_announcements = [a for a in Announcement.objects.all() if a.is_active]
|
||||||
|
else:
|
||||||
|
all_active_announcements = [a for a in Announcement.objects.filter(logged_in_only=False) if a.is_active]
|
||||||
|
if language is None:
|
||||||
|
return all_active_announcements
|
||||||
|
else:
|
||||||
|
if logged_in:
|
||||||
|
announcements_in_language = Announcement.objects.filter(language=language)
|
||||||
|
else:
|
||||||
|
announcements_in_language = Announcement.objects.filter(language=language, logged_in_only=False)
|
||||||
|
active_announcements_in_language = [a for a in announcements_in_language if a.is_active]
|
||||||
|
|
||||||
|
untranslated_announcements = []
|
||||||
|
text_codes = [announcement.text_code for announcement in active_announcements_in_language]
|
||||||
|
for announcement in all_active_announcements:
|
||||||
|
if announcement.language != language and announcement.text_code not in text_codes:
|
||||||
|
untranslated_announcements.append(announcement)
|
||||||
|
return active_announcements_in_language + untranslated_announcements
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Comment(models.Model):
|
class Comment(models.Model):
|
||||||
"""
|
"""
|
||||||
Class to store comments in markdown content
|
Class to store comments in markdown content
|
||||||
|
@ -447,3 +447,32 @@ textarea {
|
|||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.announcement {
|
||||||
|
flex: 1 100%;
|
||||||
|
margin: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 5px;
|
||||||
|
background: var(--background-three);
|
||||||
|
color: var(--text-two);
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
color: var(--text-two);
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.important {
|
||||||
|
border: #e01137 4px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
border: #e09e11 4px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
border: rgba(17, 58, 224, 0.51) 4px solid;
|
||||||
|
}
|
@ -2,6 +2,9 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
{% for announcement in announcements %}
|
||||||
|
{% include "fellchensammlung/partials/partial-announcement.html" %}
|
||||||
|
{% endfor %}
|
||||||
<h1>{% translate "Notfellchen - Vermittlungen finden" %}</h1>
|
<h1>{% translate "Notfellchen - Vermittlungen finden" %}</h1>
|
||||||
<p>{% translate "Alle Tiere brauchen ein liebendes Zuhause. Damit keins vergessen wird gibt es diese Seite. Entwickelt und betreut von " %}<em><a
|
<p>{% translate "Alle Tiere brauchen ein liebendes Zuhause. Damit keins vergessen wird gibt es diese Seite. Entwickelt und betreut von " %}<em><a
|
||||||
href="https://hyteck.de">moanos</a></em>!</p>
|
href="https://hyteck.de">moanos</a></em>!</p>
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
{% load custom_tags %}
|
||||||
|
<div class="announcement {{ announcement.type }}">
|
||||||
|
<div class="announcement-header">
|
||||||
|
<h1 class="announcement">{{ announcement.title }}</h1>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
{{ announcement.content | render_markdown }}
|
||||||
|
</p>
|
||||||
|
</div>
|
@ -14,13 +14,16 @@ from fellchensammlung import logger
|
|||||||
from fellchensammlung.models import AdoptionNotice, Text, Animal, Rule, Image, Report, ModerationAction, \
|
from fellchensammlung.models import AdoptionNotice, Text, Animal, Rule, Image, Report, ModerationAction, \
|
||||||
Member
|
Member
|
||||||
from .forms import AdoptionNoticeForm, ImageForm, ReportAdoptionNoticeForm, CommentForm, ReportCommentForm, AnimalForm
|
from .forms import AdoptionNoticeForm, ImageForm, ReportAdoptionNoticeForm, CommentForm, ReportCommentForm, AnimalForm
|
||||||
from .models import Language
|
from .models import Language, Announcement
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
"""View function for home page of site."""
|
"""View function for home page of site."""
|
||||||
latest_adoption_list = AdoptionNotice.objects.order_by("-created_at")[:5]
|
latest_adoption_list = AdoptionNotice.objects.order_by("-created_at")[:5]
|
||||||
context = {"adoption_notices": latest_adoption_list}
|
language_code = translation.get_language()
|
||||||
|
lang = Language.objects.get(languagecode=language_code)
|
||||||
|
active_announcements = Announcement.get_active_announcements(lang)
|
||||||
|
context = {"adoption_notices": latest_adoption_list, "announcements": active_announcements}
|
||||||
|
|
||||||
return render(request, 'fellchensammlung/index.html', context=context)
|
return render(request, 'fellchensammlung/index.html', context=context)
|
||||||
|
|
||||||
|
72
src/tests/test_models.py
Normal file
72
src/tests/test_models.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
from datetime import datetime, timedelta
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
from model_bakery import baker
|
||||||
|
|
||||||
|
from fellchensammlung.models import Announcement, Language
|
||||||
|
|
||||||
|
|
||||||
|
class AnnouncementTest(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.language_de = baker.make(Language, name="Deutsch_", languagecode="de")
|
||||||
|
cls.language_en = baker.make(Language, name="English_", languagecode="en")
|
||||||
|
cls.announcement1 = baker.make(Announcement, title="Notfellchen reduziert um 1000%",
|
||||||
|
content="Jetzt adoptieren was da ist!",
|
||||||
|
publish_start_time=timezone.now() + timedelta(hours=-1),
|
||||||
|
publish_end_time=timezone.now() + timedelta(hours=1),
|
||||||
|
text_code="advert1",
|
||||||
|
language=cls.language_de)
|
||||||
|
cls.announcement2 = baker.make(Announcement, title="Notfellchen now on sale!",
|
||||||
|
content="Adopt now!",
|
||||||
|
publish_start_time=timezone.now() + timedelta(hours=-1),
|
||||||
|
publish_end_time=timezone.now() + timedelta(hours=1),
|
||||||
|
text_code="advert1",
|
||||||
|
language=cls.language_en)
|
||||||
|
|
||||||
|
cls.announcement3 = baker.make(Announcement, title="We got hacked",
|
||||||
|
content="Hackers threaten to release incredibly sweet animal photos!",
|
||||||
|
publish_start_time=timezone.now() + timedelta(hours=-1),
|
||||||
|
publish_end_time=timezone.now() + timedelta(hours=1),
|
||||||
|
text_code="hacked",
|
||||||
|
language=cls.language_en)
|
||||||
|
|
||||||
|
cls.announcement4 = baker.make(Announcement, title="New function: Nothing",
|
||||||
|
content="You can now also do NOTHING on this side! NOTHING will help you to be "
|
||||||
|
"more productive",
|
||||||
|
publish_start_time=timezone.now() + timedelta(hours=1),
|
||||||
|
publish_end_time=datetime.now() + timedelta(hours=2),
|
||||||
|
text_code="inactive",
|
||||||
|
language=cls.language_en)
|
||||||
|
|
||||||
|
cls.announcement5 = baker.make(Announcement, title="Secret for all logged in",
|
||||||
|
content="You can create adoption notices yourself",
|
||||||
|
publish_start_time=timezone.now() + timedelta(hours=-1),
|
||||||
|
publish_end_time=datetime.now() + timedelta(hours=2),
|
||||||
|
text_code="secret",
|
||||||
|
language=cls.language_en,
|
||||||
|
logged_in_only=True)
|
||||||
|
|
||||||
|
def test_active_announcements(self):
|
||||||
|
active_announcements = Announcement.get_active_announcements()
|
||||||
|
self.assertTrue(self.announcement1 in active_announcements)
|
||||||
|
self.assertTrue(self.announcement2 in active_announcements)
|
||||||
|
self.assertTrue(self.announcement3 in active_announcements)
|
||||||
|
self.assertTrue(self.announcement4 not in active_announcements)
|
||||||
|
self.assertTrue(self.announcement5 not in active_announcements)
|
||||||
|
|
||||||
|
active_announcements = Announcement.get_active_announcements(language=self.language_de)
|
||||||
|
self.assertTrue(self.announcement1 in active_announcements)
|
||||||
|
self.assertTrue(self.announcement3 in active_announcements)
|
||||||
|
self.assertTrue(self.announcement2 not in active_announcements)
|
||||||
|
self.assertTrue(self.announcement4 not in active_announcements)
|
||||||
|
self.assertTrue(self.announcement5 not in active_announcements)
|
||||||
|
|
||||||
|
active_announcements = Announcement.get_active_announcements(language=self.language_de, logged_in=True)
|
||||||
|
self.assertTrue(self.announcement1 in active_announcements)
|
||||||
|
self.assertTrue(self.announcement3 in active_announcements)
|
||||||
|
self.assertTrue(self.announcement2 not in active_announcements)
|
||||||
|
self.assertTrue(self.announcement4 not in active_announcements)
|
||||||
|
self.assertTrue(self.announcement5 in active_announcements)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user