diff --git a/shiftregister/core/templates/base.html b/shiftregister/core/templates/base.html index deca202..e8930b2 100644 --- a/shiftregister/core/templates/base.html +++ b/shiftregister/core/templates/base.html @@ -31,6 +31,14 @@ margin-bottom: 1em; } + .message-incoming { + margin-right: 20%; + } + + .message-outgoing { + margin-left: 20%; + } + .sticky-nav { background-color: var(--background); margin: 0 -0.75rem; diff --git a/shiftregister/team/forms.py b/shiftregister/team/forms.py index 7faa094..2b7d4ef 100644 --- a/shiftregister/team/forms.py +++ b/shiftregister/team/forms.py @@ -23,3 +23,10 @@ class BulkMessage(forms.Form): checked_in_only = forms.BooleanField( label="Nur an Helfer*innen mit mindestens einem Check-in senden", required=False ) + + +class HelperMessage(forms.Form): + message = forms.CharField( + max_length=160, + widget=forms.Textarea(attrs={"class": "textarea", "placeholder": "Nachricht"}), + ) diff --git a/shiftregister/team/signals.py b/shiftregister/team/signals.py index d9a308b..163784e 100644 --- a/shiftregister/team/signals.py +++ b/shiftregister/team/signals.py @@ -25,9 +25,8 @@ def populate_team_nav(sender, **kwargs): nav_items.append( { "link": reverse("team:incoming_messages"), - "text": "Eingehende Nachrichten" + f" ({num_unread})" - if num_unread - else "", + "text": "Eingehende Nachrichten" + + (f" ({num_unread})" if num_unread else ""), } ) diff --git a/shiftregister/team/templates/helper_detail.html b/shiftregister/team/templates/helper_detail.html index 318878c..103ea72 100644 --- a/shiftregister/team/templates/helper_detail.html +++ b/shiftregister/team/templates/helper_detail.html @@ -1,5 +1,7 @@ {% extends "base.html" %} +{% load humanize %} + {% block title %}Helferdetails{% endblock %} {% block content %} @@ -15,4 +17,43 @@ {% endfor %} +
Nachrichtenverlauf
+{% for content, created_at, read, incoming in history %} +
+
+
+ {{ content }} +{% if created_at %} +
+ {{ created_at | naturaltime }} +
+{% endif %} +
+
+
+{% endfor %} +
+ {% csrf_token %} +
+
+ {% csrf_token %} +{% for field in form %} +
+
+ {{ field }} +
+{% for error in field.errors %} +

{{ error }}

+{% endfor %} +
+{% endfor %} +
+
+ +
+
+ +
+
+
{% endblock %} diff --git a/shiftregister/team/templates/incoming_message.html b/shiftregister/team/templates/incoming_message.html new file mode 100644 index 0000000..48a6e9a --- /dev/null +++ b/shiftregister/team/templates/incoming_message.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% load humanize %} + +{% block title %}Nachricht von {{ message.sender }}{% endblock %} + +{% block content %} +

Nachricht von {{ message.sender }}{% if not message.read %} (ungelesen){% endif %}

+
+

{{ message.created_at | naturaltime }}

+
+
+
+ {{ message.content }} +
+
+{% if not message.read %} +
+ {% csrf_token %} + +
+{% endif %} +{% endblock %} diff --git a/shiftregister/team/templates/incoming_messages.html b/shiftregister/team/templates/incoming_messages.html index 496d1cc..d113458 100644 --- a/shiftregister/team/templates/incoming_messages.html +++ b/shiftregister/team/templates/incoming_messages.html @@ -5,8 +5,9 @@ {% block title %}Sie haben {{ num_unread | apnumber }} neue Nachricht{{ num_unread | pluralize:"en" }}{% endblock %} {% block content %} +

Eingehende Nachrichten

{% for message in page %} - +
{{ message.display_sender }} {{ message.created_at | naturaltime }} diff --git a/shiftregister/team/urls.py b/shiftregister/team/urls.py index f4b1558..2ca83eb 100644 --- a/shiftregister/team/urls.py +++ b/shiftregister/team/urls.py @@ -14,5 +14,6 @@ urlpatterns = [ path("checkin/", views.checkin, name="checkin"), path("remove_helper/", views.delete_shiftregistration, name="unregister"), path("incoming/", views.incoming_messages, name="incoming_messages"), - path("incoming/", views.conversation, name="conversation"), + path("incoming/", views.incoming_message, name="incoming_message"), + path("incoming/mark_as_read/", views.mark_as_read, name="mark_as_read"), ] diff --git a/shiftregister/team/views.py b/shiftregister/team/views.py index 8b8a0ba..8ba4717 100644 --- a/shiftregister/team/views.py +++ b/shiftregister/team/views.py @@ -5,11 +5,12 @@ from django.db.models.fields import DateTimeField from django.db.models import F, Count, Q, ExpressionWrapper, Case, When from .models import ShiftRegistration, Room, Shift, Helper, Message, IncomingMessage from django.views.generic import DetailView, ListView +from django.views.generic.edit import FormMixin from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib import messages from django.db import models from django.core.paginator import Paginator -from .forms import BulkMessage, HelperShift +from .forms import BulkMessage, HelperShift, HelperMessage # Create your views here. @@ -136,9 +137,36 @@ def bulk_message(request): return render(request, "bulk_message.html", context) -class HelperDetail(LoginRequiredMixin, DetailView): +class HelperDetail(FormMixin, LoginRequiredMixin, DetailView): template_name = "helper_detail.html" model = Helper + form_class = HelperMessage + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context["history"] = ( + IncomingMessage.objects.filter(sender=self.object.phone) + .annotate(incoming=models.Value(True)) + .values_list("content", "created_at", "read", "incoming") + .union( + self.object.message_set.annotate( + read=models.Value(True), incoming=models.Value(False) + ).values_list("text", "sent_at", "read", "incoming") + ) + .order_by(F("created_at").asc(nulls_last=True)) + ) + + return context + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + + form = self.get_form() + if form.is_valid(): + Message(text=form.cleaned_data["message"], to=self.object).save() + + return self.render_to_response(self.get_context_data(form=form)) class ShiftList(LoginRequiredMixin, ListView): @@ -212,5 +240,21 @@ def incoming_messages(request): @login_required -def conversation(request, sender): - pass +def incoming_message(request, pk): + message = get_object_or_404(IncomingMessage, pk=pk) + + if request.method == "POST": + message.read = True + message.save() + + return render(request, "incoming_message.html", {"message": message}) + + +@login_required +def mark_as_read(request, pk): + helper = get_object_or_404(Helper, pk=pk) + + if request.method == "POST": + IncomingMessage.objects.filter(sender=helper.phone).update(read=True) + + return redirect("team:helper", pk=pk)