diff --git a/AKDashboard/locale/de_DE/LC_MESSAGES/django.po b/AKDashboard/locale/de_DE/LC_MESSAGES/django.po index 4bc357378058b84ba589f6702dc034faed47c73d..1520bffefccb65c63b44b38b9180a893e7351d01 100644 --- a/AKDashboard/locale/de_DE/LC_MESSAGES/django.po +++ b/AKDashboard/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\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" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -62,36 +62,61 @@ msgid "Event this button belongs to" msgstr "Veranstaltung, zu der dieser Button gehört" #: 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!" 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." msgstr "" "Bitte kontaktiere eine*n Administrator*in, falls du AKPlanning verwenden " "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" msgstr "AK Liste" -#: AKDashboard/templates/AKDashboard/dashboard_row.html:24 +#: AKDashboard/templates/AKDashboard/dashboard_row.html:23 msgid "Current AKs" msgstr "Aktuelle AKs" -#: AKDashboard/templates/AKDashboard/dashboard_row.html:31 +#: AKDashboard/templates/AKDashboard/dashboard_row.html:30 msgid "AK Wall" msgstr "AK-Wall" -#: AKDashboard/templates/AKDashboard/dashboard_row.html:39 +#: AKDashboard/templates/AKDashboard/dashboard_row.html:38 msgid "Schedule" msgstr "AK-Plan" -#: AKDashboard/templates/AKDashboard/dashboard_row.html:50 +#: AKDashboard/templates/AKDashboard/dashboard_row.html:49 msgid "AK Submission" msgstr "AK-Submission" -#: AKDashboard/templates/AKDashboard/dashboard_row.html:66 -msgid "Write to organizers of this event for questions and comments" -msgstr "" -"Kontaktiere die Organisator*innen des Events bei Fragen oder Kommentaren" +#: AKDashboard/views.py:42 +#, python-format +msgid "New AK: %(ak)s." +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." diff --git a/AKDashboard/static/AKDashboard/style.css b/AKDashboard/static/AKDashboard/style.css index 100aa012ebc8067095b45cb015691010227bed35..62aabf5e8497d4dd731a084e14ae4807334fad45 100644 --- a/AKDashboard/static/AKDashboard/style.css +++ b/AKDashboard/static/AKDashboard/style.css @@ -29,3 +29,20 @@ display: inline; 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; +} diff --git a/AKDashboard/templates/AKDashboard/dashboard.html b/AKDashboard/templates/AKDashboard/dashboard.html index 04502d665304446e43ff4af16efa756ecb4b965a..d93cbb14a66ffd43c5bffe884e4f58a54cf5f4b8 100644 --- a/AKDashboard/templates/AKDashboard/dashboard.html +++ b/AKDashboard/templates/AKDashboard/dashboard.html @@ -18,7 +18,14 @@ {% block content %} {% 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 %} <div class="jumbotron"> <h2 class="display-4"> diff --git a/AKDashboard/templates/AKDashboard/dashboard_event.html b/AKDashboard/templates/AKDashboard/dashboard_event.html index 0cef2cfa1232516717e2e04b83cc7864e9e1e915..cf5bec03ae1b02d44e65bca98dcd99fcc4c0358e 100644 --- a/AKDashboard/templates/AKDashboard/dashboard_event.html +++ b/AKDashboard/templates/AKDashboard/dashboard_event.html @@ -4,6 +4,7 @@ {% load i18n %} {% load static %} {% load tags_AKModel %} +{% load tz %} {% block imports %} @@ -19,5 +20,22 @@ {% endblock %} {% 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 %} diff --git a/AKDashboard/templates/AKDashboard/dashboard_row.html b/AKDashboard/templates/AKDashboard/dashboard_row.html index 8b8a947affb5933a7a754de0db79ed4adf6178e1..799b978721456cfeccb2baf6f94b22ff0c9b49bd 100644 --- a/AKDashboard/templates/AKDashboard/dashboard_row.html +++ b/AKDashboard/templates/AKDashboard/dashboard_row.html @@ -2,68 +2,62 @@ {% load tags_AKModel %} {% load fontawesome_5 %} -<div class="dashboard-row"> - <h2> {{ event.name }} </h2> - <div class="row"> - {% if 'AKSubmission'|check_app_installed %} - <a class="dashboard-box btn btn-primary" - href="{% url 'submit:ak_list' event_slug=event.slug %}"> - <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> - <span class="fa fa-list-ul"></span> - <span class='text'>{% trans 'AK List' %}</span> - </div> - </a> - {% endif %} - {% if 'AKPlan'|check_app_installed %} - {% if not event.plan_hidden or user.is_staff %} - {% if event.active %} - <a class="dashboard-box btn btn-primary" - href="{% url 'plan:plan_overview' event_slug=event.slug %}"> - <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> - <span class="fa fa-clock"></span> - <span class='text'>{% trans 'Current AKs' %}</span> - </div> - </a> - <a class="dashboard-box btn btn-primary" - href="{% url 'plan:plan_wall' event_slug=event.slug %}"> - <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> - <span class="fa fa-calendar"></span> - <span class='text'>{% trans 'AK Wall' %}</span> - </div> - </a> - {% else %} - <a class="dashboard-box btn btn-primary" - href="{% url 'plan:plan_overview' event_slug=event.slug %}"> - <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> - <span class="fa fa-calendar-alt"></span> - <span class='text'>{% trans 'Schedule' %}</span> - </div> - </a> - {% endif %} +<h2><a href="{% url 'dashboard:dashboard_event' slug=event.slug %}">{{ event.name }}</a></h2> +<div class="row"> + {% if 'AKSubmission'|check_app_installed %} + <a class="dashboard-box btn btn-primary" + href="{% url 'submit:ak_list' event_slug=event.slug %}"> + <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> + <span class="fa fa-list-ul"></span> + <span class='text'>{% trans 'AK List' %}</span> + </div> + </a> + {% endif %} + {% if 'AKPlan'|check_app_installed %} + {% if not event.plan_hidden or user.is_staff %} + {% if event.active %} + <a class="dashboard-box btn btn-primary" + href="{% url 'plan:plan_overview' event_slug=event.slug %}"> + <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> + <span class="fa fa-clock"></span> + <span class='text'>{% trans 'Current AKs' %}</span> + </div> + </a> + <a class="dashboard-box btn btn-primary" + href="{% url 'plan:plan_wall' event_slug=event.slug %}"> + <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> + <span class="fa fa-calendar"></span> + <span class='text'>{% trans 'AK Wall' %}</span> + </div> + </a> + {% else %} + <a class="dashboard-box btn btn-primary" + href="{% url 'plan:plan_overview' event_slug=event.slug %}"> + <div class="col-sm-12 col-md-3 col-lg-2 dashboard-button"> + <span class="fa fa-calendar-alt"></span> + <span class='text'>{% trans 'Schedule' %}</span> + </div> + </a> {% 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 %} + {% 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> + diff --git a/AKDashboard/views.py b/AKDashboard/views.py index 8740bb7d8a01b2c874a3653804000f7807e594a2..1f4f55276b9661f8f401413189a460129b31ea43 100644 --- a/AKDashboard/views.py +++ b/AKDashboard/views.py @@ -1,8 +1,12 @@ +from django.apps import apps +from django.urls import reverse_lazy from django.utils.decorators import method_decorator from django.views.decorators.csrf import ensure_csrf_cookie 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): @@ -22,3 +26,43 @@ class DashboardEventView(DetailView): template_name = 'AKDashboard/dashboard_event.html' context_object_name = '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 diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index 04302f411194498fbb5e327bec60cff6f6004915..a6ac974a500f58aaf930960fd2f77fb2a9ebcee3 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -171,6 +171,11 @@ PLAN_SHOW_HIERARCHY = True # For which time (in seconds) should changes of akslots be highlighted in plan? 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 SIMPLE_BACKEND_REDIRECT_URL = "/user/" LOGIN_REDIRECT_URL = SIMPLE_BACKEND_REDIRECT_URL