Skip to content
Snippets Groups Projects
Commit 7a3ebe79 authored by Benjamin Hättasch's avatar Benjamin Hättasch Committed by Nadja Geisler
Browse files

Add feed of recent changes to individual dashboard

Implements #72
Adapt dashboard layout to show feed
Add logic to get a list of recent changes
Add link to dashboard detail view on start page
Introduce settings to disable and control feed
Add translation
parent ff61756d
No related branches found
No related tags found
No related merge requests found
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-05-19 20:46+0000\n" "POT-Creation-Date: 2020-09-20 21:40+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -62,36 +62,61 @@ msgid "Event this button belongs to" ...@@ -62,36 +62,61 @@ msgid "Event this button belongs to"
msgstr "Veranstaltung, zu der dieser Button gehört" msgstr "Veranstaltung, zu der dieser Button gehört"
#: AKDashboard/templates/AKDashboard/dashboard.html:25 #: AKDashboard/templates/AKDashboard/dashboard.html:25
#: AKDashboard/templates/AKDashboard/dashboard_event.html:37
msgid "Write to organizers of this event for questions and comments"
msgstr ""
"Kontaktiere die Organisator*innen des Events bei Fragen oder Kommentaren"
#: AKDashboard/templates/AKDashboard/dashboard.html:32
msgid "Currently, there are no Events!" msgid "Currently, there are no Events!"
msgstr "Aktuell gibt es keine Events!" msgstr "Aktuell gibt es keine Events!"
#: AKDashboard/templates/AKDashboard/dashboard.html:28 #: AKDashboard/templates/AKDashboard/dashboard.html:35
msgid "Please contact an administrator if you want to use AKPlanning." msgid "Please contact an administrator if you want to use AKPlanning."
msgstr "" msgstr ""
"Bitte kontaktiere eine*n Administrator*in, falls du AKPlanning verwenden " "Bitte kontaktiere eine*n Administrator*in, falls du AKPlanning verwenden "
"möchtest." "möchtest."
#: AKDashboard/templates/AKDashboard/dashboard_row.html:13 #: AKDashboard/templates/AKDashboard/dashboard_event.html:27
msgid "Recent"
msgstr "Kürzlich"
#: AKDashboard/templates/AKDashboard/dashboard_row.html:12
msgid "AK List" msgid "AK List"
msgstr "AK Liste" msgstr "AK Liste"
#: AKDashboard/templates/AKDashboard/dashboard_row.html:24 #: AKDashboard/templates/AKDashboard/dashboard_row.html:23
msgid "Current AKs" msgid "Current AKs"
msgstr "Aktuelle AKs" msgstr "Aktuelle AKs"
#: AKDashboard/templates/AKDashboard/dashboard_row.html:31 #: AKDashboard/templates/AKDashboard/dashboard_row.html:30
msgid "AK Wall" msgid "AK Wall"
msgstr "AK-Wall" msgstr "AK-Wall"
#: AKDashboard/templates/AKDashboard/dashboard_row.html:39 #: AKDashboard/templates/AKDashboard/dashboard_row.html:38
msgid "Schedule" msgid "Schedule"
msgstr "AK-Plan" msgstr "AK-Plan"
#: AKDashboard/templates/AKDashboard/dashboard_row.html:50 #: AKDashboard/templates/AKDashboard/dashboard_row.html:49
msgid "AK Submission" msgid "AK Submission"
msgstr "AK-Submission" msgstr "AK-Submission"
#: AKDashboard/templates/AKDashboard/dashboard_row.html:66 #: AKDashboard/views.py:42
msgid "Write to organizers of this event for questions and comments" #, python-format
msgstr "" msgid "New AK: %(ak)s."
"Kontaktiere die Organisator*innen des Events bei Fragen oder Kommentaren" msgstr "Neuer AK: %(ak)s."
#: AKDashboard/views.py:45
#, python-format
msgid "AK \"%(ak)s\" edited."
msgstr "AK \"%(ak)s\" bearbeitet."
#: AKDashboard/views.py:48
#, python-format
msgid "AK \"%(ak)s\" deleted."
msgstr "AK \"%(ak)s\" gelöscht."
#: AKDashboard/views.py:58
#, python-format
msgid "AK \"%(ak)s\" (re-)scheduled."
msgstr "AK \"%(ak)s\" (um-)geplant."
...@@ -29,3 +29,20 @@ ...@@ -29,3 +29,20 @@
display: inline; display: inline;
padding: 0; padding: 0;
} }
#recent-changes-list {
list-style-type:none;
padding-left: 0;
line-height: 220%;
}
#recent-changes-list li {
font-size: 120%;
font-family:monospace;
}
#recent-changes-list a {
text-decoration: none;
color: #555555;
font-weight: bold;
}
...@@ -18,7 +18,14 @@ ...@@ -18,7 +18,14 @@
{% block content %} {% block content %}
{% for event in events %} {% for event in events %}
{% include "AKDashboard/dashboard_row.html" %} <div class="dashboard-row">
{% include "AKDashboard/dashboard_row.html" %}
{% if event.contact_email %}
<p>
<a href="mailto:{{ event.contact_email }}">{% fa5_icon "envelope" "fas" %} {% trans "Write to organizers of this event for questions and comments" %}</a>
</p>
{% endif %}
</div>
{% empty %} {% empty %}
<div class="jumbotron"> <div class="jumbotron">
<h2 class="display-4"> <h2 class="display-4">
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% load tags_AKModel %} {% load tags_AKModel %}
{% load tz %}
{% block imports %} {% block imports %}
...@@ -19,5 +20,22 @@ ...@@ -19,5 +20,22 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% include "AKDashboard/dashboard_row.html" %} <div class="dashboard-row">
{% include "AKDashboard/dashboard_row.html" %}
{% if recent_changes|length > 0 %}
<h3 class="mt-1">{% trans "Recent" %}:</h3>
<ul id="recent-changes-list">
{% for recent in recent_changes %}
<li><a href="{{ recent.link }}">{% fa5_icon recent.icon.0 recent.icon.1 %} {{ recent.text }}</a> <span style="color: #999999;">{{ recent.timestamp | timezone:event.timezone | date:"d.m. H:i" }}</span></li>
{% endfor %}
</ul>
{% endif %}
{% if event.contact_email %}
<p>
<a href="mailto:{{ event.contact_email }}">{% fa5_icon "envelope" "fas" %} {% trans "Write to organizers of this event for questions and comments" %}</a>
</p>
{% endif %}
</div>
{% endblock %} {% endblock %}
...@@ -2,68 +2,62 @@ ...@@ -2,68 +2,62 @@
{% load tags_AKModel %} {% load tags_AKModel %}
{% load fontawesome_5 %} {% load fontawesome_5 %}
<div class="dashboard-row"> <h2><a href="{% url 'dashboard:dashboard_event' slug=event.slug %}">{{ event.name }}</a></h2>
<h2> {{ event.name }} </h2> <div class="row">
<div class="row"> {% if 'AKSubmission'|check_app_installed %}
{% if 'AKSubmission'|check_app_installed %} <a class="dashboard-box btn btn-primary"
<a class="dashboard-box btn btn-primary" href="{% url 'submit:ak_list' event_slug=event.slug %}">
href="{% url 'submit:ak_list' event_slug=event.slug %}"> <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> <span class="fa fa-list-ul"></span>
<span class="fa fa-list-ul"></span> <span class='text'>{% trans 'AK List' %}</span>
<span class='text'>{% trans 'AK List' %}</span> </div>
</div> </a>
</a> {% endif %}
{% endif %} {% if 'AKPlan'|check_app_installed %}
{% if 'AKPlan'|check_app_installed %} {% if not event.plan_hidden or user.is_staff %}
{% if not event.plan_hidden or user.is_staff %} {% if event.active %}
{% if event.active %} <a class="dashboard-box btn btn-primary"
<a class="dashboard-box btn btn-primary" href="{% url 'plan:plan_overview' event_slug=event.slug %}">
href="{% url 'plan:plan_overview' event_slug=event.slug %}"> <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> <span class="fa fa-clock"></span>
<span class="fa fa-clock"></span> <span class='text'>{% trans 'Current AKs' %}</span>
<span class='text'>{% trans 'Current AKs' %}</span> </div>
</div> </a>
</a> <a class="dashboard-box btn btn-primary"
<a class="dashboard-box btn btn-primary" href="{% url 'plan:plan_wall' event_slug=event.slug %}">
href="{% url 'plan:plan_wall' event_slug=event.slug %}"> <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> <span class="fa fa-calendar"></span>
<span class="fa fa-calendar"></span> <span class='text'>{% trans 'AK Wall' %}</span>
<span class='text'>{% trans 'AK Wall' %}</span> </div>
</div> </a>
</a> {% else %}
{% else %} <a class="dashboard-box btn btn-primary"
<a class="dashboard-box btn btn-primary" href="{% url 'plan:plan_overview' event_slug=event.slug %}">
href="{% url 'plan:plan_overview' event_slug=event.slug %}"> <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> <span class="fa fa-calendar-alt"></span>
<span class="fa fa-calendar-alt"></span> <span class='text'>{% trans 'Schedule' %}</span>
<span class='text'>{% trans 'Schedule' %}</span> </div>
</div> </a>
</a>
{% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if 'AKSubmission'|check_app_installed and event.active %}
<a class="dashboard-box btn btn-primary"
href="{% url 'submit:submission_overview' event_slug=event.slug %}">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
<span class="fa fa-pencil-alt"></span>
<span class='text'>{% trans 'AK Submission' %}</span>
</div>
</a>
{% endif %}
{% for button in event.dashboardbutton_set.all %}
<a class="dashboard-box btn btn-{{ button.get_color_display }}"
href="{{ button.url }}">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
{% if button.icon %}<span class="fa">{{ button.icon.as_html }}</span>{% endif %}
<span class='text'>{{ button.text }}</span>
</div>
</a>
{% endfor %}
</div>
{% if event.contact_email %}
<p>
<a href="mailto:{{ event.contact_email }}">{% fa5_icon "envelope" "fas" %} {% trans "Write to organizers of this event for questions and comments" %}</a>
</p>
{% endif %} {% endif %}
{% if 'AKSubmission'|check_app_installed and event.active %}
<a class="dashboard-box btn btn-primary"
href="{% url 'submit:submission_overview' event_slug=event.slug %}">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
<span class="fa fa-pencil-alt"></span>
<span class='text'>{% trans 'AK Submission' %}</span>
</div>
</a>
{% endif %}
{% for button in event.dashboardbutton_set.all %}
<a class="dashboard-box btn btn-{{ button.get_color_display }}"
href="{{ button.url }}">
<div class="col-sm-12 col-md-3 col-lg-2 dashboard-button">
{% if button.icon %}<span class="fa">{{ button.icon.as_html }}</span>{% endif %}
<span class='text'>{{ button.text }}</span>
</div>
</a>
{% endfor %}
</div> </div>
from django.apps import apps
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.generic import TemplateView, DetailView from django.views.generic import TemplateView, DetailView
from django.utils.translation import gettext_lazy as _
from AKModel.models import Event from AKModel.models import Event, AK, AKSlot
from AKPlanning import settings
class DashboardView(TemplateView): class DashboardView(TemplateView):
...@@ -22,3 +26,43 @@ class DashboardEventView(DetailView): ...@@ -22,3 +26,43 @@ class DashboardEventView(DetailView):
template_name = 'AKDashboard/dashboard_event.html' template_name = 'AKDashboard/dashboard_event.html'
context_object_name = 'event' context_object_name = 'event'
model = Event model = Event
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Show feed of recent changes (if activated)
if settings.DASHBOARD_SHOW_RECENT:
recent_changes = []
# Newest AKs
if apps.is_installed("AKSubmission"):
submission_changes = AK.history.filter(event=context['event'])[:50]
for s in submission_changes:
if s.history_type == '+':
text = _('New AK: %(ak)s.') % {'ak': s.name}
icon = ('plus-square', 'far')
elif s.history_type == '~':
text = _('AK "%(ak)s" edited.') % {'ak': s.name}
icon = ('pen-square', 'fas')
else:
text = _('AK "%(ak)s" deleted.') % {'ak': s.name}
icon = ('times', 'fas')
recent_changes.append({'icon': icon, 'text': text, 'link': reverse_lazy('submit:ak_detail', kwargs={'event_slug': context['event'].slug, 'pk': s.id}), 'timestamp': s.history_date})
# Changes in plan
if apps.is_installed("AKPlan"):
if not context['event'].plan_hidden:
last_changed_slots = AKSlot.objects.filter(event=context['event']).order_by('-updated')[:50]
for changed_slot in last_changed_slots:
recent_changes.append({'icon': ('clock', 'far'), 'text': _('AK "%(ak)s" (re-)scheduled.') % {'ak': changed_slot.ak.name}, 'link': reverse_lazy('submit:ak_detail', kwargs={
'event_slug': context['event'].slug, 'pk': changed_slot.ak.id}), 'timestamp': changed_slot.updated})
# Sort by change date...
recent_changes.sort(key=lambda x: x['timestamp'], reverse=True)
# ... and restrict to the latest 25 changes
context['recent_changes'] = recent_changes[:settings.DASHBOARD_RECENT_MAX]
else:
context['recent_changes'] = []
return context
...@@ -171,6 +171,11 @@ PLAN_SHOW_HIERARCHY = True ...@@ -171,6 +171,11 @@ PLAN_SHOW_HIERARCHY = True
# For which time (in seconds) should changes of akslots be highlighted in plan? # For which time (in seconds) should changes of akslots be highlighted in plan?
PLAN_MAX_HIGHLIGHT_UPDATE_SECONDS = 2 * 60 * 60 PLAN_MAX_HIGHLIGHT_UPDATE_SECONDS = 2 * 60 * 60
# Show feed of recent changes in dashboard
DASHBOARD_SHOW_RECENT = True
# How many entries max?
DASHBOARD_RECENT_MAX = 25
# Registration/login behavior # Registration/login behavior
SIMPLE_BACKEND_REDIRECT_URL = "/user/" SIMPLE_BACKEND_REDIRECT_URL = "/user/"
LOGIN_REDIRECT_URL = SIMPLE_BACKEND_REDIRECT_URL LOGIN_REDIRECT_URL = SIMPLE_BACKEND_REDIRECT_URL
......
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