From e34edc2e7ca0b8bf45605c481f1222feadbd4f22 Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Wed, 30 Oct 2024 22:48:53 +0100 Subject: [PATCH] =?UTF-8?q?Introduction=20des=20descriptions=20d'=C3=A9tiq?= =?UTF-8?q?uettes=20Am=C3=A9liorations=20du=20rendu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agenda_culturel/admin.py | 2 + src/agenda_culturel/migrations/0093_tag.py | 22 +++++++ .../migrations/0094_auto_20241030_2002.py | 33 ++++++++++ .../migrations/0095_alter_tag_description.py | 19 ++++++ .../migrations/0096_alter_tag_name.py | 18 ++++++ src/agenda_culturel/models.py | 24 ++++++++ src/agenda_culturel/static/style.scss | 8 ++- .../templates/agenda_culturel/page.html | 16 +++-- .../agenda_culturel/place_detail.html | 2 +- .../templates/agenda_culturel/side-nav.html | 1 - .../single-event/event-elegant-inc.html | 48 +++++++++------ .../templates/agenda_culturel/tag.html | 29 ++++++++- .../agenda_culturel/tag_confirm_delete.html | 21 +++++++ .../templates/agenda_culturel/tag_form.html | 27 ++++++++ .../templates/agenda_culturel/tags.html | 56 +++++++++++------ src/agenda_culturel/templatetags/tag_extra.py | 6 +- src/agenda_culturel/urls.py | 3 + src/agenda_culturel/views.py | 61 +++++++++++++++---- 18 files changed, 332 insertions(+), 64 deletions(-) create mode 100644 src/agenda_culturel/migrations/0093_tag.py create mode 100644 src/agenda_culturel/migrations/0094_auto_20241030_2002.py create mode 100644 src/agenda_culturel/migrations/0095_alter_tag_description.py create mode 100644 src/agenda_culturel/migrations/0096_alter_tag_name.py create mode 100644 src/agenda_culturel/templates/agenda_culturel/tag_confirm_delete.html create mode 100644 src/agenda_culturel/templates/agenda_culturel/tag_form.html diff --git a/src/agenda_culturel/admin.py b/src/agenda_culturel/admin.py index 81d5e4a..64f1c33 100644 --- a/src/agenda_culturel/admin.py +++ b/src/agenda_culturel/admin.py @@ -3,6 +3,7 @@ from django import forms from .models import ( Event, Category, + Tag, StaticContent, DuplicatedEvents, BatchImportation, @@ -17,6 +18,7 @@ from django_better_admin_arrayfield.models.fields import DynamicArrayField admin.site.register(Category) +admin.site.register(Tag) admin.site.register(StaticContent) admin.site.register(DuplicatedEvents) admin.site.register(BatchImportation) diff --git a/src/agenda_culturel/migrations/0093_tag.py b/src/agenda_culturel/migrations/0093_tag.py new file mode 100644 index 0000000..a1bce8e --- /dev/null +++ b/src/agenda_culturel/migrations/0093_tag.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.9 on 2024-10-30 17:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda_culturel', '0092_alter_categorisationrule_weight'), + ] + + operations = [ + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Tag name', max_length=512, verbose_name='Name')), + ('description', models.TextField(blank=True, help_text='Description of the tag', null=True, verbose_name='Description')), + ('principal', models.BooleanField(default=True, help_text='This tag is highlighted as a main tag for visitors, particularly in the filter.', verbose_name='Principal')), + ], + ), + ] diff --git a/src/agenda_culturel/migrations/0094_auto_20241030_2002.py b/src/agenda_culturel/migrations/0094_auto_20241030_2002.py new file mode 100644 index 0000000..ee640f1 --- /dev/null +++ b/src/agenda_culturel/migrations/0094_auto_20241030_2002.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.9 on 2024-10-30 19:02 + +from django.db import migrations +from django.contrib.auth.models import Group, Permission + +def update_groups_permissions(apps, schema_editor): + # first add a missing role + user_roles = ["Tag editor"] + + for name in user_roles: + Group.objects.create(name=name) + + all_perms = Permission.objects.all() + + # set permissions for moderators + editor_perms = [i for i in all_perms if i.content_type.app_label == 'agenda_culturel' and i.content_type.model == 'tag'] + Group.objects.get(name="Tag editor").permissions.add(*editor_perms) + +def update_groups_delete(apps, schema_editor): + user_roles = ["Tag editor"] + + for name in user_roles: + Group.objects.filter(name=name).delete() + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda_culturel', '0093_tag'), + ] + + operations = [ + migrations.RunPython(update_groups_permissions, reverse_code=update_groups_delete), + ] diff --git a/src/agenda_culturel/migrations/0095_alter_tag_description.py b/src/agenda_culturel/migrations/0095_alter_tag_description.py new file mode 100644 index 0000000..c2b6691 --- /dev/null +++ b/src/agenda_culturel/migrations/0095_alter_tag_description.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.9 on 2024-10-30 19:11 + +from django.db import migrations +import django_ckeditor_5.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda_culturel', '0094_auto_20241030_2002'), + ] + + operations = [ + migrations.AlterField( + model_name='tag', + name='description', + field=django_ckeditor_5.fields.CKEditor5Field(blank=True, help_text='Description of the tag', null=True, verbose_name='Description'), + ), + ] diff --git a/src/agenda_culturel/migrations/0096_alter_tag_name.py b/src/agenda_culturel/migrations/0096_alter_tag_name.py new file mode 100644 index 0000000..ba2ad1c --- /dev/null +++ b/src/agenda_culturel/migrations/0096_alter_tag_name.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.9 on 2024-10-30 20:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda_culturel', '0095_alter_tag_description'), + ] + + operations = [ + migrations.AlterField( + model_name='tag', + name='name', + field=models.CharField(help_text='Tag name', max_length=512, unique=True, verbose_name='Name'), + ), + ] diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index 85894e2..b187a30 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -172,6 +172,30 @@ class Category(models.Model): verbose_name_plural = _("Categories") +class Tag(models.Model): + + name = models.CharField( + verbose_name=_("Name"), help_text=_("Tag name"), max_length=512, + unique=True + ) + + description = CKEditor5Field( + verbose_name=_("Description"), + help_text=_("Description of the tag"), + blank=True, + null=True, + ) + + principal = models.BooleanField( + verbose_name=_("Principal"), + help_text=_("This tag is highlighted as a main tag for visitors, particularly in the filter."), + default=True, + ) + + def get_absolute_url(self): + return reverse("view_tag", kwargs={"t": self.name}) + + class DuplicatedEvents(models.Model): fixed = models.BooleanField( diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss index 90817d1..8b6c1f1 100644 --- a/src/agenda_culturel/static/style.scss +++ b/src/agenda_culturel/static/style.scss @@ -222,6 +222,10 @@ svg { vertical-align: -0.125em; } +.small-ephemeride { + font-size: 80%; + clear: both; +} .ephemeris { float: left; font-size: 110%; @@ -1235,7 +1239,7 @@ article { } -.a-venir, .place { +.a-venir, .place, .tag, .tag-descriptions { article#filters { margin: 2em 0; } @@ -1248,7 +1252,7 @@ article { .resume { column-count: 4; } - .single-event { + .single-event, .tag-description { display: grid; grid-template-columns: 30% auto 14em; grid-column-gap: 1em; diff --git a/src/agenda_culturel/templates/agenda_culturel/page.html b/src/agenda_culturel/templates/agenda_culturel/page.html index 617f490..13e9d92 100644 --- a/src/agenda_culturel/templates/agenda_culturel/page.html +++ b/src/agenda_culturel/templates/agenda_culturel/page.html @@ -103,23 +103,27 @@ + - {% include "agenda_culturel/side-nav.html" with current="tags" %} - +{% endcache %} +{% endwith %} {% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templatetags/tag_extra.py b/src/agenda_culturel/templatetags/tag_extra.py index 8de75fe..ea91e84 100644 --- a/src/agenda_culturel/templatetags/tag_extra.py +++ b/src/agenda_culturel/templatetags/tag_extra.py @@ -37,4 +37,8 @@ def tag_button_strike(tag, link=False): @register.filter def tag_button_link(tag): - return t_button(tag, '/?tags=' + tag, False) \ No newline at end of file + return t_button(tag, '/?tags=' + tag, False) + +@register.filter +def tag_not_in_db(tag, tags): + return len([t for t in tags if t.name == tag]) == 0 \ No newline at end of file diff --git a/src/agenda_culturel/urls.py b/src/agenda_culturel/urls.py index 76eda87..8c8f415 100644 --- a/src/agenda_culturel/urls.py +++ b/src/agenda_culturel/urls.py @@ -20,6 +20,9 @@ urlpatterns = [ path("ce-mois-ci", month_view, name="ce_mois_ci"), path("tag//", view_tag, name="view_tag"), path("tags/", tag_list, name="view_all_tags"), + path("tag//edit", TagUpdateView.as_view(), name="edit_tag"), + path("tag//delete", TagDeleteView.as_view(), name="delete_tag"), + path("tags/add", TagCreateView.as_view(), name="add_tag"), path("moderation/", moderation, name="moderation"), path( "event////-", diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py index 0ed28f8..1ecce74 100644 --- a/src/agenda_culturel/views.py +++ b/src/agenda_culturel/views.py @@ -41,6 +41,7 @@ from .forms import ( from .models import ( Event, Category, + Tag, StaticContent, ContactMessage, BatchImportation, @@ -499,19 +500,6 @@ def upcoming_events(request, year=None, month=None, day=None, neighsize=1): return render(request, "agenda_culturel/page-upcoming.html", context) -def view_tag(request, t): - events = Event.objects.filter(tags__contains=[t]).order_by( - "start_day", "start_time" - ) - context = {"tag": t, "events": events} - return render(request, "agenda_culturel/tag.html", context) - - -def tag_list(request): - tags = Event.get_all_tags() - context = {"tags": sorted(tags, key=lambda x: remove_accents(x).lower())} - return render(request, "agenda_culturel/tags.html", context) - class StaticContentCreateView(LoginRequiredMixin, CreateView): model = StaticContent @@ -2073,3 +2061,50 @@ class PlaceFromEventCreateView(PlaceCreateView): def get_success_url(self): return self.event.get_absolute_url() + + +######################### +## Tags +######################### + +class TagUpdateView(PermissionRequiredMixin, SuccessMessageMixin, UpdateView): + model = Tag + permission_required = "agenda_culturel.change_tag" + fields = ["name", "description", "principal"] + success_message = _("The tag has been successfully updated.") + + +class TagCreateView(PermissionRequiredMixin, SuccessMessageMixin, CreateView): + model = Tag + permission_required = "agenda_culturel.add_tag" + fields = ["name", "description", "principal"] + success_message = _("The tag has been successfully created.") + + def get_initial(self, *args, **kwargs): + initial = super().get_initial(**kwargs) + if "name" in self.request.GET: + initial["name"] = self.request.GET.get("name") + return initial + + +class TagDeleteView(PermissionRequiredMixin, DeleteView): + model = Tag + permission_required = "agenda_culturel.delete_tag" + success_url = reverse_lazy("view_all_tags") + + +def view_tag(request, t): + events = Event.objects.filter(tags__contains=[t]).order_by( + "start_day", "start_time" + ) + tag = Tag.objects.filter(name=t).first() + context = {"tag": t, "events": events, "object": tag} + return render(request, "agenda_culturel/tag.html", context) + + +def tag_list(request): + tags = Event.get_all_tags() + objects = Tag.objects.order_by("name").all() + context = {"other_tags": sorted(tags, key=lambda x: remove_accents(x).lower()), + "tags": objects} + return render(request, "agenda_culturel/tags.html", context) \ No newline at end of file