Add an inline admin interface to the log module

This commit is contained in:
Rodolphe Breard 2018-02-04 20:28:09 +01:00
parent fdf879a6b3
commit 28e0743b3c
9 changed files with 187 additions and 28 deletions

View file

@ -1,5 +1,4 @@
from django.contrib import admin from django.contrib import admin
from .models import Source, Entry from .models import Source
admin.site.register(Source) admin.site.register(Source)
admin.site.register(Entry)

14
logs/forms.py Normal file
View file

@ -0,0 +1,14 @@
from django.utils.translation import gettext_lazy as _
from django.forms.widgets import DateInput
from django import forms
import datetime
class SearchForm(forms.Form):
source = forms.CharField(max_length=128)
date = forms.DateField(
label=_('date'),
initial=datetime.date.today(),
widget=DateInput(format='%d-%m-%Y'),
input_formats=['%d-%m-%Y'],
)

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.0\n" "Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-27 18:32+0100\n" "POT-Creation-Date: 2018-02-04 19:45+0100\n"
"PO-Revision-Date: 2018-01-27 18:35+0100\n" "PO-Revision-Date: 2018-01-27 18:35+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n" "Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n" "Language-Team: Khaganat <assoc@khaganat.net>\n"
@ -12,7 +12,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/logs/entries.html:10 templates/logs/entries.html:18 #: forms.py:10
msgid "date"
msgstr ""
#: templates/logs/entries.html:10 templates/logs/entries.html:21
msgid "logs_back" msgid "logs_back"
msgstr "Back" msgstr "Back"
@ -20,6 +24,28 @@ msgstr "Back"
msgid "logs_title" msgid "logs_title"
msgstr "Khaganat's logs" msgstr "Khaganat's logs"
#: templates/logs/index.html:33 #: templates/logs/index.html:32
msgid "go"
msgstr ""
#: templates/logs/index.html:36
#, python-format
msgid "%(name)s is hidden."
msgstr ""
#: templates/logs/index.html:37
msgid "show"
msgstr ""
#: templates/logs/index.html:39
#, python-format
msgid "%(name)s is published."
msgstr ""
#: templates/logs/index.html:40
msgid "hide"
msgstr ""
#: templates/logs/index.html:51
msgid "logs_no_logs_available" msgid "logs_no_logs_available"
msgstr "No logs available." msgstr "No logs available."

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 1.0\n" "Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-27 18:32+0100\n" "POT-Creation-Date: 2018-02-04 19:45+0100\n"
"PO-Revision-Date: 2018-01-27 18:35+0100\n" "PO-Revision-Date: 2018-01-27 18:35+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n" "Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n" "Language-Team: Khaganat <assoc@khaganat.net>\n"
@ -12,7 +12,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: templates/logs/entries.html:10 templates/logs/entries.html:18 #: forms.py:10
msgid "date"
msgstr ""
#: templates/logs/entries.html:10 templates/logs/entries.html:21
msgid "logs_back" msgid "logs_back"
msgstr "Retour" msgstr "Retour"
@ -20,6 +24,28 @@ msgstr "Retour"
msgid "logs_title" msgid "logs_title"
msgstr "Journaux de conversation de Khaganat" msgstr "Journaux de conversation de Khaganat"
#: templates/logs/index.html:33 #: templates/logs/index.html:32
msgid "go"
msgstr ""
#: templates/logs/index.html:36
#, python-format
msgid "%(name)s is hidden."
msgstr "%(name)s est masqué."
#: templates/logs/index.html:37
msgid "show"
msgstr "montrer"
#: templates/logs/index.html:39
#, python-format
msgid "%(name)s is published."
msgstr "%(name)s est publié."
#: templates/logs/index.html:40
msgid "hide"
msgstr "masquer"
#: templates/logs/index.html:51
msgid "logs_no_logs_available" msgid "logs_no_logs_available"
msgstr "Aucun journal de conversation disponible." msgstr "Aucun journal de conversation disponible."

View file

@ -11,6 +11,9 @@
</div> </div>
<div> <div>
{% for entry in entries%} {% for entry in entries%}
{% if request.user.is_staff %}
<a href="{% url 'log_switch_entry' entry.pk %}?next={{ request.path_info }}">{% if entry.hidden %}<span class="text-warning"></span>{% else %}<span class="text-success"></span>{% endif %}</a>
{% endif %}
{{ entry.created|date:"H:i:s" }} {% if entry.nick %}<span class="log-nick">&lt;{{ entry.nick }}&gt;</span> <span class="log-content">{{ entry.content }}</span>{% else %}<span class="log-action">* {{ entry.content }}</span>{% endif %}<br /> {{ entry.created|date:"H:i:s" }} {% if entry.nick %}<span class="log-nick">&lt;{{ entry.nick }}&gt;</span> <span class="log-content">{{ entry.content }}</span>{% else %}<span class="log-action">* {{ entry.content }}</span>{% endif %}<br />
{% endfor %} {% endfor %}
</div> </div>

View file

@ -23,6 +23,24 @@
{% for date in source.stats %} {% for date in source.stats %}
<a href="{% url 'log_day' source=source.source__slug year=date.date.year month=date.date.month day=date.date.day %}" class="list-group-item list-group-item-action">{{ date.date }}</a> <a href="{% url 'log_day' source=source.source__slug year=date.date.year month=date.date.month day=date.date.day %}" class="list-group-item list-group-item-action">{{ date.date }}</a>
{% endfor %} {% endfor %}
{% if request.user.is_staff %}
<div class="list-group-item list-group-item-action">
<form method="post" action="{% url 'log_search' %}">
{% csrf_token %}
{{ form.date }}
<input type="hidden" name="{{ form.source.name }}" value="{{ source.source__slug }}" />
<input type="submit" value="{% trans 'go'|capfirst %}" class="btn btn-secondary" />
</form>
{% if source.source__hidden %}
{% blocktrans with name=source.source__name %}{{ name }} is hidden.{% endblocktrans %}
<a href="{% url 'log_switch_source' source.source__id %}" class="btn btn-warning">{% trans 'show'|capfirst %}</a>
{% else %}
{% blocktrans with name=source.source__name %}{{ name }} is published.{% endblocktrans %}
<a href="{% url 'log_switch_source' source.source__id %}" class="btn btn-warning">{% trans 'hide'|capfirst %}</a>
{% endif %}
</div>
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

View file

@ -6,6 +6,18 @@ urlpatterns = [
path('', views.IndexView.as_view(), name='log_index'), path('', views.IndexView.as_view(), name='log_index'),
path( path(
'<slug:source>/<int:year>/<int:month>/<int:day>/', '<slug:source>/<int:year>/<int:month>/<int:day>/',
views.EntriesView.as_view(), name='log_day' views.EntriesView.as_view(),
name='log_day'
), ),
path(
'switch/source/<int:pk>/',
views.switch_source,
name='log_switch_source'
),
path(
'switch/entry/<int:pk>/',
views.switch_entry,
name='log_switch_entry'
),
path('search/', views.search_view, name='log_search'),
] ]

View file

@ -1,29 +1,86 @@
from django.contrib.admin.views.decorators import staff_member_required
from django.shortcuts import redirect, get_object_or_404
from django.db.models.functions import TruncDate from django.db.models.functions import TruncDate
from django.db.models import Count from django.db.models import Count
from django.views import generic from django.views import generic
from django.conf import settings from django.conf import settings
from django.urls import reverse
from django.http import Http404
from .models import Source, Entry from .models import Source, Entry
from .forms import SearchForm
import datetime import datetime
def _get_dates():
now = datetime.date.today()
start_date = now - datetime.timedelta(
days=settings.KHAGANAT_LOGS_MAX_DAYS
)
end_date = now - datetime.timedelta(
days=settings.KHAGANAT_LOGS_MIN_DAYS - 1
)
return (now, start_date, end_date)
def _switch_hidden(request, obj, pk):
e = get_object_or_404(obj, pk=pk)
e.hidden = not e.hidden
e.save()
next_page = request.GET.get('next', '')
if next_page == '':
next_page = reverse('log_index')
return redirect(next_page)
@staff_member_required
def switch_source(request, pk):
return _switch_hidden(request, Source, pk)
@staff_member_required
def switch_entry(request, pk):
return _switch_hidden(request, Entry, pk)
def search_view(request):
if request.method == 'POST':
form = SearchForm(request.POST)
if form.is_valid():
date = form.cleaned_data['date']
return redirect(reverse('log_day', kwargs={
'source': form.cleaned_data['source'],
'year': date.year,
'month': date.month,
'day': date.day,
}))
raise Http404('No search parameters.')
class IndexView(generic.ListView): class IndexView(generic.ListView):
template_name = 'logs/index.html' template_name = 'logs/index.html'
context_object_name = 'sources' context_object_name = 'sources'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = SearchForm()
return context
def get_queryset(self): def get_queryset(self):
now = datetime.date.today() now, start_date, end_date = _get_dates()
start_date = now - datetime.timedelta(
days=settings.KHAGANAT_LOGS_MAX_DAYS
)
end_date = now - datetime.timedelta(
days=settings.KHAGANAT_LOGS_MIN_DAYS - 1
)
out = [] out = []
qs = Entry.objects.filter( qs = Entry.objects.all()
hidden=False,
source__hidden=False, if not self.request.user.is_staff:
created__range=(start_date, end_date) qs = qs.filter(
).values('source', 'source__name', 'source__slug').annotate( hidden=False,
source__hidden=False,
created__range=(start_date, end_date)
)
qs = qs.values(
'source', 'source__name', 'source__slug',
'source__id', 'source__hidden'
).annotate(
nb=Count('id') nb=Count('id')
) )
@ -60,6 +117,7 @@ class EntriesView(generic.ListView):
return context return context
def get_queryset(self): def get_queryset(self):
is_staff = self.request.user.is_staff
dt = datetime.date( dt = datetime.date(
self.kwargs['year'], self.kwargs['year'],
self.kwargs['month'], self.kwargs['month'],
@ -70,15 +128,19 @@ class EntriesView(generic.ListView):
(now - dt).days > settings.KHAGANAT_LOGS_MAX_DAYS, (now - dt).days > settings.KHAGANAT_LOGS_MAX_DAYS,
(now - dt).days < settings.KHAGANAT_LOGS_MIN_DAYS, (now - dt).days < settings.KHAGANAT_LOGS_MIN_DAYS,
)) ))
if out_of_bounds: if out_of_bounds and not is_staff:
return Entry.objects.none() return Entry.objects.none()
src = Source.objects.get(slug=self.kwargs['source']) src = Source.objects.get(slug=self.kwargs['source'])
if src is None or src.hidden: if src is None:
return Entry.objects.none() return Entry.objects.none()
return Entry.objects.filter( if src.hidden and not is_staff:
hidden=False, return Entry.objects.none()
qs = Entry.objects.filter(
source=src, source=src,
created__year=dt.year, created__year=dt.year,
created__month=dt.month, created__month=dt.month,
created__day=dt.day created__day=dt.day
).order_by('created') )
if not is_staff:
qs = qs.filter(hidden=False)
return qs.order_by('created')

View file

@ -1,5 +1,5 @@
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.contrib.auth.tokens import default_token_generator from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string from django.template.loader import render_to_string
@ -7,7 +7,6 @@ from django.core.mail import EmailMultiAlternatives
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.conf import settings from django.conf import settings
from django.urls import reverse
from .forms import RegistrationForm from .forms import RegistrationForm
from .models import NelUser from .models import NelUser