From 489d2e2f0f9ae040f3a72cf1eb29733915616361 Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Sat, 9 Nov 2024 23:00:29 +0100 Subject: [PATCH] =?UTF-8?q?Migration=20au=20nouveau=20paradigme=20de=20dup?= =?UTF-8?q?liqu=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #184 --- src/agenda_culturel/forms.py | 15 +- .../locale/fr/LC_MESSAGES/django.po | 416 +++++++++--------- src/agenda_culturel/models.py | 190 ++++---- src/agenda_culturel/static/style.scss | 4 + .../agenda_culturel/duplicate-diff-inc.html | 2 +- .../agenda_culturel/event-date-info-inc.html | 16 + .../agenda_culturel/event-sources-inc.html | 14 + .../templates/agenda_culturel/page-event.html | 16 +- .../single-event/event-in-flat-list-inc.html | 1 + .../event-in-list-by-day-inc.html | 12 +- .../single-event/event-in-list-inc.html | 10 +- .../event-in-unknown-place-list-inc.html | 9 +- .../single-event/event-single-inc.html | 73 ++- src/agenda_culturel/views.py | 12 +- 14 files changed, 409 insertions(+), 381 deletions(-) create mode 100644 src/agenda_culturel/templates/agenda_culturel/event-date-info-inc.html create mode 100644 src/agenda_culturel/templates/agenda_culturel/event-sources-inc.html diff --git a/src/agenda_culturel/forms.py b/src/agenda_culturel/forms.py index 5730b4d..4af4c29 100644 --- a/src/agenda_culturel/forms.py +++ b/src/agenda_culturel/forms.py @@ -80,6 +80,8 @@ class EventForm(ModelForm): "imported_date", "modified_date", "moderated_date", + "import_sources", + "uuids" ] widgets = { "start_day": TextInput( @@ -98,9 +100,7 @@ class EventForm(ModelForm): ), "end_day": TextInput(attrs={"type": "date"}), "end_time": TextInput(attrs={"type": "time"}), - "uuids": MultipleHiddenInput(), "other_versions": HiddenInput(), - "import_sources": MultipleHiddenInput(), "reference_urls": DynamicArrayWidgetURLs(), "tags": DynamicArrayWidgetTags(), } @@ -164,12 +164,16 @@ class FixDuplicates(Form): super().__init__(*args, **kwargs) choices = [] + initial = None for i, e in enumerate(events): if e.status != Event.STATUS.TRASH: il = auc[i] msg = "" - if e.modified(): + if e.local_version(): msg = _(" (locally modified version)") + initial = "Select" + il + if e.pure_import(): + msg = _(" (synchronized on import version)") choices += [ ( "Select" + il, @@ -177,8 +181,10 @@ class FixDuplicates(Form): ) ] extra = "" - if edup.has_modified(): + if edup.has_local_version(): extra = _(" Warning: a version is already locally modified.") + if initial is None: + initial = "Merge" choices += [ ("Merge", _("Create a new version by merging.") + extra) ] @@ -193,6 +199,7 @@ class FixDuplicates(Form): choices += [("NotDuplicates", _("Make all versions independent."))] self.fields["action"].choices = choices + self.fields["action"].initial = initial def is_action_no_duplicates(self): return self.cleaned_data["action"] == "NotDuplicates" diff --git a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po index a06717d..8d65c36 100644 --- a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po +++ b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: agenda_culturel\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-11-09 11:29+0100\n" +"POT-Creation-Date: 2024-11-09 22:59+0100\n" "PO-Revision-Date: 2023-10-29 14:16+0000\n" "Last-Translator: Jean-Marie Favreau \n" "Language-Team: Jean-Marie Favreau \n" @@ -91,8 +91,8 @@ msgid "Evening" msgstr "Soir" #: agenda_culturel/forms.py:44 agenda_culturel/models.py:165 -#: agenda_culturel/models.py:191 agenda_culturel/models.py:447 -#: agenda_culturel/models.py:1552 agenda_culturel/models.py:1657 +#: agenda_culturel/models.py:191 agenda_culturel/models.py:448 +#: agenda_culturel/models.py:1563 agenda_culturel/models.py:1668 msgid "Category" msgstr "Catégorie" @@ -113,61 +113,65 @@ msgstr "L'heure de fin ne peut pas être avant l'heure de début." msgid "JSON in the format expected for the import." msgstr "JSON dans le format attendu pour l'import" -#: agenda_culturel/forms.py:171 +#: agenda_culturel/forms.py:173 msgid " (locally modified version)" msgstr " (version modifiée localement)" -#: agenda_culturel/forms.py:175 +#: agenda_culturel/forms.py:176 +msgid " (synchronized on import version)" +msgstr " (version synchronisée sur l'import)" + +#: agenda_culturel/forms.py:180 msgid "Select {} as representative version." msgstr "Sélectionner {} comme version représentative" -#: agenda_culturel/forms.py:180 +#: agenda_culturel/forms.py:185 msgid " Warning: a version is already locally modified." msgstr " Attention: une version a déjà été modifiée localement." -#: agenda_culturel/forms.py:182 +#: agenda_culturel/forms.py:189 msgid "Create a new version by merging." msgstr "Créer une nouvelle version par fusion." -#: agenda_culturel/forms.py:190 +#: agenda_culturel/forms.py:197 msgid "Make {} independent." msgstr "Rendre {} indépendant." -#: agenda_culturel/forms.py:192 +#: agenda_culturel/forms.py:199 msgid "Make all versions independent." msgstr "Rendre toutes les versions indépendantes." -#: agenda_culturel/forms.py:244 +#: agenda_culturel/forms.py:252 msgid "Value of event {}" msgstr "Valeur de l'événement {}" -#: agenda_culturel/forms.py:399 +#: agenda_culturel/forms.py:407 msgid "Apply category {} to the event {}" msgstr "Appliquer la catégorie {} à l'événement {}" -#: agenda_culturel/forms.py:414 agenda_culturel/models.py:371 -#: agenda_culturel/models.py:1709 +#: agenda_culturel/forms.py:422 agenda_culturel/models.py:372 +#: agenda_culturel/models.py:1720 msgid "Place" msgstr "Lieu" -#: agenda_culturel/forms.py:416 +#: agenda_culturel/forms.py:424 msgid "Create a missing place" msgstr "Créer un lieu manquant" -#: agenda_culturel/forms.py:426 +#: agenda_culturel/forms.py:434 msgid "Add \"{}\" to the aliases of the place" msgstr "Ajouter « {} » aux alias du lieu" -#: agenda_culturel/forms.py:453 +#: agenda_culturel/forms.py:461 msgid "On saving, use aliases to detect all matching events with missing place" msgstr "" "Lors de l'enregistrement, utiliser des alias pour détecter tous les " "événements correspondants dont la place est manquante." #: agenda_culturel/models.py:49 agenda_culturel/models.py:94 -#: agenda_culturel/models.py:172 agenda_culturel/models.py:333 -#: agenda_culturel/models.py:350 agenda_culturel/models.py:1424 -#: agenda_culturel/models.py:1498 +#: agenda_culturel/models.py:172 agenda_culturel/models.py:334 +#: agenda_culturel/models.py:351 agenda_culturel/models.py:1435 +#: agenda_culturel/models.py:1509 msgid "Name" msgstr "Nom" @@ -227,7 +231,7 @@ msgstr "Catégories" msgid "Tag name" msgstr "Nom de l'étiquette" -#: agenda_culturel/models.py:177 agenda_culturel/models.py:500 +#: agenda_culturel/models.py:177 agenda_culturel/models.py:501 msgid "Description" msgstr "Description" @@ -265,51 +269,51 @@ msgstr "" msgid "Duplicated events" msgstr "Événements dupliqués" -#: agenda_culturel/models.py:333 +#: agenda_culturel/models.py:334 msgid "Name of the location" msgstr "Nom de la position" -#: agenda_culturel/models.py:336 +#: agenda_culturel/models.py:337 msgid "Main" msgstr "Principale" -#: agenda_culturel/models.py:337 +#: agenda_culturel/models.py:338 msgid "This location is one of the main locations (shown first)." msgstr "Cette position est une position principale (affichée en premier)." -#: agenda_culturel/models.py:342 +#: agenda_culturel/models.py:343 msgid "Reference location" msgstr "Position de référence" -#: agenda_culturel/models.py:343 +#: agenda_culturel/models.py:344 msgid "Reference locations" msgstr "Positions de référence" -#: agenda_culturel/models.py:350 +#: agenda_culturel/models.py:351 msgid "Name of the place" msgstr "Nom du lieu" -#: agenda_culturel/models.py:352 +#: agenda_culturel/models.py:353 msgid "Address" msgstr "Adresse" -#: agenda_culturel/models.py:353 +#: agenda_culturel/models.py:354 msgid "Address of this place (without city name)" msgstr "Adresse de ce lieu (sans le nom de la ville)" -#: agenda_culturel/models.py:357 +#: agenda_culturel/models.py:358 msgid "City" msgstr "Ville" -#: agenda_culturel/models.py:357 +#: agenda_culturel/models.py:358 msgid "City name" msgstr "Nom de la ville" -#: agenda_culturel/models.py:362 +#: agenda_culturel/models.py:363 msgid "Alternative names" msgstr "Noms alternatifs" -#: agenda_culturel/models.py:364 +#: agenda_culturel/models.py:365 msgid "" "Alternative names or addresses used to match a place with the free-form " "location of an event." @@ -317,77 +321,77 @@ msgstr "" "Noms et adresses alternatives qui seront utilisées pour associer une adresse " "avec la localisation en forme libre d'un événement" -#: agenda_culturel/models.py:372 +#: agenda_culturel/models.py:373 msgid "Places" msgstr "Lieux" -#: agenda_culturel/models.py:425 agenda_culturel/models.py:1539 +#: agenda_culturel/models.py:426 agenda_culturel/models.py:1550 msgid "Published" msgstr "Publié" -#: agenda_culturel/models.py:426 +#: agenda_culturel/models.py:427 msgid "Draft" msgstr "Brouillon" -#: agenda_culturel/models.py:427 +#: agenda_culturel/models.py:428 msgid "Trash" msgstr "Corbeille" -#: agenda_culturel/models.py:438 +#: agenda_culturel/models.py:439 msgid "Title" msgstr "Titre" -#: agenda_culturel/models.py:438 +#: agenda_culturel/models.py:439 msgid "Short title" msgstr "Titre court" -#: agenda_culturel/models.py:442 agenda_culturel/models.py:1625 +#: agenda_culturel/models.py:443 agenda_culturel/models.py:1636 msgid "Status" msgstr "Status" -#: agenda_culturel/models.py:448 +#: agenda_culturel/models.py:449 msgid "Category of the event" msgstr "Catégorie de l'événement" -#: agenda_culturel/models.py:455 +#: agenda_culturel/models.py:456 msgid "Day of the event" msgstr "Date de l'événement" -#: agenda_culturel/models.py:458 agenda_culturel/models.py:459 +#: agenda_culturel/models.py:459 agenda_culturel/models.py:460 msgid "Starting time" msgstr "Heure de début" -#: agenda_culturel/models.py:465 +#: agenda_culturel/models.py:466 msgid "End day of the event" msgstr "Fin de l'événement" -#: agenda_culturel/models.py:467 +#: agenda_culturel/models.py:468 msgid "End day of the event, only required if different from the start day." msgstr "" "Date de fin de l'événement, uniquement nécessaire s'il est différent du " "premier jour de l'événement" -#: agenda_culturel/models.py:473 +#: agenda_culturel/models.py:474 msgid "Final time" msgstr "Heure de fin" -#: agenda_culturel/models.py:477 +#: agenda_culturel/models.py:478 msgid "Recurrence" msgstr "Récurrence" -#: agenda_culturel/models.py:482 agenda_culturel/models.py:1544 +#: agenda_culturel/models.py:483 agenda_culturel/models.py:1555 msgid "Location" msgstr "Localisation" -#: agenda_culturel/models.py:483 +#: agenda_culturel/models.py:484 msgid "Address of the event" msgstr "Adresse de l'événement" -#: agenda_culturel/models.py:489 +#: agenda_culturel/models.py:490 msgid "Location (free form)" msgstr "Localisation (forme libre)" -#: agenda_culturel/models.py:491 +#: agenda_culturel/models.py:492 msgid "" "Address of the event in case its not available in the already known places " "(free form)" @@ -395,211 +399,211 @@ msgstr "" "Addresse d'un événement si elle n'est pas déjà présente dans la liste des " "lieux disponible (forme libre)" -#: agenda_culturel/models.py:501 +#: agenda_culturel/models.py:502 msgid "General description of the event" msgstr "Description générale de l'événement" -#: agenda_culturel/models.py:507 +#: agenda_culturel/models.py:508 msgid "Illustration (local image)" msgstr "Illustration (image locale)" -#: agenda_culturel/models.py:508 +#: agenda_culturel/models.py:509 msgid "Illustration image stored in the agenda server" msgstr "Image d'illustration stockée sur le serveur de l'agenda" -#: agenda_culturel/models.py:515 +#: agenda_culturel/models.py:516 msgid "Illustration" msgstr "Illustration" -#: agenda_culturel/models.py:516 +#: agenda_culturel/models.py:517 msgid "URL of the illustration image" msgstr "URL de l'image illustrative" -#: agenda_culturel/models.py:522 +#: agenda_culturel/models.py:523 msgid "Illustration description" msgstr "Description de l'illustration" -#: agenda_culturel/models.py:523 +#: agenda_culturel/models.py:524 msgid "Alternative text used by screen readers for the image" msgstr "Texte alternatif utiliser par les lecteurs d'écrans pour l'image" -#: agenda_culturel/models.py:531 +#: agenda_culturel/models.py:532 msgid "Importation source" msgstr "Source d'importation" -#: agenda_culturel/models.py:532 +#: agenda_culturel/models.py:533 msgid "Importation source used to detect removed entries." msgstr "Source d'importation utilisée pour détecter les éléments supprimés/" -#: agenda_culturel/models.py:538 +#: agenda_culturel/models.py:539 msgid "UUIDs" msgstr "UUIDs" -#: agenda_culturel/models.py:539 +#: agenda_culturel/models.py:540 msgid "UUIDs from import to detect duplicated entries." msgstr "UUIDs utilisés pendant l'import pour détecter les entrées dupliquées" -#: agenda_culturel/models.py:545 +#: agenda_culturel/models.py:546 msgid "URLs" msgstr "URLs" -#: agenda_culturel/models.py:546 +#: agenda_culturel/models.py:547 msgid "List of all the urls where this event can be found." msgstr "Liste de toutes les urls où l'événement peut être trouvé." -#: agenda_culturel/models.py:553 +#: agenda_culturel/models.py:554 msgid "Tags" msgstr "Étiquettes" -#: agenda_culturel/models.py:554 +#: agenda_culturel/models.py:555 msgid "A list of tags that describe the event." msgstr "Une liste d'étiquettes décrivant l'événement" -#: agenda_culturel/models.py:561 +#: agenda_culturel/models.py:562 msgid "Other versions" msgstr "" -#: agenda_culturel/models.py:626 +#: agenda_culturel/models.py:627 msgid "Event" msgstr "Événement" -#: agenda_culturel/models.py:627 +#: agenda_culturel/models.py:628 msgid "Events" msgstr "Événements" -#: agenda_culturel/models.py:1415 +#: agenda_culturel/models.py:1426 msgid "Contact message" msgstr "Message de contact" -#: agenda_culturel/models.py:1416 +#: agenda_culturel/models.py:1427 msgid "Contact messages" msgstr "Messages de contact" -#: agenda_culturel/models.py:1419 +#: agenda_culturel/models.py:1430 msgid "Subject" msgstr "Sujet" -#: agenda_culturel/models.py:1420 +#: agenda_culturel/models.py:1431 msgid "The subject of your message" msgstr "Sujet de votre message" -#: agenda_culturel/models.py:1425 +#: agenda_culturel/models.py:1436 msgid "Your name" msgstr "Votre nom" -#: agenda_culturel/models.py:1431 +#: agenda_culturel/models.py:1442 msgid "Email address" msgstr "Adresse email" -#: agenda_culturel/models.py:1432 +#: agenda_culturel/models.py:1443 msgid "Your email address" msgstr "Votre adresse email" -#: agenda_culturel/models.py:1437 +#: agenda_culturel/models.py:1448 msgid "Message" msgstr "Message" -#: agenda_culturel/models.py:1437 +#: agenda_culturel/models.py:1448 msgid "Your message" msgstr "Votre message" -#: agenda_culturel/models.py:1442 agenda_culturel/views.py:967 +#: agenda_culturel/models.py:1453 agenda_culturel/views.py:969 msgid "Spam" msgstr "Spam" -#: agenda_culturel/models.py:1443 +#: agenda_culturel/models.py:1454 msgid "This message is a spam." msgstr "Ce message est un spam." -#: agenda_culturel/models.py:1448 agenda_culturel/views.py:962 +#: agenda_culturel/models.py:1459 agenda_culturel/views.py:964 msgid "Closed" msgstr "Fermé" -#: agenda_culturel/models.py:1450 +#: agenda_culturel/models.py:1461 msgid "this message has been processed and no longer needs to be handled" msgstr "Ce message a été traité et ne nécessite plus d'être pris en charge" -#: agenda_culturel/models.py:1455 +#: agenda_culturel/models.py:1466 msgid "Comments" msgstr "Commentaires" -#: agenda_culturel/models.py:1456 +#: agenda_culturel/models.py:1467 msgid "Comments on the message from the moderation team" msgstr "Commentaires sur ce message par l'équipe de modération" -#: agenda_culturel/models.py:1468 agenda_culturel/models.py:1605 +#: agenda_culturel/models.py:1479 agenda_culturel/models.py:1616 msgid "Recurrent import" msgstr "Import récurrent" -#: agenda_culturel/models.py:1469 +#: agenda_culturel/models.py:1480 msgid "Recurrent imports" msgstr "Imports récurrents" -#: agenda_culturel/models.py:1473 +#: agenda_culturel/models.py:1484 msgid "ical" msgstr "ical" -#: agenda_culturel/models.py:1474 +#: agenda_culturel/models.py:1485 msgid "ical no busy" msgstr "ical sans busy" -#: agenda_culturel/models.py:1475 +#: agenda_culturel/models.py:1486 msgid "ical no VC" msgstr "ical sans VC" -#: agenda_culturel/models.py:1476 +#: agenda_culturel/models.py:1487 msgid "lacoope.org" msgstr "lacoope.org" -#: agenda_culturel/models.py:1477 +#: agenda_culturel/models.py:1488 msgid "la comédie" msgstr "la comédie" -#: agenda_culturel/models.py:1478 +#: agenda_culturel/models.py:1489 msgid "le fotomat" msgstr "le fotomat" -#: agenda_culturel/models.py:1479 +#: agenda_culturel/models.py:1490 msgid "la puce à l'oreille" msgstr "la puce à loreille" -#: agenda_culturel/models.py:1480 +#: agenda_culturel/models.py:1491 msgid "Plugin wordpress MEC" msgstr "Plugin wordpress MEC" -#: agenda_culturel/models.py:1481 +#: agenda_culturel/models.py:1492 msgid "Événements d'une page FB" msgstr "Événements d'une page FB" -#: agenda_culturel/models.py:1482 +#: agenda_culturel/models.py:1493 msgid "la cour des 3 coquins" msgstr "la cour des 3 coquins" -#: agenda_culturel/models.py:1483 +#: agenda_culturel/models.py:1494 msgid "Arachnée concert" msgstr "Arachnée concert" -#: agenda_culturel/models.py:1486 +#: agenda_culturel/models.py:1497 msgid "simple" msgstr "simple" -#: agenda_culturel/models.py:1487 +#: agenda_culturel/models.py:1498 msgid "Headless Chromium" msgstr "chromium sans interface" -#: agenda_culturel/models.py:1488 +#: agenda_culturel/models.py:1499 msgid "Headless Chromium (pause)" msgstr "chromium sans interface (pause)" -#: agenda_culturel/models.py:1493 +#: agenda_culturel/models.py:1504 msgid "daily" msgstr "chaque jour" -#: agenda_culturel/models.py:1495 +#: agenda_culturel/models.py:1506 msgid "weekly" msgstr "chaque semaine" -#: agenda_culturel/models.py:1500 +#: agenda_culturel/models.py:1511 msgid "" "Recurrent import name. Be careful to choose a name that is easy to " "understand, as it will be public and displayed on the sites About page." @@ -607,135 +611,135 @@ msgstr "" "Nom de l'import récurrent. Attention à choisir un nom compréhensible, car il " "sera public, et affiché sur la page à propos du site." -#: agenda_culturel/models.py:1507 +#: agenda_culturel/models.py:1518 msgid "Processor" msgstr "Processeur" -#: agenda_culturel/models.py:1510 +#: agenda_culturel/models.py:1521 msgid "Downloader" msgstr "Téléchargeur" -#: agenda_culturel/models.py:1517 +#: agenda_culturel/models.py:1528 msgid "Import recurrence" msgstr "Récurrence d'import" -#: agenda_culturel/models.py:1524 +#: agenda_culturel/models.py:1535 msgid "Source" msgstr "Source" -#: agenda_culturel/models.py:1525 +#: agenda_culturel/models.py:1536 msgid "URL of the source document" msgstr "URL du document source" -#: agenda_culturel/models.py:1529 +#: agenda_culturel/models.py:1540 msgid "Browsable url" msgstr "URL navigable" -#: agenda_culturel/models.py:1531 +#: agenda_culturel/models.py:1542 msgid "URL of the corresponding document that will be shown to visitors." msgstr "URL correspondant au document et qui sera montrée aux visiteurs" -#: agenda_culturel/models.py:1540 +#: agenda_culturel/models.py:1551 msgid "Status of each imported event (published or draft)" msgstr "Status de chaque événement importé (publié ou brouillon)" -#: agenda_culturel/models.py:1545 +#: agenda_culturel/models.py:1556 msgid "Address for each imported event" msgstr "Adresse de chaque événement importé" -#: agenda_culturel/models.py:1553 +#: agenda_culturel/models.py:1564 msgid "Category of each imported event" msgstr "Catégorie de chaque événement importé" -#: agenda_culturel/models.py:1561 +#: agenda_culturel/models.py:1572 msgid "Tags for each imported event" msgstr "Étiquettes de chaque événement importé" -#: agenda_culturel/models.py:1562 +#: agenda_culturel/models.py:1573 msgid "A list of tags that describe each imported event." msgstr "Une liste d'étiquettes décrivant chaque événement importé" -#: agenda_culturel/models.py:1591 +#: agenda_culturel/models.py:1602 msgid "Running" msgstr "En cours" -#: agenda_culturel/models.py:1592 +#: agenda_culturel/models.py:1603 msgid "Canceled" msgstr "Annulé" -#: agenda_culturel/models.py:1593 +#: agenda_culturel/models.py:1604 msgid "Success" msgstr "Succès" -#: agenda_culturel/models.py:1594 +#: agenda_culturel/models.py:1605 msgid "Failed" msgstr "Erreur" -#: agenda_culturel/models.py:1597 +#: agenda_culturel/models.py:1608 msgid "Batch importation" msgstr "Importation par lot" -#: agenda_culturel/models.py:1598 +#: agenda_culturel/models.py:1609 msgid "Batch importations" msgstr "Importations par lot" -#: agenda_culturel/models.py:1606 +#: agenda_culturel/models.py:1617 msgid "Reference to the recurrent import processing" msgstr "Référence du processus d'import récurrent" -#: agenda_culturel/models.py:1614 +#: agenda_culturel/models.py:1625 msgid "URL (if not recurrent import)" msgstr "URL (si pas d'import récurrent)" -#: agenda_culturel/models.py:1616 +#: agenda_culturel/models.py:1627 msgid "Source URL if no RecurrentImport is associated." msgstr "URL source si aucun import récurrent n'est associé" -#: agenda_culturel/models.py:1629 +#: agenda_culturel/models.py:1640 msgid "Error message" msgstr "Votre message" -#: agenda_culturel/models.py:1633 +#: agenda_culturel/models.py:1644 msgid "Number of collected events" msgstr "Nombre d'événements collectés" -#: agenda_culturel/models.py:1636 +#: agenda_culturel/models.py:1647 msgid "Number of imported events" msgstr "Nombre d'événements importés" -#: agenda_culturel/models.py:1639 +#: agenda_culturel/models.py:1650 msgid "Number of updated events" msgstr "Nombre d'événements mis à jour" -#: agenda_culturel/models.py:1642 +#: agenda_culturel/models.py:1653 msgid "Number of removed events" msgstr "Nombre d'événements supprimés" -#: agenda_culturel/models.py:1650 +#: agenda_culturel/models.py:1661 msgid "Weight" msgstr "Poids" -#: agenda_culturel/models.py:1651 +#: agenda_culturel/models.py:1662 msgid "The lower is the weight, the earlier the filter is applied" msgstr "Plus le poids est léger, plus le filtre sera appliqué tôt" -#: agenda_culturel/models.py:1658 +#: agenda_culturel/models.py:1669 msgid "Category applied to the event" msgstr "Catégorie appliquée à l'événement" -#: agenda_culturel/models.py:1663 +#: agenda_culturel/models.py:1674 msgid "Contained in the title" msgstr "Contenu dans le titre" -#: agenda_culturel/models.py:1664 +#: agenda_culturel/models.py:1675 msgid "Text contained in the event title" msgstr "Texte contenu dans le titre de l'événement" -#: agenda_culturel/models.py:1670 +#: agenda_culturel/models.py:1681 msgid "Exact title extract" msgstr "Extrait exact du titre" -#: agenda_culturel/models.py:1672 +#: agenda_culturel/models.py:1683 msgid "" "If checked, the extract will be searched for in the title using the exact " "form (capitals, accents)." @@ -743,19 +747,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans le titre en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:1678 +#: agenda_culturel/models.py:1689 msgid "Contained in the description" msgstr "Contenu dans la description" -#: agenda_culturel/models.py:1679 +#: agenda_culturel/models.py:1690 msgid "Text contained in the description" msgstr "Texte contenu dans la description" -#: agenda_culturel/models.py:1685 +#: agenda_culturel/models.py:1696 msgid "Exact description extract" msgstr "Extrait exact de description" -#: agenda_culturel/models.py:1687 +#: agenda_culturel/models.py:1698 msgid "" "If checked, the extract will be searched for in the description using the " "exact form (capitals, accents)." @@ -763,19 +767,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans la description en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:1693 +#: agenda_culturel/models.py:1704 msgid "Contained in the location" msgstr "Contenu dans la localisation" -#: agenda_culturel/models.py:1694 +#: agenda_culturel/models.py:1705 msgid "Text contained in the event location" msgstr "Texte contenu dans la localisation de l'événement" -#: agenda_culturel/models.py:1700 +#: agenda_culturel/models.py:1711 msgid "Exact location extract" msgstr "Extrait exact de localisation" -#: agenda_culturel/models.py:1702 +#: agenda_culturel/models.py:1713 msgid "" "If checked, the extract will be searched for in the location using the exact " "form (capitals, accents)." @@ -783,56 +787,56 @@ msgstr "" "Si coché, l'extrait sera recherché dans la localisation en utilisant la " "forme exacte (majuscules, accents)" -#: agenda_culturel/models.py:1710 +#: agenda_culturel/models.py:1721 msgid "Location from place" msgstr "Localisation depuis le lieu" -#: agenda_culturel/models.py:1719 +#: agenda_culturel/models.py:1730 msgid "Categorisation rule" msgstr "Règle de catégorisation" -#: agenda_culturel/models.py:1720 +#: agenda_culturel/models.py:1731 msgid "Categorisation rules" msgstr "Règles de catégorisation" -#: agenda_culturel/models.py:1791 agenda_culturel/models.py:1823 +#: agenda_culturel/models.py:1802 agenda_culturel/models.py:1834 msgid "Question" msgstr "Question" -#: agenda_culturel/models.py:1792 agenda_culturel/models.py:1830 +#: agenda_culturel/models.py:1803 agenda_culturel/models.py:1841 msgid "Text that will be shown to moderators" msgstr "Text tel que présenté aux modérateurices" -#: agenda_culturel/models.py:1798 +#: agenda_culturel/models.py:1809 msgid "Moderation question" msgstr "Question de modération" -#: agenda_culturel/models.py:1799 +#: agenda_culturel/models.py:1810 msgid "Moderation questions" msgstr "Questions de modération" -#: agenda_culturel/models.py:1824 +#: agenda_culturel/models.py:1835 msgid "Associated question from moderation" msgstr "Question associée pour la modération" -#: agenda_culturel/models.py:1829 +#: agenda_culturel/models.py:1840 msgid "Answer" msgstr "Réponse" -#: agenda_culturel/models.py:1836 +#: agenda_culturel/models.py:1847 msgid "Adds tags" msgstr "Ajoute les étiquettes" -#: agenda_culturel/models.py:1837 +#: agenda_culturel/models.py:1848 msgid "A list of tags that will be added if you choose this answer." msgstr "" "Une liste d'étiquettes qui seront ajoutées si vous choisissez cette réponse." -#: agenda_culturel/models.py:1843 +#: agenda_culturel/models.py:1854 msgid "Removes tags" msgstr "Retire les étiquettes" -#: agenda_culturel/models.py:1844 +#: agenda_culturel/models.py:1855 msgid "A list of tags that will be removed if you choose this answer." msgstr "" "Une liste d'étiquettes qui seront retirées si vous choisissez cette réponse." @@ -879,23 +883,23 @@ msgstr "" "La mise à jour de l'événement a été mise en attente et sera effectuée sous " "peu." -#: agenda_culturel/views.py:562 agenda_culturel/views.py:620 +#: agenda_culturel/views.py:562 agenda_culturel/views.py:622 msgid "The event has been successfully modified." msgstr "L'événement a été modifié avec succès." -#: agenda_culturel/views.py:589 +#: agenda_culturel/views.py:591 msgid "The event has been successfully deleted." msgstr "L'événement a été supprimé avec succès" -#: agenda_culturel/views.py:645 +#: agenda_culturel/views.py:647 msgid "The status has been successfully modified." msgstr "Le status a été modifié avec succès." -#: agenda_culturel/views.py:681 +#: agenda_culturel/views.py:683 msgid "The event was created: {}." msgstr "L'événement a été créé: {}." -#: agenda_culturel/views.py:683 agenda_culturel/views.py:698 +#: agenda_culturel/views.py:685 agenda_culturel/views.py:700 msgid "" "The event has been submitted and will be published as soon as it has been " "validated by the moderation team." @@ -903,105 +907,105 @@ msgstr "" "L'événement a été soumis et sera publié dès qu'il aura été validé par " "l'équipe de modération." -#: agenda_culturel/views.py:692 +#: agenda_culturel/views.py:694 msgid "The event is saved." msgstr "L'événement est enregistré." -#: agenda_culturel/views.py:784 agenda_culturel/views.py:836 +#: agenda_culturel/views.py:786 agenda_culturel/views.py:838 msgid "{} has not been submitted since its already known: {}." msgstr "{} n'a pas été soumis car il est déjà connu: {}." -#: agenda_culturel/views.py:789 agenda_culturel/views.py:842 +#: agenda_culturel/views.py:791 agenda_culturel/views.py:844 msgid "" "{} has not been submitted since its already known and currently into " "moderation process." msgstr "{} n'a pas été soumis car il est déjà connu et en cours de modération" -#: agenda_culturel/views.py:799 +#: agenda_culturel/views.py:801 msgid "Integrating {} url(s) into our import process." msgstr "Intégration de {} url(s) dans notre processus d'import." -#: agenda_culturel/views.py:849 +#: agenda_culturel/views.py:851 msgid "Integrating {} into our import process." msgstr "Intégration de {} dans notre processus d'import." -#: agenda_culturel/views.py:922 +#: agenda_culturel/views.py:924 msgid "Your message has been sent successfully." msgstr "Votre message a été envoyé avec succès." -#: agenda_culturel/views.py:932 +#: agenda_culturel/views.py:934 msgid "The contact message has been successfully deleted." msgstr "Le message de contact a été supprimé avec succès." -#: agenda_culturel/views.py:946 +#: agenda_culturel/views.py:948 msgid "The contact message properties has been successfully modified." msgstr "Les propriétés du message de contact ont été modifié avec succès." -#: agenda_culturel/views.py:962 +#: agenda_culturel/views.py:964 msgid "Open" msgstr "Ouvert" -#: agenda_culturel/views.py:967 +#: agenda_culturel/views.py:969 msgid "Non spam" msgstr "Non spam" -#: agenda_culturel/views.py:1030 +#: agenda_culturel/views.py:1032 msgid "Spam has been successfully deleted." msgstr "Le spam a été supprimé avec succès" -#: agenda_culturel/views.py:1047 +#: agenda_culturel/views.py:1049 msgid "Search" msgstr "Rechercher" -#: agenda_culturel/views.py:1233 +#: agenda_culturel/views.py:1235 msgid "The import has been run successfully." msgstr "L'import a été lancé avec succès" -#: agenda_culturel/views.py:1252 +#: agenda_culturel/views.py:1254 msgid "The import has been canceled." msgstr "L'import a été annulé" -#: agenda_culturel/views.py:1326 +#: agenda_culturel/views.py:1328 msgid "The recurrent import has been successfully modified." msgstr "L'import récurrent a été modifié avec succès." -#: agenda_culturel/views.py:1335 +#: agenda_culturel/views.py:1337 msgid "The recurrent import has been successfully deleted." msgstr "L'import récurrent a été supprimé avec succès" -#: agenda_culturel/views.py:1375 +#: agenda_culturel/views.py:1377 msgid "The import has been launched." msgstr "L'import a été lancé" -#: agenda_culturel/views.py:1397 +#: agenda_culturel/views.py:1399 msgid "Imports has been launched." msgstr "Les imports ont été lancés" -#: agenda_culturel/views.py:1487 +#: agenda_culturel/views.py:1489 msgid "Creation of a merged event has been successfully completed." msgstr "Création d'un événement fusionné réalisée avec succès." -#: agenda_culturel/views.py:1523 +#: agenda_culturel/views.py:1525 msgid "Events have been marked as unduplicated." msgstr "Les événements ont été marqués comme non dupliqués." -#: agenda_culturel/views.py:1537 +#: agenda_culturel/views.py:1539 msgid "The selected event has been set as representative" msgstr "L'événement sélectionné a été défini comme representatif." -#: agenda_culturel/views.py:1547 +#: agenda_culturel/views.py:1550 msgid "The event has been withdrawn from the group and made independent." msgstr "L'événement a été retiré du groupe et rendu indépendant." -#: agenda_culturel/views.py:1582 +#: agenda_culturel/views.py:1584 msgid "Cleaning up duplicates: {} item(s) fixed." msgstr "Nettoyage des dupliqués: {} élément(s) corrigé(s)." -#: agenda_culturel/views.py:1629 +#: agenda_culturel/views.py:1633 msgid "The event was successfully duplicated." msgstr "L'événement a été marqué dupliqué avec succès." -#: agenda_culturel/views.py:1637 +#: agenda_culturel/views.py:1641 msgid "" "The event has been successfully flagged as a duplicate. The moderation team " "will deal with your suggestion shortly." @@ -1009,32 +1013,32 @@ msgstr "" "L'événement a été signalé comme dupliqué avec succès. Votre suggestion sera " "prochainement prise en charge par l'équipe de modération." -#: agenda_culturel/views.py:1690 +#: agenda_culturel/views.py:1694 msgid "The categorisation rule has been successfully modified." msgstr "La règle de catégorisation a été modifiée avec succès." -#: agenda_culturel/views.py:1699 +#: agenda_culturel/views.py:1703 msgid "The categorisation rule has been successfully deleted." msgstr "La règle de catégorisation a été supprimée avec succès" -#: agenda_culturel/views.py:1721 +#: agenda_culturel/views.py:1725 msgid "The rules were successfully applied and 1 event was categorised." msgstr "" "Les règles ont été appliquées avec succès et 1 événement a été catégorisé" -#: agenda_culturel/views.py:1728 +#: agenda_culturel/views.py:1732 msgid "The rules were successfully applied and {} events were categorised." msgstr "" "Les règles ont été appliquées avec succès et {} événements ont été " "catégorisés" -#: agenda_culturel/views.py:1735 agenda_culturel/views.py:1788 +#: agenda_culturel/views.py:1739 agenda_culturel/views.py:1792 msgid "The rules were successfully applied and no events were categorised." msgstr "" "Les règles ont été appliquées avec succès et aucun événement n'a été " "catégorisé" -#: agenda_culturel/views.py:1774 +#: agenda_culturel/views.py:1778 msgid "" "The rules were successfully applied and 1 event with default category was " "categorised." @@ -1042,7 +1046,7 @@ msgstr "" "Les règles ont été appliquées avec succès et 1 événement avec catégorie par " "défaut a été catégorisé" -#: agenda_culturel/views.py:1781 +#: agenda_culturel/views.py:1785 msgid "" "The rules were successfully applied and {} events with default category were " "categorised." @@ -1050,46 +1054,46 @@ msgstr "" "Les règles ont été appliquées avec succès et {} événements avec catégorie " "par défaut ont été catégorisés" -#: agenda_culturel/views.py:1828 +#: agenda_culturel/views.py:1832 msgid "The moderation question has been created with success." msgstr "La question de modération a été créée avec succès." -#: agenda_culturel/views.py:1954 agenda_culturel/views.py:2016 -#: agenda_culturel/views.py:2054 +#: agenda_culturel/views.py:1958 agenda_culturel/views.py:2020 +#: agenda_culturel/views.py:2058 msgid "{} events have been updated." msgstr "{} événements ont été mis à jour." -#: agenda_culturel/views.py:1957 agenda_culturel/views.py:2018 -#: agenda_culturel/views.py:2057 +#: agenda_culturel/views.py:1961 agenda_culturel/views.py:2022 +#: agenda_culturel/views.py:2061 msgid "1 event has been updated." msgstr "1 événement a été mis à jour" -#: agenda_culturel/views.py:1959 agenda_culturel/views.py:2020 -#: agenda_culturel/views.py:2059 +#: agenda_culturel/views.py:1963 agenda_culturel/views.py:2024 +#: agenda_culturel/views.py:2063 msgid "No events have been modified." msgstr "Aucun événement n'a été modifié." -#: agenda_culturel/views.py:1968 +#: agenda_culturel/views.py:1972 msgid "The place has been successfully updated." msgstr "Le lieu a été modifié avec succès." -#: agenda_culturel/views.py:1977 +#: agenda_culturel/views.py:1981 msgid "The place has been successfully created." msgstr "Le lieu a été créé avec succès." -#: agenda_culturel/views.py:2042 +#: agenda_culturel/views.py:2046 msgid "The selected place has been assigned to the event." msgstr "Le lieu sélectionné a été assigné à l'événement." -#: agenda_culturel/views.py:2046 +#: agenda_culturel/views.py:2050 msgid "A new alias has been added to the selected place." msgstr "Un nouvel alias a été créé pour le lieu sélectionné." -#: agenda_culturel/views.py:2102 +#: agenda_culturel/views.py:2106 msgid "The tag has been successfully updated." msgstr "L'étiquette a été modifiée avec succès." -#: agenda_culturel/views.py:2109 +#: agenda_culturel/views.py:2113 msgid "The tag has been successfully created." msgstr "L'étiquette a été créée avec succès." diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index fb2cec7..259081a 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -237,18 +237,24 @@ class DuplicatedEvents(models.Model): def fixed(self): return not self.representative is None + def is_published(self): + return len([e for e in self.get_duplicated() if e.is_published()]) > 0 + def has_modified(self): return len([e for e in self.get_duplicated() if e.modified()]) > 0 + def has_local_version(self): + return len([e for e in self.get_duplicated() if e.local_version()]) > 0 + def get_local_version(self): - if self.representative and self.representative.modified(): + if self.representative and self.representative.local_version(): return self.representative - l = [e for e in self.get_duplicated() if e.modified()] + l = [e for e in self.get_duplicated() if e.local_version()] if len(l) == 0: return None else: - l.sort(key=lambda x: -x.modified_date) + l.sort(key=lambda x: x.modified_date, reverse=True) return l[0] def merge_into(self, other): @@ -256,7 +262,8 @@ class DuplicatedEvents(models.Model): for e in self.get_duplicated(): # change their group membership e.other_versions = other - # save them + # save them without updating modified date + e.set_no_modification_date_changed() e.save() other.representative = None other.save() @@ -304,27 +311,6 @@ class DuplicatedEvents(models.Model): nb, d = singletons.delete() return nb - def fix_similar_entries(): - to_be_fixed = [] - - for d in DuplicatedEvents.not_fixed_qs().prefetch_related('event_set'): - comp = Event.get_comparison(d.get_duplicated()) - similar = len([c for c in comp if not c["similar"]]) == 0 - if similar: - to_be_fixed.append(d) - - nb = len(to_be_fixed) - if nb > 0: - logger.warning("Removing: " + str(nb) + " similar duplicated") - for d in to_be_fixed: - if len(d.get_duplicated()) == 0: - logger.warning(" empty") - else: - logger.warning(" " + d.get_duplicated()[0].title) - for s in to_be_fixed: - s.fix() - - return nb def not_fixed_qs(qs=None, fixed=False): if not qs: @@ -673,6 +659,21 @@ class Event(models.Model): return False return self.modified_date is None or (self.modified_date - self.imported_date).total_seconds() <= 0 + def local_version(self): + return self.imported_date is None or self.modified() + + def get_reference_urls(self): + res = [] if self.reference_urls is None else self.reference_urls + + if self.other_versions: + for o in self.other_versions.get_duplicated(): + if o.status == Event.STATUS.PUBLISHED and not o.reference_urls is None: + res += o.reference_urls + + res = list(set(res)) + res.sort() + + return res def get_local_version(self): # a non-pure import is a local version @@ -689,7 +690,12 @@ class Event(models.Model): return Event.objects.filter(status=Event.STATUS.DRAFT).count() def get_qs_events_with_unkwnon_place(): - return Event.objects.filter(exact_location__isnull=True).filter(~Q(status=Event.STATUS.TRASH)).filter(Q(other_versions=None)|~Q(other_versions__representative=F('pk'))) + return Event.objects.filter(exact_location__isnull=True). \ + filter(~Q(status=Event.STATUS.TRASH)). \ + filter(Q(other_versions=None)|Q(other_versions__representative=F('pk'))) + + def is_representative(self): + return self.other_versions is None or self.other_versions.representative == self def download_image(self): # first download file @@ -717,13 +723,19 @@ class Event(models.Model): def set_in_importation_process(self): self.in_importation_process = True + def is_no_modification_date_changed(self): + return hasattr(self, "no_modification_date_changed") + + def set_no_modification_date_changed(self): + self.no_modification_date_changed = True + def update_modification_dates(self): now = timezone.now() if not self.id: self.created_date = now if self.is_in_importation_process(): self.imported_date = now - if self.modified_date is None or not self.is_in_importation_process(): + if self.modified_date is None or not self.is_no_modification_date_changed(): self.modified_date = now def get_recurrence_at_date(self, year, month, day): @@ -872,8 +884,13 @@ class Event(models.Model): # if it exists similar events, add this relation to the event if len(similar_events) != 0: self.set_other_versions(similar_events) + + # check if it's a clone (that will become representative) + clone = self.pk is None and not self.other_versions is None + # check if we need to clean the other_versions if ( + not clone and self.pk and self.other_versions is not None and self.other_versions.nb_duplicated() == 1 @@ -881,8 +898,14 @@ class Event(models.Model): self.other_versions.delete() self.other_versions = None + # first save the current object super().save(*args, **kwargs) + # then if its a clone, update the representative + if clone: + self.other_versions.representative = self + self.other_versions.save() + def from_structure(event_structure, import_source=None): if "category" in event_structure and event_structure["category"] is not None: try: @@ -1057,9 +1080,9 @@ class Event(models.Model): def masked(self): return self.other_versions and self.other_versions.representative != self - def get_comparison(events, all=True): + def get_comparison(events): result = [] - for attr in Event.data_fields(all=all, local_img=False, exact_location=False): + for attr in Event.data_fields(local_img=False, exact_location=False): values = [getattr(e, attr) for e in events] values = ["" if v is None else v for v in values] values = [[] if attr == "tags" and v == "" else v for v in values] @@ -1067,20 +1090,22 @@ class Event(models.Model): if attr == "image": values = [v.split("?")[0] if "fbcdn.net" in v else v for v in values] - if len(set([str(v) for v in values])) == 1: + if attr == "description": + values = [v.replace("\r\n", "\n") for v in values] + if len(set([str(v).strip() for v in values])) == 1: result.append({"similar": True, "key": attr, "values": values[0]}) else: result.append({"similar": False, "key": attr, "values": values}) return result - def similar(self, event, all=True): - res = Event.get_comparison([self, event], all) + def similar(self, event): + res = Event.get_comparison([self, event]) for r in res: if not r["similar"]: return False return True - def set_other_versions(self, events): + def set_other_versions(self, events, force_non_fixed=False): # get existing groups groups = list( set([e.other_versions for e in events] + [self.other_versions]) @@ -1093,6 +1118,9 @@ class Event(models.Model): else: # otherwise merge existing groups group = DuplicatedEvents.merge_groups(groups) + + if force_non_fixed: + group.representative = None group.save() # set the possibly duplicated group for the current object @@ -1106,13 +1134,10 @@ class Event(models.Model): elist = list(events) + ([self] if self.pk is not None else []) Event.objects.bulk_update(elist, fields=["other_versions"]) - def data_fields(all=False, local_img=True, exact_location=True): - if all: - result = ["category"] - else: - result = [] - - result += [ + def data_fields(local_img=True, exact_location=True): + result = [ + "category", + "tags", "title", "location", "start_day", @@ -1131,15 +1156,6 @@ class Event(models.Model): result += ["tags"] return result - def same_event_by_data(self, other): - for attr in Event.data_fields(): - if str(getattr(self, attr)) != str(getattr(other, attr)): - return False - return True - - def find_same_event_by_data_in_list(self, events): - return [e for e in events if self.same_event_by_data(e)] - def find_last_imported(events): events = [e for e in events if e.imported_date is not None] if len(events) == 0: @@ -1148,13 +1164,8 @@ class Event(models.Model): events.sort(key=lambda e: e.imported_date, reverse=True) return events[0] - def find_last_imported_not_modified(events): - events = [ - e - for e in events - if e.imported_date is not None - and (e.modified_date is None or e.modified_date <= e.imported_date) - ] + def find_last_pure_import(events): + events = [e for e in events if e.pure_import()] if len(events) == 0: return None else: @@ -1162,13 +1173,6 @@ class Event(models.Model): return events[0] def update(self, other): - - # we do not modify the category (local categories are more important) - # however, we add supplementary tags - if other.tags: - if not self.tags: - self.tags = [] - self.tags += [t for t in other.tags if not t in self.tags] # set attributes for attr in Event.data_fields(): @@ -1223,25 +1227,36 @@ class Event(models.Model): if len(same_events) != 0: # check if one event has been imported and not modified in this list - same_imported = Event.find_last_imported_not_modified(same_events) - # check if the imported events are similar or not (considering data and not category or tags) - same_events_not_similar = [ - e for e in same_events if not e.similar(event, False) - ] - if same_imported or len(same_events_not_similar) == 0: - # TODO: revoir ici: - if not same_imported: - same_imported = Event.find_last_imported(same_events) + same_imported = Event.find_last_pure_import(same_events) - # if this event exists, it will be updated with new data only if the data is fresher - if same_imported.modified_date < event.modified_date: - same_imported.update(event) - same_imported.set_in_importation_process() - same_imported.prepare_save() - to_update.append(same_imported) + # if not, we check if it does not match exactly with another + if not same_imported: + for e in same_events: + if event.similar(e): + same_imported = e + break + + if same_imported: + # reopen DuplicatedEvents if required + if not event.similar(same_imported) and same_imported.other_versions: + if same_imported.status != Event.STATUS.TRASH: + if same_imported.other_versions.is_published(): + if same_imported.other_versions.representative != same_imported: + same_imported.other_versions.representative = None + same_imported.other_versions.save() + + same_imported.update(event) + same_imported.set_in_importation_process() + same_imported.prepare_save() + to_update.append(same_imported) else: # otherwise, the new event possibly a duplication of the remaining others. - event.set_other_versions(same_events) + + # check if it should be published + trash = len([e for e in same_events if e.status != Event.STATUS.TRASH]) == 0 + if trash: + event.status = Event.STATUS.TRASH + event.set_other_versions(same_events, force_non_fixed=not trash) # it will be imported to_import.append(event) else: @@ -1250,18 +1265,9 @@ class Event(models.Model): # if it exists similar events, add this relation to the event if len(similar_events) != 0: - # check if an event from the list is exactly the same as the new one (using data) - same_events = event.find_same_event_by_data_in_list(similar_events) - if same_events is not None and len(same_events) > 0: - # merge with the first one - same_events[0].update(event) - same_events[0].set_in_importation_process() - same_events[0].prepare_save() - to_update.append(same_events[0]) - else: - # the event is possibly a duplication of the others - event.set_other_versions(similar_events) - to_import.append(event) + # the event is possibly a duplication of the others + event.set_other_versions(similar_events, force_non_fixed=True) + to_import.append(event) else: # import this new event to_import.append(event) @@ -1300,6 +1306,8 @@ class Event(models.Model): for e in in_interval: if len(uuids.intersection(e.uuids)) == 0: e.status = Event.STATUS.TRASH + # save them without updating modified date + e.set_no_modification_date_changed() e.prepare_save() to_draft.append(e) diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss index 4312aa6..4a0917e 100644 --- a/src/agenda_culturel/static/style.scss +++ b/src/agenda_culturel/static/style.scss @@ -549,6 +549,10 @@ article#filters { font-size: 100%; } } +header .remarque { + font-style: italic; +} + .django-ckeditor-widget { width: 100%; diff --git a/src/agenda_culturel/templates/agenda_culturel/duplicate-diff-inc.html b/src/agenda_culturel/templates/agenda_culturel/duplicate-diff-inc.html index 229369b..6d99bc6 100644 --- a/src/agenda_culturel/templates/agenda_culturel/duplicate-diff-inc.html +++ b/src/agenda_culturel/templates/agenda_culturel/duplicate-diff-inc.html @@ -14,7 +14,7 @@ {% if e.imported_date %}
  • Dernière importation : {{ e.imported_date }}
  • {% endif %}
  • État : {% if e.pure_import %}version fidèle à la source importée{% endif %} - {% if e.modified %}version modifiée localement{% endif %} + {% if e.local_version %}version modifiée localement{% endif %}
  • diff --git a/src/agenda_culturel/templates/agenda_culturel/event-date-info-inc.html b/src/agenda_culturel/templates/agenda_culturel/event-date-info-inc.html new file mode 100644 index 0000000..9a84b6a --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/event-date-info-inc.html @@ -0,0 +1,16 @@ +{% if user.is_authenticated %} + +{% endif %} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/event-sources-inc.html b/src/agenda_culturel/templates/agenda_culturel/event-sources-inc.html new file mode 100644 index 0000000..8a20d58 --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/event-sources-inc.html @@ -0,0 +1,14 @@ +{% load utils_extra %} + +{% with event.get_reference_urls as refs %} +{% if refs|length > 0 %} +

    Source{{ refs|pluralize }} : + + {% for eurl in refs %} +{{ eurl|hostname }}{% if not forloop.last %}, {% endif %} +{% endfor %} +

    +{% else %} +

    À notre connaissance, cet événement n'est pas référencé autre part sur internet.

    +{% endif %} +{% endwith %} \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/page-event.html b/src/agenda_culturel/templates/agenda_culturel/page-event.html index df687d4..bbc3319 100644 --- a/src/agenda_culturel/templates/agenda_culturel/page-event.html +++ b/src/agenda_culturel/templates/agenda_culturel/page-event.html @@ -84,29 +84,19 @@ {% endwith %} {% endwith %} - {% if event.other_versions %} + {% if event.other_versions and not event.other_versions.fixed %} {% with poss_dup=event.get_other_versions|only_allowed:user.is_authenticated %} {% if poss_dup|length > 0 %}
    - {% if event.other_versions.representative %} -

    Sources multiples

    -

    L'événement affiché est également disponible - {% if poss_dup.count == 1 %} - dans une autre version - {% else %} - dans d'autres versions - {% endif %} :

    - {% else %}

    Possibles doublons

    -

    Notre algorithme a détecté que l'événement affiché pourrait être dupliqué sur l'agenda, et consultable dans +

    L'événement affiché pourrait être dupliqué sur l'agenda, et consultable dans {% if poss_dup.count == 1 %} une autre version {% else %} d'autres versions {% endif %} - ci-dessous.

    - {% endif %} + ci-dessous. Nous faisons notre maximum pour résoudre cette duplication temporaire.