2
0
Fork 0

Implement incoming_message view and show message history on helper page

This commit is contained in:
Luca 2023-05-07 17:24:26 +02:00
parent e9e263d59d
commit eb681d31b0
8 changed files with 133 additions and 9 deletions

View File

@ -31,6 +31,14 @@
margin-bottom: 1em; margin-bottom: 1em;
} }
.message-incoming {
margin-right: 20%;
}
.message-outgoing {
margin-left: 20%;
}
.sticky-nav { .sticky-nav {
background-color: var(--background); background-color: var(--background);
margin: 0 -0.75rem; margin: 0 -0.75rem;

View File

@ -23,3 +23,10 @@ class BulkMessage(forms.Form):
checked_in_only = forms.BooleanField( checked_in_only = forms.BooleanField(
label="Nur an Helfer*innen mit mindestens einem Check-in senden", required=False 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"}),
)

View File

@ -25,9 +25,8 @@ def populate_team_nav(sender, **kwargs):
nav_items.append( nav_items.append(
{ {
"link": reverse("team:incoming_messages"), "link": reverse("team:incoming_messages"),
"text": "Eingehende Nachrichten" + f" ({num_unread})" "text": "Eingehende Nachrichten"
if num_unread + (f" ({num_unread})" if num_unread else ""),
else "",
} }
) )

View File

@ -1,5 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load humanize %}
{% block title %}Helferdetails{% endblock %} {% block title %}Helferdetails{% endblock %}
{% block content %} {% block content %}
@ -15,4 +17,43 @@
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
<h5 class="subtitle" id="history">Nachrichtenverlauf</h5>
{% for content, created_at, read, incoming in history %}
<div class="message{% if not read %} is-info{% endif %} mb-5 {% if incoming %}message-incoming{% else %}{% if not created_at %}is-warning{% else %}is-primary{% endif %} message-outgoing{% endif %}">
<div class="message-body">
<div class="is-flex is-flex-wrap-wrap">
{{ content }}
{% if created_at %}
<div class="has-text-right is-flex-grow-1">
<small>{{ created_at | naturaltime }}</small>
</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
<form action="{% url 'team:mark_as_read' helper.pk %}" id="markAsRead" method="POST">
{% csrf_token %}
</form>
<form id="sendMessage" method="POST">
{% csrf_token %}
{% for field in form %}
<div class="field">
<div class="control">
{{ field }}
</div>
{% for error in field.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
</div>
{% endfor %}
<div class="field is-grouped is-grouped-right">
<div class="control">
<button class="button" form="markAsRead" type="submit">Alle als gelesen markieren</button>
</div>
<div class="control">
<button class="button is-link" form="sendMessage" type="submit">Senden</button>
</div>
</div>
</form>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,23 @@
{% extends "base.html" %}
{% load humanize %}
{% block title %}Nachricht von {{ message.sender }}{% endblock %}
{% block content %}
<h3 class="title">Nachricht von {{ message.sender }}{% if not message.read %} (ungelesen){% endif %}</h3>
<div class="display mb-5">
<p>{{ message.created_at | naturaltime }}</p>
</div>
<div class="message mb-5">
<div class="message-body">
{{ message.content }}
</div>
</div>
{% if not message.read %}
<form method="POST">
{% csrf_token %}
<button class="button is-info" type="submit">Als gelesen markieren</button>
</form>
{% endif %}
{% endblock %}

View File

@ -5,8 +5,9 @@
{% block title %}Sie haben {{ num_unread | apnumber }} neue Nachricht{{ num_unread | pluralize:"en" }}{% endblock %} {% block title %}Sie haben {{ num_unread | apnumber }} neue Nachricht{{ num_unread | pluralize:"en" }}{% endblock %}
{% block content %} {% block content %}
<h3 class="title">Eingehende Nachrichten</h3>
{% for message in page %} {% for message in page %}
<a href="{% if message.from_helper %}{% url 'team:helper' message.from_helper.pk %}{% else %}{% url 'team:conversation' message.sender %}{% endif %}"> <a href="{% if message.from_helper %}{% url 'team:helper' message.from_helper.pk %}#history{% else %}{% url 'team:incoming_message' message.pk %}{% endif %}">
<div class="message{% if not message.read %} is-info{% endif %} mb-5"> <div class="message{% if not message.read %} is-info{% endif %} mb-5">
<div class="message-header"> <div class="message-header">
{{ message.display_sender }} <small>{{ message.created_at | naturaltime }}</small> {{ message.display_sender }} <small>{{ message.created_at | naturaltime }}</small>

View File

@ -14,5 +14,6 @@ urlpatterns = [
path("checkin/<int:pk>", views.checkin, name="checkin"), path("checkin/<int:pk>", views.checkin, name="checkin"),
path("remove_helper/<int:pk>", views.delete_shiftregistration, name="unregister"), path("remove_helper/<int:pk>", views.delete_shiftregistration, name="unregister"),
path("incoming/", views.incoming_messages, name="incoming_messages"), path("incoming/", views.incoming_messages, name="incoming_messages"),
path("incoming/<str:sender>", views.conversation, name="conversation"), path("incoming/<int:pk>", views.incoming_message, name="incoming_message"),
path("incoming/mark_as_read/<int:pk>", views.mark_as_read, name="mark_as_read"),
] ]

View File

@ -5,11 +5,12 @@ from django.db.models.fields import DateTimeField
from django.db.models import F, Count, Q, ExpressionWrapper, Case, When from django.db.models import F, Count, Q, ExpressionWrapper, Case, When
from .models import ShiftRegistration, Room, Shift, Helper, Message, IncomingMessage from .models import ShiftRegistration, Room, Shift, Helper, Message, IncomingMessage
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
from django.views.generic.edit import FormMixin
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages from django.contrib import messages
from django.db import models from django.db import models
from django.core.paginator import Paginator from django.core.paginator import Paginator
from .forms import BulkMessage, HelperShift from .forms import BulkMessage, HelperShift, HelperMessage
# Create your views here. # Create your views here.
@ -136,9 +137,36 @@ def bulk_message(request):
return render(request, "bulk_message.html", context) return render(request, "bulk_message.html", context)
class HelperDetail(LoginRequiredMixin, DetailView): class HelperDetail(FormMixin, LoginRequiredMixin, DetailView):
template_name = "helper_detail.html" template_name = "helper_detail.html"
model = Helper 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): class ShiftList(LoginRequiredMixin, ListView):
@ -212,5 +240,21 @@ def incoming_messages(request):
@login_required @login_required
def conversation(request, sender): def incoming_message(request, pk):
pass 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)