Add the log app

This commit is contained in:
Rodolphe Breard 2018-01-27 18:58:36 +01:00
parent fc0ebef9cb
commit 2d40a57613
18 changed files with 272 additions and 0 deletions

View file

@ -30,3 +30,5 @@ You can set the following variables in the `.env` file:
* `KHAGANAT_TIME_ZONE`: Time zone, default is `Europe/Paris`.
* `KHAGANAT_STATIC_URL`: URL for static files, default is `/static/`.
* `KHAGANAT_STATIC_ROOT`: Absolute path to the directory where static files should be collected.
* `KHAGANAT_LOGS_MIN_DAYS`: Numbers of days before logs are hidden, default is 7.
* `KHAGANAT_LOGS_MAX_DAYS`: Number of days before logs are published, default is 0.

View file

@ -41,6 +41,7 @@ INSTALLED_APPS = [
'khaganat',
'pages.apps.PagesConfig',
'navbar.apps.NavbarConfig',
'logs.apps.LogsConfig',
]
MIDDLEWARE = [
@ -131,3 +132,7 @@ USE_TZ = True
STATIC_URL = os.getenv('KHAGANAT_STATIC_URL', default='/static/')
STATIC_ROOT = os.getenv('KHAGANAT_STATIC_ROOT', default='') or None
# Logs configuration
KHAGANAT_LOGS_MIN_DAYS = int(os.getenv('KHAGANAT_LOGS_MIN_DAYS', default='0'))
KHAGANAT_LOGS_MAX_DAYS = int(os.getenv('KHAGANAT_LOGS_MAX_DAYS', default='7'))

View file

@ -27,4 +27,5 @@ urlpatterns = [
urlpatterns += i18n_patterns(
path('', index),
path('page/', include('pages.urls')),
path('logs/', include('logs.urls')),
)

0
logs/__init__.py Normal file
View file

5
logs/admin.py Normal file
View file

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

5
logs/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class LogsConfig(AppConfig):
name = 'logs'

View file

@ -0,0 +1,25 @@
msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-27 18:32+0100\n"
"PO-Revision-Date: 2018-01-27 18:35+1\n"
"Last-Translator: Rodolphe Bréard <rodolphe@what.tf>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n"
"Language: English\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/logs/entries.html:10 templates/logs/entries.html:18
msgid "logs_back"
msgstr "Back"
#: templates/logs/index.html:4 templates/logs/index.html:8
msgid "logs_title"
msgstr "Khaganat's logs"
#: templates/logs/index.html:33
msgid "logs_no_logs_available"
msgstr "No logs available."

View file

@ -0,0 +1,25 @@
msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-27 18:32+0100\n"
"PO-Revision-Date: 2018-01-27 18:35+1\n"
"Last-Translator: Rodolphe Bréard <rodolphe@what.tf>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n"
"Language: Français\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: templates/logs/entries.html:10 templates/logs/entries.html:18
msgid "logs_back"
msgstr "Retour"
#: templates/logs/index.html:4 templates/logs/index.html:8
msgid "logs_title"
msgstr "Journaux de conversation de Khaganat"
#: templates/logs/index.html:33
msgid "logs_no_logs_available"
msgstr "Aucun journal de conversation disponible."

View file

@ -0,0 +1,38 @@
# Generated by Django 2.0.1 on 2018-01-27 13:35
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Entry',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('hidden', models.BooleanField(default=False)),
('created', models.DateTimeField()),
('nick', models.CharField(max_length=128)),
('content', models.CharField(max_length=2048)),
],
),
migrations.CreateModel(
name='Source',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128)),
('hidden', models.BooleanField(default=False)),
],
),
migrations.AddField(
model_name='entry',
name='source',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='logs.Source'),
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 2.0.1 on 2018-01-27 15:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('logs', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='source',
name='slug',
field=models.CharField(default='', max_length=128),
preserve_default=False,
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 2.0.1 on 2018-01-27 16:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('logs', '0002_source_slug'),
]
operations = [
migrations.AlterField(
model_name='source',
name='slug',
field=models.CharField(max_length=128, unique=True),
),
]

View file

17
logs/models.py Normal file
View file

@ -0,0 +1,17 @@
from django.db import models
class Source(models.Model):
name = models.CharField(max_length=128)
slug = models.CharField(max_length=128, unique=True)
hidden = models.BooleanField(default=False)
def __str__(self):
return self.name
class Entry(models.Model):
source = models.ForeignKey(Source, on_delete=models.CASCADE)
hidden = models.BooleanField(default=False)
created = models.DateTimeField()
nick = models.CharField(max_length=128)
content = models.CharField(max_length=2048)

View file

@ -0,0 +1,21 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{{ source_channel.name }}{% endblock %}
{% block content %}
<div class="content-bloc">
<h2>{{ source_channel.name }} ({{ date }})</h2>
<div>
<a class="btn btn-primary" href="{% url 'log_index' %}" role="button">{% trans "logs_back" %}</a>
</div>
<div>
{% for entry in entries%}
{{ entry.created|date:"H:i:s" }} &lt;{{ entry.nick }}&gt; {{ entry.content }}<br />
{% endfor %}
</div>
<div>
<a class="btn btn-primary" href="{% url 'log_index' %}" role="button">{% trans "logs_back" %}</a>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,36 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "logs_title" %}{% endblock %}
{% block content %}
<div class="content-bloc">
<h2>{% trans "logs_title" %}</h2>
{% if sources %}
<div class="row">
<div class="col-4">
<div class="list-group" id="list-tab" role="tablist">
{% for source in sources %}
<a class="list-group-item list-group-item-action" id="list-{{ source.source }}-list" data-toggle="list" href="#list-{{ source.source }}" role="tab" aria-controls="home">{{ source.source__name }}</a>
{% endfor %}
</div>
</div>
<div class="col-8">
<div class="tab-content" id="nav-tabContent">
{% for source in sources %}
<div class="tab-pane fade show" id="list-{{ source.source }}" role="tabpanel" aria-labelledby="list-{{ source.source }}-list">
<div class="list-group">
{% 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>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% else %}
<p>{% trans "logs_no_logs_available" %}</p>
{% endif %}
</div>
{% endblock %}

3
logs/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

8
logs/urls.py Normal file
View file

@ -0,0 +1,8 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.IndexView.as_view(), name='log_index'),
path('<slug:source>/<int:year>/<int:month>/<int:day>/', views.EntriesView.as_view(), name='log_day'),
]

44
logs/views.py Normal file
View file

@ -0,0 +1,44 @@
from django.db.models.functions import TruncDate
from django.db.models import Count
from django.views import generic
from django.conf import settings
from .models import Source,Entry
import datetime
class IndexView(generic.ListView):
template_name = 'logs/index.html'
context_object_name = 'sources'
def get_queryset(self):
now = datetime.date.today()
begin_date = now - datetime.timedelta(days=settings.KHAGANAT_LOGS_MAX_DAYS)
end_date = now - datetime.timedelta(days=settings.KHAGANAT_LOGS_MIN_DAYS - 1)
out = []
for src in Entry.objects.filter(hidden=False, source__hidden=False, created__range=(begin_date, end_date)).values('source', 'source__name', 'source__slug').annotate(nb=Count('id')):
src['stats'] = Entry.objects.filter(hidden=False, source=src['source'], created__range=(begin_date, end_date)).annotate(date=TruncDate('created')).values('date').annotate(nb=Count('date')).order_by('-date')
out.append(src)
return out
class EntriesView(generic.ListView):
context_object_name = 'entries'
template_name = 'logs/entries.html'
allow_empty = False
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['date'] = datetime.date(self.kwargs['year'], self.kwargs['month'], self.kwargs['day'])
context['source_channel'] = Source.objects.get(slug=self.kwargs['source']),
if isinstance(context['source_channel'], tuple):
context['source_channel'] = context['source_channel'][0]
return context
def get_queryset(self):
dt = datetime.date(self.kwargs['year'], self.kwargs['month'], self.kwargs['day'])
now = datetime.date.today()
if (now - dt).days > settings.KHAGANAT_LOGS_MAX_DAYS or (now - dt).days < settings.KHAGANAT_LOGS_MIN_DAYS:
return Entry.objects.none()
src = Source.objects.get(slug=self.kwargs['source'])
if src is None or src.hidden:
return Entry.objects.none()
return Entry.objects.filter(hidden=False, source=src, created__year=dt.year, created__month=dt.month, created__day=dt.day).order_by('created')