From 4e9ac573acc25b9d9d64648a7afea846c2995481 Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 11:42:29 +0100
Subject: [PATCH 01/85] Consolidation en cas d'appel avec simple downloader
---
src/agenda_culturel/import_tasks/generic_extractors.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/agenda_culturel/import_tasks/generic_extractors.py b/src/agenda_culturel/import_tasks/generic_extractors.py
index 10803c9..02f808f 100644
--- a/src/agenda_culturel/import_tasks/generic_extractors.py
+++ b/src/agenda_culturel/import_tasks/generic_extractors.py
@@ -264,7 +264,8 @@ class TwoStepsExtractorNoPause(TwoStepsExtractor):
only_future=True,
ignore_404=True
):
- pause = self.downloader.pause
+ if hasattr(self.downloader, "pause"):
+ pause = self.downloader.pause
self.downloader.pause = False
result = super().extract(content, url, url_human, default_values, published, only_future, ignore_404)
self.downloader.pause = pause
From 7120da3e2891a72e5991b8a13aeb2f5e6ba9cd4f Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 11:44:40 +0100
Subject: [PATCH 02/85] =?UTF-8?q?On=20d=C3=A9fini=20une=20valeur=20par=20d?=
=?UTF-8?q?=C3=A9faut?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/agenda_culturel/import_tasks/generic_extractors.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/agenda_culturel/import_tasks/generic_extractors.py b/src/agenda_culturel/import_tasks/generic_extractors.py
index 02f808f..14acc44 100644
--- a/src/agenda_culturel/import_tasks/generic_extractors.py
+++ b/src/agenda_culturel/import_tasks/generic_extractors.py
@@ -265,7 +265,9 @@ class TwoStepsExtractorNoPause(TwoStepsExtractor):
ignore_404=True
):
if hasattr(self.downloader, "pause"):
- pause = self.downloader.pause
+ pause = self.downloader.pause
+ else:
+ pause = False
self.downloader.pause = False
result = super().extract(content, url, url_human, default_values, published, only_future, ignore_404)
self.downloader.pause = pause
From 1256adcb8af7c4577a5546b99e0ace38067eaa6b Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 12:16:02 +0100
Subject: [PATCH 03/85] On ajoute un parse de plus pour les dates
---
src/agenda_culturel/import_tasks/extractor.py | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/agenda_culturel/import_tasks/extractor.py b/src/agenda_culturel/import_tasks/extractor.py
index 3e75870..6822b47 100644
--- a/src/agenda_culturel/import_tasks/extractor.py
+++ b/src/agenda_culturel/import_tasks/extractor.py
@@ -49,7 +49,7 @@ class Extractor(ABC):
return i + 1
return None
- def parse_french_date(text):
+ def parse_french_date(text, default_year=None):
# format NomJour Numero Mois Année
m = re.search(
"[a-zA-ZéÉûÛ:.]+[ ]*([0-9]+)[er]*[ ]*([a-zA-ZéÉûÛ:.]+)[ ]*([0-9]+)", text
@@ -73,8 +73,15 @@ class Extractor(ABC):
month = int(m.group(2))
year = m.group(3)
else:
- # TODO: consolider les cas non satisfaits
- return None
+ # format Numero Mois Annee
+ m = re.search("([0-9]+)[er]*[ ]*([a-zA-ZéÉûÛ:.]+)", text)
+ if m:
+ day = m.group(1)
+ month = Extractor.guess_month(m.group(2))
+ year = default_year
+ else:
+ # TODO: consolider les cas non satisfaits
+ return None
if month is None:
return None
From bf773686f9661e55b9730a393e1c515189faaeef Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 12:43:20 +0100
Subject: [PATCH 04/85] L'image a une url absolue
---
src/agenda_culturel/models.py | 7 +++++--
.../templates/agenda_culturel/page-event.html | 2 +-
src/agenda_culturel/templatetags/event_extra.py | 6 +++++-
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py
index d7b3909..9554190 100644
--- a/src/agenda_culturel/models.py
+++ b/src/agenda_culturel/models.py
@@ -923,10 +923,13 @@ class Event(models.Model):
else:
return recurrences[0]
- def get_image_url(self):
+ def get_image_url(self, request=None):
if self.local_image and hasattr(self.local_image, "url"):
try:
- return self.local_image.url
+ if request:
+ return request.build_absolute_uri(self.local_image.url)
+ else:
+ return self.local_image.url
except:
pass
if self.image:
diff --git a/src/agenda_culturel/templates/agenda_culturel/page-event.html b/src/agenda_culturel/templates/agenda_culturel/page-event.html
index 142defe..42f0276 100644
--- a/src/agenda_culturel/templates/agenda_culturel/page-event.html
+++ b/src/agenda_culturel/templates/agenda_culturel/page-event.html
@@ -6,7 +6,7 @@
{% block title %}{% block og_title %}{{ event.title }}{% endblock %}{% endblock %}
-{% block og_image %}{% if event.has_image_url %}{{ event.get_image_url }}{% else %}{{ block.super }}{% endif %}{% endblock %}
+{% block og_image %}{% if event.has_image_url %}{{ event|get_image_uri:request }}{% else %}{{ block.super }}{% endif %}{% endblock %}
{% block og_description %}{% if event.description %}{{ event.description |truncatewords:20|linebreaks }}{% else %}{{ block.super }}{% endif %}{% endblock %}
{% block entete_header %}
diff --git a/src/agenda_culturel/templatetags/event_extra.py b/src/agenda_culturel/templatetags/event_extra.py
index 32bdee7..4dd5be9 100644
--- a/src/agenda_culturel/templatetags/event_extra.py
+++ b/src/agenda_culturel/templatetags/event_extra.py
@@ -179,4 +179,8 @@ def tw_badge(event):
if event.tags and len([t for t in event.tags if t.startswith("TW:")]) > 0:
return mark_safe('TW')
else:
- return ""
\ No newline at end of file
+ return ""
+
+@register.filter
+def get_image_uri(event, request):
+ return event.get_image_url(request)
\ No newline at end of file
From ac3d6796cff7713b82d204aabc06bbdd1280884f Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 14:57:29 +0100
Subject: [PATCH 05/85] Ajout de l'import Rio
Fix #187
---
experimentations/get_le_rio.py | 43 +++++++++
src/agenda_culturel/celery.py | 2 +
.../import_tasks/custom_extractors/lerio.py | 91 +++++++++++++++++++
.../0122_alter_recurrentimport_processor.py | 18 ++++
src/agenda_culturel/models.py | 1 +
5 files changed, 155 insertions(+)
create mode 100755 experimentations/get_le_rio.py
create mode 100644 src/agenda_culturel/import_tasks/custom_extractors/lerio.py
create mode 100644 src/agenda_culturel/migrations/0122_alter_recurrentimport_processor.py
diff --git a/experimentations/get_le_rio.py b/experimentations/get_le_rio.py
new file mode 100755
index 0000000..35e0364
--- /dev/null
+++ b/experimentations/get_le_rio.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python3
+# coding: utf-8
+
+import os
+import json
+import sys
+
+# getting the name of the directory
+# where the this file is present.
+current = os.path.dirname(os.path.realpath(__file__))
+
+# Getting the parent directory name
+# where the current directory is present.
+parent = os.path.dirname(current)
+
+# adding the parent directory to
+# the sys.path.
+sys.path.append(parent)
+
+from src.agenda_culturel.import_tasks.downloader import *
+from src.agenda_culturel.import_tasks.extractor import *
+from src.agenda_culturel.import_tasks.importer import *
+from src.agenda_culturel.import_tasks.custom_extractors import *
+
+
+
+
+
+if __name__ == "__main__":
+
+ u2e = URL2Events(SimpleDownloader(), lerio.CExtractor())
+ url = "https://www.cinemalerio.com/evenements/"
+ url_human = "https://www.cinemalerio.com/evenements/"
+
+ try:
+ events = u2e.process(url, url_human, cache = "cache-le-rio.html", default_values = {"location": "Cinéma le Rio", "category": "Cinéma"}, published = True)
+
+ exportfile = "events-le-roi.json"
+ print("Saving events to file {}".format(exportfile))
+ with open(exportfile, "w") as f:
+ json.dump(events, f, indent=4, default=str)
+ except Exception as e:
+ print("Exception: " + str(e))
diff --git a/src/agenda_culturel/celery.py b/src/agenda_culturel/celery.py
index b435900..f3ffaeb 100644
--- a/src/agenda_culturel/celery.py
+++ b/src/agenda_culturel/celery.py
@@ -147,6 +147,8 @@ def run_recurrent_import_internal(rimport, downloader, req_id):
extractor = c3c.CExtractor()
elif rimport.processor == RecurrentImport.PROCESSOR.ARACHNEE:
extractor = arachnee.CExtractor()
+ elif rimport.processor == RecurrentImport.PROCESSOR.LERIO:
+ extractor = lerio.CExtractor()
else:
extractor = None
diff --git a/src/agenda_culturel/import_tasks/custom_extractors/lerio.py b/src/agenda_culturel/import_tasks/custom_extractors/lerio.py
new file mode 100644
index 0000000..117693c
--- /dev/null
+++ b/src/agenda_culturel/import_tasks/custom_extractors/lerio.py
@@ -0,0 +1,91 @@
+from ..generic_extractors import *
+from bs4 import BeautifulSoup
+from datetime import datetime
+
+# A class dedicated to get events from Cinéma Le Rio (Clermont-Ferrand)
+# URL: https://www.cinemalerio.com/evenements/
+class CExtractor(TwoStepsExtractorNoPause):
+
+ def __init__(self):
+ super().__init__()
+ self.possible_dates = {}
+ self.theater = None
+
+ def build_event_url_list(self, content, infuture_days=180):
+
+ soup = BeautifulSoup(content, "html.parser")
+
+ links = soup.select("td.seance_link a")
+ if links:
+ for l in links:
+ print(l["href"])
+ self.add_event_url(l["href"])
+
+ def to_text_select_one(soup, filter):
+ e = soup.select_one(filter)
+ if e is None:
+ return None
+ else:
+ return e.text
+
+ def add_event_from_content(
+ self,
+ event_content,
+ event_url,
+ url_human=None,
+ default_values=None,
+ published=False,
+ ):
+
+ soup = BeautifulSoup(event_content, "html.parser")
+
+ title = soup.select_one("h1").text
+
+ alerte_date = CExtractor.to_text_select_one(soup, ".alerte_date")
+ if alerte_date is None:
+ return
+ dh = alerte_date.split("à")
+ # if date is not found, we skip
+ if len(dh) != 2:
+ return
+
+ date = Extractor.parse_french_date(dh[0], default_year=datetime.now().year)
+ time = Extractor.parse_french_time(dh[1])
+
+ synopsis = CExtractor.to_text_select_one(soup, ".synopsis_bloc")
+ special_titre = CExtractor.to_text_select_one(soup, ".alerte_titre")
+ special = CExtractor.to_text_select_one(soup, ".alerte_text")
+
+ # it's not a specific event: we skip it
+ special_lines = None if special is None else special.split('\n')
+ if special is None or len(special_lines) == 0 or \
+ (len(special_lines) == 1 and special_lines[0].strip().startswith('En partenariat')):
+ return
+
+ description = "\n\n".join([x for x in [synopsis, special_titre, special] if not x is None])
+
+ image = soup.select_one(".col1 img")
+ image_alt = None
+ if not image is None:
+ image_alt = image["alt"]
+ image = image["src"]
+
+ self.add_event_with_props(
+ default_values,
+ event_url,
+ title,
+ None,
+ date,
+ None,
+ description,
+ [],
+ recurrences=None,
+ uuids=[event_url],
+ url_human=event_url,
+ start_time=time,
+ end_day=None,
+ end_time=None,
+ published=published,
+ image=image,
+ image_alt=image_alt
+ )
\ No newline at end of file
diff --git a/src/agenda_culturel/migrations/0122_alter_recurrentimport_processor.py b/src/agenda_culturel/migrations/0122_alter_recurrentimport_processor.py
new file mode 100644
index 0000000..0758649
--- /dev/null
+++ b/src/agenda_culturel/migrations/0122_alter_recurrentimport_processor.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.9 on 2024-11-29 13:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('agenda_culturel', '0121_contactmessage_related_event'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='recurrentimport',
+ name='processor',
+ field=models.CharField(choices=[('ical', 'ical'), ('icalnobusy', 'ical no busy'), ('icalnovc', 'ical no VC'), ('lacoope', 'lacoope.org'), ('lacomedie', 'la comédie'), ('lefotomat', 'le fotomat'), ('lapucealoreille', "la puce à l'oreille"), ('Plugin wordpress MEC', 'Plugin wordpress MEC'), ('Facebook events', "Événements d'une page FB"), ('cour3coquins', 'la cour des 3 coquins'), ('arachnee', 'Arachnée concert'), ('rio', 'Le Rio')], default='ical', max_length=20, verbose_name='Processor'),
+ ),
+ ]
diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py
index 9554190..03aeba3 100644
--- a/src/agenda_culturel/models.py
+++ b/src/agenda_culturel/models.py
@@ -1767,6 +1767,7 @@ class RecurrentImport(models.Model):
FBEVENTS = "Facebook events", _("Événements d'une page FB")
C3C = "cour3coquins", _("la cour des 3 coquins")
ARACHNEE = "arachnee", _("Arachnée concert")
+ LERIO = "rio", _('Le Rio')
class DOWNLOADER(models.TextChoices):
SIMPLE = "simple", _("simple")
From c55ed5c4dc3668310a3097248c224a409c273f1a Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 15:44:20 +0100
Subject: [PATCH 06/85] Mise en forme recherche lieu
---
.../templates/agenda_culturel/organisation_form.html | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/agenda_culturel/templates/agenda_culturel/organisation_form.html b/src/agenda_culturel/templates/agenda_culturel/organisation_form.html
index 07116f5..c358c5b 100644
--- a/src/agenda_culturel/templates/agenda_culturel/organisation_form.html
+++ b/src/agenda_culturel/templates/agenda_culturel/organisation_form.html
@@ -35,12 +35,8 @@
const places = document.querySelector('#id_principal_place');
const choices_places = new Choices(places,
{
- placeholderValue: 'Sélectionner le lieu principal ',
- allowHTML: true,
- delimiter: ',',
- removeItemButton: true,
shouldSort: false,
- }
+ }
);
From 7f1bbabebfd24d02c7e27b741fe6900f895b969b Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 19:35:45 +0100
Subject: [PATCH 07/85] On enregistre l'auteur d'une modification
Fix #228
---
src/agenda_culturel/celery.py | 8 +--
src/agenda_culturel/db_importer.py | 6 ++-
src/agenda_culturel/forms.py | 6 ++-
...by_user_event_imported_by_user_and_more.py | 36 +++++++++++++
src/agenda_culturel/models.py | 52 ++++++++++++++++++-
.../agenda_culturel/event-info-inc.html | 8 +--
.../agenda_culturel/event_form_moderate.html | 2 +-
src/agenda_culturel/views.py | 11 ++--
8 files changed, 113 insertions(+), 16 deletions(-)
create mode 100644 src/agenda_culturel/migrations/0123_event_created_by_user_event_imported_by_user_and_more.py
diff --git a/src/agenda_culturel/celery.py b/src/agenda_culturel/celery.py
index f3ffaeb..67672bb 100644
--- a/src/agenda_culturel/celery.py
+++ b/src/agenda_culturel/celery.py
@@ -291,7 +291,7 @@ def weekly_imports(self):
run_recurrent_imports_from_list([imp.pk for imp in imports])
@app.task(base=ChromiumTask, bind=True)
-def import_events_from_url(self, url, cat, tags, force=False):
+def import_events_from_url(self, url, cat, tags, force=False, user_id=None):
from .db_importer import DBImporterEvents
from agenda_culturel.models import RecurrentImport, BatchImportation
from agenda_culturel.models import Event, Category
@@ -337,7 +337,7 @@ def import_events_from_url(self, url, cat, tags, force=False):
json_events = json.dumps(events, default=str)
# import events (from json)
- success, error_message = importer.import_events(json_events)
+ success, error_message = importer.import_events(json_events, user_id)
# finally, close task
close_import_task(self.request.id, success, error_message, importer)
@@ -354,14 +354,14 @@ def import_events_from_url(self, url, cat, tags, force=False):
@app.task(base=ChromiumTask, bind=True)
-def import_events_from_urls(self, urls_cat_tags):
+def import_events_from_urls(self, urls_cat_tags, user_id=None):
for ucat in urls_cat_tags:
if ucat is not None:
url = ucat[0]
cat = ucat[1]
tags = ucat[2]
- import_events_from_url.delay(url, cat, tags)
+ import_events_from_url.delay(url, cat, tags, user_id=user_id)
app.conf.beat_schedule = {
diff --git a/src/agenda_culturel/db_importer.py b/src/agenda_culturel/db_importer.py
index de38ce8..24e9c22 100644
--- a/src/agenda_culturel/db_importer.py
+++ b/src/agenda_culturel/db_importer.py
@@ -11,6 +11,7 @@ class DBImporterEvents:
def __init__(self, celery_id):
self.celery_id = celery_id
self.error_message = ""
+ self.user_id = None
self.init_result_properties()
self.today = timezone.now().date().isoformat()
@@ -34,9 +35,10 @@ class DBImporterEvents:
def get_nb_removed_events(self):
return self.nb_removed
- def import_events(self, json_structure):
+ def import_events(self, json_structure, user_id=None):
print(json_structure)
self.init_result_properties()
+ self.user_id = user_id
try:
structure = json.loads(json_structure)
@@ -95,7 +97,7 @@ class DBImporterEvents:
def save_imported(self):
self.db_event_objects, self.nb_updated, self.nb_removed = Event.import_events(
- self.event_objects, remove_missing_from_source=self.url
+ self.event_objects, remove_missing_from_source=self.url, user_id=self.user_id
)
def is_valid_event_structure(self, event):
diff --git a/src/agenda_culturel/forms.py b/src/agenda_culturel/forms.py
index f93b4db..314ad20 100644
--- a/src/agenda_culturel/forms.py
+++ b/src/agenda_culturel/forms.py
@@ -205,7 +205,11 @@ class EventForm(GroupFormMixin, ModelForm):
"modified_date",
"moderated_date",
"import_sources",
- "image"
+ "image",
+ "moderated_by_user",
+ "modified_by_user",
+ "created_by_user",
+ "imported_by_user"
]
widgets = {
"start_day": TextInput(
diff --git a/src/agenda_culturel/migrations/0123_event_created_by_user_event_imported_by_user_and_more.py b/src/agenda_culturel/migrations/0123_event_created_by_user_event_imported_by_user_and_more.py
new file mode 100644
index 0000000..a8359ce
--- /dev/null
+++ b/src/agenda_culturel/migrations/0123_event_created_by_user_event_imported_by_user_and_more.py
@@ -0,0 +1,36 @@
+# Generated by Django 4.2.9 on 2024-11-29 18:18
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('agenda_culturel', '0122_alter_recurrentimport_processor'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='event',
+ name='created_by_user',
+ field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='created_events', to=settings.AUTH_USER_MODEL, verbose_name='Author of the event creation'),
+ ),
+ migrations.AddField(
+ model_name='event',
+ name='imported_by_user',
+ field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='imported_events', to=settings.AUTH_USER_MODEL, verbose_name='Author of the last importation'),
+ ),
+ migrations.AddField(
+ model_name='event',
+ name='moderated_by_user',
+ field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='moderated_events', to=settings.AUTH_USER_MODEL, verbose_name='Author of the last moderation'),
+ ),
+ migrations.AddField(
+ model_name='event',
+ name='modified_by_user',
+ field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='modified_events', to=settings.AUTH_USER_MODEL, verbose_name='Author of the last modification'),
+ ),
+ ]
diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py
index 03aeba3..40792ae 100644
--- a/src/agenda_culturel/models.py
+++ b/src/agenda_culturel/models.py
@@ -10,6 +10,7 @@ from colorfield.fields import ColorField
from django_ckeditor_5.fields import CKEditor5Field
from urllib.parse import urlparse
from django.core.cache import cache
+from django.contrib.auth.models import User
import emoji
import hashlib
@@ -558,6 +559,39 @@ class Event(models.Model):
modified_date = models.DateTimeField(blank=True, null=True)
moderated_date = models.DateTimeField(blank=True, null=True)
+ created_by_user = models.ForeignKey(
+ User,
+ verbose_name=_("Author of the event creation"),
+ null=True,
+ default=None,
+ on_delete=models.SET_DEFAULT,
+ related_name="created_events"
+ )
+ imported_by_user = models.ForeignKey(
+ User,
+ verbose_name=_("Author of the last importation"),
+ null=True,
+ default=None,
+ on_delete=models.SET_DEFAULT,
+ related_name="imported_events"
+ )
+ modified_by_user = models.ForeignKey(
+ User,
+ verbose_name=_("Author of the last modification"),
+ null=True,
+ default=None,
+ on_delete=models.SET_DEFAULT,
+ related_name="modified_events"
+ )
+ moderated_by_user = models.ForeignKey(
+ User,
+ verbose_name=_("Author of the last moderation"),
+ null=True,
+ default=None,
+ on_delete=models.SET_DEFAULT,
+ related_name="moderated_events"
+ )
+
recurrence_dtstart = models.DateTimeField(editable=False, blank=True, null=True)
recurrence_dtend = models.DateTimeField(editable=False, blank=True, null=True)
@@ -692,6 +726,10 @@ class Event(models.Model):
blank=True,
)
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.processing_user = None
+
def get_consolidated_end_day(self, intuitive=True):
if intuitive:
end_day = self.get_consolidated_end_day(False)
@@ -896,6 +934,9 @@ class Event(models.Model):
def set_no_modification_date_changed(self):
self.no_modification_date_changed = True
+ def set_processing_user(self, user):
+ self.processing_user = user
+
def set_in_moderation_process(self):
self.in_moderation_process = True
@@ -906,12 +947,16 @@ class Event(models.Model):
now = timezone.now()
if not self.id:
self.created_date = now
+ self.created_by_user = self.processing_user
if self.is_in_importation_process():
self.imported_date = now
+ self.imported_by_user = self.processing_user
if self.modified_date is None or not self.is_no_modification_date_changed():
self.modified_date = now
+ self.modified_by_user = self.processing_user
if self.is_in_moderation_process():
self.moderated_date = now
+ self.moderated_by_user = self.processing_user
def get_recurrence_at_date(self, year, month, day):
dtstart = timezone.make_aware(
@@ -1412,7 +1457,11 @@ class Event(models.Model):
self.import_sources.append(source)
# Limitation: the given events should not be considered similar one to another...
- def import_events(events, remove_missing_from_source=None):
+ def import_events(events, remove_missing_from_source=None, user_id=None):
+
+ user = None
+ if user_id:
+ user = User.objects.filter(pk=user_id).first()
to_import = []
to_update = []
@@ -1439,6 +1488,7 @@ class Event(models.Model):
# imported events should be updated
event.set_in_importation_process()
+ event.set_processing_user(user)
event.prepare_save()
# check if the event has already be imported (using uuid)
diff --git a/src/agenda_culturel/templates/agenda_culturel/event-info-inc.html b/src/agenda_culturel/templates/agenda_culturel/event-info-inc.html
index fd968dc..4f1df6a 100644
--- a/src/agenda_culturel/templates/agenda_culturel/event-info-inc.html
+++ b/src/agenda_culturel/templates/agenda_culturel/event-info-inc.html
@@ -1,10 +1,10 @@
-
- {% picto_from_name "map-pin" %}
+
{% if event.exact_location %}
- {{ event.exact_location.name }}, {{ event.exact_location.city }}
+
{% picto_from_name "map-pin" %}
+ {{ event.exact_location.name }}, {{ event.exact_location.city }}
{% else %}
{% if perms.agenda_culturel.change_event and perms.agenda_culturel.change_place %}
- {{ event.location }}
+ {% picto_from_name "map-pin" %}
+ {% if event.location %}{{ event.location }}{% else %}sans lieu{% endif %}
{% else %}
- {{ event.location }}
+ {% if event.location %}{% picto_from_name "map-pin" %} {{ event.location }}
{% endif %}
{% endif %}
{% endif %}
From 63aad60260e5990dbd57428f548a7ab0d6570016 Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 19:37:47 +0100
Subject: [PATCH 12/85] =?UTF-8?q?On=20supprime=20une=20m=C3=A9thode=20qui?=
=?UTF-8?q?=20n'est=20plus=20utilis=C3=A9e=20depuis=20longtemps?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/agenda_culturel/views.py | 19 -------------------
1 file changed, 19 deletions(-)
diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py
index a70189a..2049ea6 100644
--- a/src/agenda_culturel/views.py
+++ b/src/agenda_culturel/views.py
@@ -530,25 +530,6 @@ class EventCreateView(SuccessMessageMixin, CreateView):
return super().form_valid(form)
-def import_from_details(request):
- form = EventForm(request.POST, is_authenticated=request.user.is_authenticated)
- if form.is_valid():
- new_event = form.save()
- if request.user.is_authenticated:
- messages.success(request, _("The event is saved."))
- return HttpResponseRedirect(new_event.get_absolute_url())
- else:
- messages.success(
- request,
- _(
- "The event has been submitted and will be published as soon as it has been validated by the moderation team."
- ),
- )
- return HttpResponseRedirect(reverse("home"))
- else:
- return render(
- request, "agenda_culturel/event_form.html", context={"form": form}
- )
# A class to evaluate the URL according to the existing events and the authentification
# level of the user
From e875ae626bf7ce7a5e151f5975d251a3584bac2c Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 19:49:47 +0100
Subject: [PATCH 13/85] =?UTF-8?q?Am=C3=A9lioration=20mise=20en=20page?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/agenda_culturel/static/style.scss | 11 +++++++++++
.../single-event/event-elegant-inc.html | 17 +++++++++--------
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss
index 4947696..38fe13a 100644
--- a/src/agenda_culturel/static/style.scss
+++ b/src/agenda_culturel/static/style.scss
@@ -1434,6 +1434,17 @@ img.preview {
}
}
+.header-complement {
+ float: none;
+}
+
+@media only screen and (min-width: 992px) {
+ .header-complement {
+ float: left;
+ clear: both;
+ }
+}
+
form.messages div, form.moderation-events {
@media only screen and (min-width: 992px) {
display: grid;
diff --git a/src/agenda_culturel/templates/agenda_culturel/single-event/event-elegant-inc.html b/src/agenda_culturel/templates/agenda_culturel/single-event/event-elegant-inc.html
index 74bf724..057e2c8 100644
--- a/src/agenda_culturel/templates/agenda_culturel/single-event/event-elegant-inc.html
+++ b/src/agenda_culturel/templates/agenda_culturel/single-event/event-elegant-inc.html
@@ -6,7 +6,11 @@
From 1d9251946c92e5c0c74b3294be8a194c4145bcc5 Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 20:02:12 +0100
Subject: [PATCH 14/85] Fix erreur 500 contact form
---
src/agenda_culturel/views.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py
index 2049ea6..fa162c5 100644
--- a/src/agenda_culturel/views.py
+++ b/src/agenda_culturel/views.py
@@ -732,6 +732,10 @@ class ContactMessageCreateView(SuccessMessageMixin, CreateView):
success_url = reverse_lazy("home")
success_message = _("Your message has been sent successfully.")
+ def __init__(self, *args, **kwargs):
+ self.event = None
+ super().__init__(*args, **kwargs)
+
def get_form(self, form_class=None):
if form_class is None:
form_class = self.get_form_class()
From d55d029fc73c6411c6f1d77e04800cfcba2b907e Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 20:09:40 +0100
Subject: [PATCH 15/85] Fix formulaire (again)
---
src/agenda_culturel/forms.py | 1 +
.../templates/agenda_culturel/contactmessage_create_form.html | 2 +-
src/agenda_culturel/views.py | 2 ++
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/agenda_culturel/forms.py b/src/agenda_culturel/forms.py
index 314ad20..16569d1 100644
--- a/src/agenda_culturel/forms.py
+++ b/src/agenda_culturel/forms.py
@@ -759,3 +759,4 @@ class ContactMessageForm(ModelForm):
def __init__(self, *args, **kwargs):
self.event = kwargs.pop("event", False)
super().__init__(*args, **kwargs)
+ self.fields['related_event'].required = False
diff --git a/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html b/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html
index e91208d..a8ab063 100644
--- a/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html
+++ b/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html
@@ -31,7 +31,7 @@ Contact{% endif %}{% endblock %}{% endblock %}
{% endif %}
- Attention : n'utilisez pas le formulaire ci-dessous pour proposer un événement, il sera ignoré. Utilisez plutôt la page ajouter un événement.
+ Attention : n'utilisez pas le formulaire ci-dessous pour proposer un événement, il sera ignoré. Utilisez plutôt la page ajouter un événement.
{% if form.event %}
Tu nous contactes au sujet de l'événement « {{ form.event.title }} » du {{ form.event.start_day }}.
N'hésites pas à nous indiquer le maximum de contexte et à nous laisser ton adresse
diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py
index fa162c5..46d417b 100644
--- a/src/agenda_culturel/views.py
+++ b/src/agenda_culturel/views.py
@@ -752,6 +752,8 @@ class ContactMessageCreateView(SuccessMessageMixin, CreateView):
self.event = get_object_or_404(Event, pk=self.kwargs["pk"])
result["related_event"] = self.event
result["subject"] = _('Reporting the event {} on {}').format(self.event.title, self.event.start_day)
+ else:
+ result["related_event"] = None
return result
From 21b42e4fee84f4d38189a991c22678ed2af7efdf Mon Sep 17 00:00:00 2001
From: Jean-Marie Favreau
Date: Fri, 29 Nov 2024 20:09:48 +0100
Subject: [PATCH 16/85] Ajout d'un antispam
Fix #227
---
src/agenda_culturel/settings/base.py | 3 +++
.../agenda_culturel/contactmessage_create_form.html | 2 ++
src/agenda_culturel/views.py | 5 ++++-
src/requirements.txt | 3 ++-
4 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/agenda_culturel/settings/base.py b/src/agenda_culturel/settings/base.py
index 9df688b..646507b 100644
--- a/src/agenda_culturel/settings/base.py
+++ b/src/agenda_culturel/settings/base.py
@@ -56,8 +56,11 @@ INSTALLED_APPS = [
"robots",
"debug_toolbar",
"cache_cleaner",
+ "honeypot",
]
+HONEYPOT_FIELD_NAME = "alias_name"
+
SITE_ID = 1
MIDDLEWARE = [
diff --git a/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html b/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html
index a8ab063..d3acd2b 100644
--- a/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html
+++ b/src/agenda_culturel/templates/agenda_culturel/contactmessage_create_form.html
@@ -1,5 +1,6 @@
{% extends "agenda_culturel/page-admin.html" %}
{% load static %}
+{% load honeypot %}
{% block title %}{% block og_title %}{% if form.event %}Contact au sujet de l'événement {{ form.event.title }}{% else %}
Contact{% endif %}{% endblock %}{% endblock %}
@@ -40,6 +41,7 @@ Contact{% endif %}{% endblock %}{% endblock %}
{% endif %}