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

Include graphical announcement form

parent 327bf3ab
No related branches found
No related tags found
1 merge request!173Frontend based announcement management
from datetime import time
from django import forms from django import forms
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget
from material import Layout, Fieldset, Row
from .models import Group, Person, School, SchoolTerm from .models import Group, Person, School, SchoolTerm, Announcement
class PersonAccountForm(forms.ModelForm): class PersonAccountForm(forms.ModelForm):
...@@ -132,3 +137,72 @@ class EditTermForm(forms.ModelForm): ...@@ -132,3 +137,72 @@ class EditTermForm(forms.ModelForm):
class Meta: class Meta:
model = SchoolTerm model = SchoolTerm
fields = ["caption", "date_start", "date_end"] fields = ["caption", "date_start", "date_end"]
class AnnouncementForm(forms.ModelForm):
valid_from = forms.DateTimeField(required=False)
valid_until = forms.DateTimeField(required=False)
valid_from_date = forms.DateField(label=_("Date"))
valid_from_time = forms.TimeField(label=_("Time"))
valid_until_date = forms.DateField(label=_("Date"))
valid_until_time = forms.TimeField(label=_("Time"))
layout = Layout(
Fieldset(
_("From when until when should the announcement be displayed?"),
Row("valid_from_date", "valid_from_time", "valid_until_date", "valid_until_time"),
),
Fieldset(_("Write your announcement:"), "title", "description"),
)
@classmethod
def get_initial(cls):
return {
"valid_from_date": timezone.datetime.now(),
"valid_from_time": time(0,0),
"valid_until_date": timezone.datetime.now(),
"valid_until_time": time(23, 59)
}
def clean(self):
data = super().clean()
from_date = data["valid_from_date"]
from_time = data["valid_from_time"]
until_date = data["valid_until_date"]
until_time = data["valid_until_time"]
valid_from = timezone.datetime.combine(from_date, from_time)
valid_until = timezone.datetime.combine(until_date, until_time)
if valid_until < timezone.datetime.now():
raise ValidationError(
_("You are not allowed to create announcements which are only valid in the past.")
)
elif valid_from > valid_until:
raise ValidationError(
_("The from date and time must be earlier then the until date and time.")
)
data["valid_from"] = valid_from
data["valid_until"] = valid_until
return data
def save(self, _ = False):
a = self.instance if self.instance is not None else Announcement()
a.valid_from = self.cleaned_data["valid_from"]
a.valid_until = self.cleaned_data["valid_until"]
a.title = self.cleaned_data["title"]
a.description = self.cleaned_data["description"]
a.save()
return a
class Meta:
model = Announcement
exclude = []
...@@ -57,6 +57,15 @@ MENUS = { ...@@ -57,6 +57,15 @@ MENUS = {
"menu_generator.validators.is_superuser", "menu_generator.validators.is_superuser",
], ],
"submenu": [ "submenu": [
{
"name": _("Announcements"),
"url": "announcements",
"icon": "announcement",
"validators": [
"menu_generator.validators.is_authenticated",
"menu_generator.validators.is_superuser",
],
},
{ {
"name": _("Data management"), "name": _("Data management"),
"url": "data_management", "url": "data_management",
......
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load i18n material_form %}
{% block browser_title %}
{% if mode == "edit" %}
{% blocktrans %}Edit announcement{% endblocktrans %}
{% else %}
{% blocktrans %}Publish announcement{% endblocktrans %}
{% endif %}
{% endblock %}
{% block page_title %}
{% if mode == "edit" %}
{% blocktrans %}Edit announcement{% endblocktrans %}
{% else %}
{% blocktrans %}Publish new announcement{% endblocktrans %}
{% endif %}
{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
{% form form=form %}{% endform %}
<button type="submit" class="btn green waves-effect waves-light">
<i class="material-icons left">save</i>
{% trans "Save und publish announcement" %}
</button>
</form>
{% endblock %}
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load i18n %}
{% block browser_title %}{% blocktrans %}Announcements{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Announcements{% endblocktrans %}{% endblock %}
{% block content %}
<a class="btn green waves-effect waves-light" href="{% url "add_announcement" %}">
<i class="material-icons left">add</i>
{% trans "Publish new announcement" %}
</a>
<table class="highlight">
<thead>
<tr>
<th>{% trans "Title" %}</th>
<th>{% trans "Valid from" %}</th>
<th>{% trans "Valid until" %}</th>
<th>{% trans "Recipients" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for announcement in announcements %}
<tr>
<td>{{ announcement.title }}</td>
<td>{{ announcement.valid_from }}</td>
<td>{{ announcement.valid_until }}</td>
<td>{{ announcement.recipients.all|join:", " }}</td>
<td>
<a class="btn-flat waves-effect waves-orange orange-text" href="{% url "edit_announcement" announcement.id %}">
<i class="material-icons left">edit</i>
{% trans "Edit" %}
</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="4">
<p class="flow-text">{% trans "There are no announcements." %}</p>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
...@@ -35,6 +35,9 @@ urlpatterns = [ ...@@ -35,6 +35,9 @@ urlpatterns = [
path("group/<int:id_>/edit", views.edit_group, name="edit_group_by_id"), path("group/<int:id_>/edit", views.edit_group, name="edit_group_by_id"),
path("", views.index, name="index"), path("", views.index, name="index"),
path("notifications/mark-read/<int:id_>", views.notification_mark_read, name="notification_mark_read"), path("notifications/mark-read/<int:id_>", views.notification_mark_read, name="notification_mark_read"),
path("announcements/", views.announcements, name="announcements"),
path("announcement/create/", views.announcement_form, name="add_announcement"),
path("announcement/edit/<int:pk>/", views.announcement_form, name="edit_announcement"),
path("maintenance-mode/", include("maintenance_mode.urls")), path("maintenance-mode/", include("maintenance_mode.urls")),
path("impersonate/", include("impersonate.urls")), path("impersonate/", include("impersonate.urls")),
path("__i18n__/", include("django.conf.urls.i18n")), path("__i18n__/", include("django.conf.urls.i18n")),
......
...@@ -15,6 +15,7 @@ from .forms import ( ...@@ -15,6 +15,7 @@ from .forms import (
EditSchoolForm, EditSchoolForm,
EditTermForm, EditTermForm,
PersonsAccountsFormSet, PersonsAccountsFormSet,
AnnouncementForm,
) )
from .models import Activity, Group, Notification, Person, School, DashboardWidget, Announcement from .models import Activity, Group, Notification, Person, School, DashboardWidget, Announcement
from .tables import GroupsTable, PersonsTable from .tables import GroupsTable, PersonsTable
...@@ -271,3 +272,47 @@ def notification_mark_read(request: HttpRequest, id_: int) -> HttpResponse: ...@@ -271,3 +272,47 @@ def notification_mark_read(request: HttpRequest, id_: int) -> HttpResponse:
raise PermissionDenied(_("You are not allowed to mark notifications from other users as read!")) raise PermissionDenied(_("You are not allowed to mark notifications from other users as read!"))
return redirect("index") return redirect("index")
@admin_required
def announcements(request: HttpRequest) -> HttpResponse:
context = {}
# Get all persons
announcements = Announcement.objects.all()
context["announcements"] = announcements
return render(request, "core/announcement/list.html", context)
@admin_required
def announcement_form(request: HttpRequest, pk: Optional[int] = None) -> HttpResponse:
context = {}
if pk:
announcement = get_object_or_404(Announcement, pk=pk)
form = AnnouncementForm(
request.POST or None,
instance=announcement,
initial={
"valid_from_date": announcement.valid_from.date(),
"valid_from_time": announcement.valid_from.time(),
"valid_until_date": announcement.valid_until.date(),
"valid_until_time": announcement.valid_until.time()
}
)
context["mode"] = "edit"
else:
form = AnnouncementForm(request.POST or None, initial=AnnouncementForm.get_initial())
context["mode"] = "add"
if request.method == "POST":
if form.is_valid():
form.save()
messages.success(request, _("The announcement has been saved."))
return redirect("announcements")
context["form"] = form
return render(request, "core/announcement/form.html", context)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment