diff --git a/config/settings/base.py b/config/settings/base.py index aaa01876b..6e66ad4a7 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -449,3 +449,8 @@ "sync-xhr": [], "usb": [], } + +# forum_stats +# --------------------------------------- + +SEARCH_COLLECTION_PERIOD_DAYS = 30 diff --git a/lacommunaute/forum_stats/admin.py b/lacommunaute/forum_stats/admin.py index ad7d441cf..66197245e 100644 --- a/lacommunaute/forum_stats/admin.py +++ b/lacommunaute/forum_stats/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from lacommunaute.forum_stats.models import Stat +from lacommunaute.forum_stats.models import SearchCollectionPeriod, SearchQuery, Stat class StatAdmin(admin.ModelAdmin): @@ -8,4 +8,14 @@ class StatAdmin(admin.ModelAdmin): list_filter = ("name", "date", "period") +class SearchCollectionPeriodAdmin(admin.ModelAdmin): + list_display = ("name", "start_date", "end_date") + + +class SearchQueryAdmin(admin.ModelAdmin): + list_display = ("period", "nb_visits") + + admin.site.register(Stat, StatAdmin) +admin.site.register(SearchCollectionPeriod, SearchCollectionPeriodAdmin) +admin.site.register(SearchQuery, SearchQueryAdmin) diff --git a/lacommunaute/forum_stats/factories.py b/lacommunaute/forum_stats/factories.py index 645cca2b6..d7771e30d 100644 --- a/lacommunaute/forum_stats/factories.py +++ b/lacommunaute/forum_stats/factories.py @@ -2,9 +2,10 @@ import factory import factory.django +from django.conf import settings from lacommunaute.forum_stats.enums import Period -from lacommunaute.forum_stats.models import Stat +from lacommunaute.forum_stats.models import SearchCollectionPeriod, SearchQuery, Stat class StatFactory(factory.django.DjangoModelFactory): @@ -23,3 +24,27 @@ class Params: value=46, period="day", ) + + +class SearchCollectionPeriodFactory(factory.django.DjangoModelFactory): + class Meta: + model = SearchCollectionPeriod + + name = factory.Faker("word") + start_date = factory.Faker("date") + + @factory.lazy_attribute + def end_date(self): + return ( + datetime.datetime.strptime(self.start_date, "%Y-%m-%d") + + datetime.timedelta(days=settings.SEARCH_COLLECTION_PERIOD_DAYS) + ).date() + + +class SearchQueryFactory(factory.django.DjangoModelFactory): + class Meta: + model = SearchQuery + + label = factory.Faker("word") + period = factory.SubFactory(SearchCollectionPeriodFactory) + nb_visits = factory.Faker("random_int", min=1, max=10) diff --git a/lacommunaute/forum_stats/migrations/0002_searchcollectionperiod_usersearch.py b/lacommunaute/forum_stats/migrations/0002_searchcollectionperiod_usersearch.py new file mode 100644 index 000000000..1e6bb599b --- /dev/null +++ b/lacommunaute/forum_stats/migrations/0002_searchcollectionperiod_usersearch.py @@ -0,0 +1,49 @@ +# Generated by Django 5.0.6 on 2024-06-17 16:54 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("forum_stats", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="SearchCollectionPeriod", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("name", models.CharField(max_length=256, verbose_name="Name")), + ("start_date", models.DateField(help_text="The start of the period", verbose_name="Start date")), + ("end_date", models.DateField(help_text="The end of the period", verbose_name="End date")), + ], + options={ + "verbose_name": "Search Collection Period", + "verbose_name_plural": "Search Collection Periods", + "ordering": ["-end_date", "-start_date"], + "unique_together": {("start_date", "end_date")}, + }, + ), + migrations.CreateModel( + name="SearchQuery", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("label", models.TextField(help_text="The search query made by the user")), + ("nb_visits", models.PositiveIntegerField(verbose_name="Number visits")), + ( + "period", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="searches", + to="forum_stats.searchcollectionperiod", + ), + ), + ], + options={ + "verbose_name": "Search Query", + "verbose_name_plural": "Search Queries", + "ordering": ["-period", "label"], + }, + ), + ] diff --git a/lacommunaute/forum_stats/models.py b/lacommunaute/forum_stats/models.py index dd01c2cba..8857653f9 100644 --- a/lacommunaute/forum_stats/models.py +++ b/lacommunaute/forum_stats/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.utils.translation import gettext_lazy as _ from lacommunaute.forum_stats.enums import Period @@ -31,3 +32,39 @@ def __str__(self): return f"{self.name} - {self.date} - {self.period}" objects = StatQuerySet().as_manager() + + +class SearchCollectionPeriod(models.Model): + name = models.CharField(max_length=256, verbose_name=_("Name")) + start_date = models.DateField(verbose_name=_("Start date"), help_text=_("The start of the period")) + end_date = models.DateField(verbose_name=_("End date"), help_text=_("The end of the period")) + + class Meta: + verbose_name = _("Search Collection Period") + verbose_name_plural = _("Search Collection Periods") + ordering = ["-end_date", "-start_date"] + unique_together = ("start_date", "end_date") + + def __str__(self): + return f"Period {str(self.name)} ({str(self.start_date)} - {str(self.end_date)})" + + +class SearchQuery(models.Model): + """ + Matomo logs for us the searches made by users visiting the site. + We collect searches made during a period and store them for interpretation + """ + + label = models.TextField(help_text=_("The search query made by the user")) + period = models.ForeignKey( + SearchCollectionPeriod, related_name="searches", on_delete=models.CASCADE, db_index=True + ) + nb_visits = models.PositiveIntegerField(verbose_name=_("Number visits")) + + class Meta: + verbose_name = _("Search Query") + verbose_name_plural = _("Search Queries") + ordering = ["-period", "label"] + + def __str__(self): + return f"Search from {str(self.period)}" diff --git a/lacommunaute/forum_stats/tests/tests_search_collection.py b/lacommunaute/forum_stats/tests/tests_search_collection.py new file mode 100644 index 000000000..e69de29bb diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo index 00fb78b10..672905262 100644 Binary files a/locale/fr/LC_MESSAGES/django.mo and b/locale/fr/LC_MESSAGES/django.mo differ diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 07b07876b..063dedc77 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -46,6 +46,46 @@ msgstr "Motif du blocage" msgid "Poster" msgstr "Auteur" +#: lacommunaute/forum_stats/models.py +msgid "Start date" +msgstr "Date de début" + +#: lacommunaute/forum_stats/models.py +msgid "The start of the period" +msgstr "Le début de la période" + +#: lacommunaute/forum_stats/models.py +msgid "End date" +msgstr "Date de fin" + +#: lacommunaute/forum_stats/models.py +msgid "The end of the period" +msgstr "La fin de la période" + +#: lacommunaute/forum_stats/models.py +msgid "Search Collection Period" +msgstr "Recherche Période de collecte" + +#: lacommunaute/forum_stats/models.py +msgid "Search Collection Periods" +msgstr "Recherche de Périodes de collecte" + +#: lacommunaute/forum_stats/models.py +msgid "The search query made by the user" +msgstr "La requête de recherche effectuée par l'utilisateur" + +#: lacommunaute/forum_stats/models.py +msgid "Number visits" +msgstr "Nombre de visites" + +#: lacommunaute/forum_stats/models.py +msgid "Search Query" +msgstr "Recherche" + +#: lacommunaute/forum_stats/models.py +msgid "Search Queries" +msgstr "Recherches" + #: lacommunaute/search/forms.py:24 msgid "Keywords or phrase" msgstr "Mots clés ou phrase" @@ -77,6 +117,7 @@ msgid "Global forum permissions" msgstr "Autorisations globales des communautés" #: lacommunaute/templates/admin/forum/forum/change_list_table.html:9 +#: lacommunaute/forum_stats/models.py msgid "Name" msgstr "Nom"