parent
cb214c0926
commit
a09f6751e3
@ -171,11 +171,12 @@ class IntervalInDay(DayInCalendar):
|
||||
self.id = self.id + '-' + str(id)
|
||||
|
||||
class CalendarList:
|
||||
def __init__(self, firstdate, lastdate, filter=None, exact=False):
|
||||
def __init__(self, firstdate, lastdate, filter=None, exact=False, ignore_dup=None):
|
||||
self.firstdate = firstdate
|
||||
self.lastdate = lastdate
|
||||
self.now = date.today()
|
||||
self.filter = filter
|
||||
self.ignore_dup = ignore_dup
|
||||
|
||||
if exact:
|
||||
self.c_firstdate = self.firstdate
|
||||
@ -219,6 +220,9 @@ class CalendarList:
|
||||
qs = Event.objects.all()
|
||||
else:
|
||||
qs = self.filter.qs
|
||||
|
||||
if self.ignore_dup:
|
||||
qs = qs.exclude(possibly_duplicated=self.ignore_dup)
|
||||
startdatetime = timezone.make_aware(datetime.combine(self.c_firstdate, time.min), timezone.get_default_timezone())
|
||||
lastdatetime = timezone.make_aware(datetime.combine(self.c_lastdate, time.max), timezone.get_default_timezone())
|
||||
self.events = qs.filter(
|
||||
@ -230,7 +234,7 @@ class CalendarList:
|
||||
| Q(recurrence_dtend__lt=startdatetime)
|
||||
)
|
||||
)
|
||||
).order_by("start_time").prefetch_related("exact_location").prefetch_related("category")
|
||||
).filter(masked=False).order_by("start_time").prefetch_related("exact_location").prefetch_related("category")
|
||||
|
||||
firstdate = datetime.fromordinal(self.c_firstdate.toordinal())
|
||||
if firstdate.tzinfo is None or firstdate.tzinfo.utcoffset(firstdate) is None:
|
||||
|
@ -162,17 +162,17 @@ class FixDuplicates(Form):
|
||||
choices += [
|
||||
(
|
||||
"SelectA",
|
||||
"Ces événements sont identiques, on garde A et on met B à la corbeille",
|
||||
"Ces événements sont identiques, on garde A et on masque B",
|
||||
)
|
||||
]
|
||||
choices += [
|
||||
(
|
||||
"SelectB",
|
||||
"Ces événements sont identiques, on garde B et on met A à la corbeille",
|
||||
"Ces événements sont identiques, on garde B et on masque A",
|
||||
)
|
||||
]
|
||||
choices += [
|
||||
("Merge", "Ces événements sont identiques, on fusionne à la main")
|
||||
("Merge", "Ces événements sont identiques, créé une nouvelle version par fusion")
|
||||
]
|
||||
else:
|
||||
choices = [("NotDuplicates", "Ces événements sont tous différents")]
|
||||
@ -191,11 +191,11 @@ class FixDuplicates(Form):
|
||||
"Select" + i,
|
||||
"Ces événements sont identiques, on garde "
|
||||
+ i
|
||||
+ " et on met les autres à la corbeille",
|
||||
+ " et on masque les autres",
|
||||
)
|
||||
]
|
||||
choices += [
|
||||
("Merge", "Ces événements sont identiques, on fusionne à la main")
|
||||
("Merge", "Ces événements sont identiques, on en créé un nouveau par fusion")
|
||||
]
|
||||
|
||||
self.fields["action"].choices = choices
|
||||
@ -248,7 +248,7 @@ class MergeDuplicates(Form):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
choices = [
|
||||
("event" + i, "Valeur de l'évenement " + i) for i in auc[0:nb_events]
|
||||
("event" + i, "Valeur de l'événement " + i) for i in auc[0:nb_events]
|
||||
]
|
||||
|
||||
for f in self.duplicates.get_items_comparison():
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: agenda_culturel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-10-18 00:07+0200\n"
|
||||
"POT-Creation-Date: 2024-10-28 18:58+0100\n"
|
||||
"PO-Revision-Date: 2023-10-29 14:16+0000\n"
|
||||
"Last-Translator: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
|
||||
"Language-Team: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
|
||||
@ -91,46 +91,46 @@ msgid "Evening"
|
||||
msgstr "Soir"
|
||||
|
||||
#: agenda_culturel/forms.py:44 agenda_culturel/models.py:171
|
||||
#: agenda_culturel/models.py:355 agenda_culturel/models.py:1378
|
||||
#: agenda_culturel/models.py:1480
|
||||
#: agenda_culturel/models.py:355 agenda_culturel/models.py:1401
|
||||
#: agenda_culturel/models.py:1506
|
||||
msgid "Category"
|
||||
msgstr "Catégorie"
|
||||
|
||||
#: agenda_culturel/forms.py:48
|
||||
#: agenda_culturel/forms.py:47
|
||||
msgid "Optional. If you dont specify a category, well find it for you."
|
||||
msgstr ""
|
||||
"Facultatif. Si tu ne donnes pas la catégorie, on s'occupe de la trouver."
|
||||
|
||||
#: agenda_culturel/forms.py:123
|
||||
#: agenda_culturel/forms.py:122
|
||||
msgid "The end date must be after the start date."
|
||||
msgstr "La date de fin doit être après la date de début."
|
||||
|
||||
#: agenda_culturel/forms.py:139
|
||||
#: agenda_culturel/forms.py:138
|
||||
msgid "The end time cannot be earlier than the start time."
|
||||
msgstr "L'heure de fin ne peut pas être avant l'heure de début."
|
||||
|
||||
#: agenda_culturel/forms.py:149
|
||||
#: agenda_culturel/forms.py:148
|
||||
msgid "JSON in the format expected for the import."
|
||||
msgstr "JSON dans le format attendu pour l'import"
|
||||
|
||||
#: agenda_culturel/forms.py:407
|
||||
#: agenda_culturel/forms.py:406
|
||||
msgid "Apply category {} to the event {}"
|
||||
msgstr "Appliquer la catégorie {} à l'événement {}"
|
||||
|
||||
#: agenda_culturel/forms.py:422 agenda_culturel/models.py:279
|
||||
#: agenda_culturel/models.py:1532
|
||||
#: agenda_culturel/forms.py:421 agenda_culturel/models.py:279
|
||||
#: agenda_culturel/models.py:1558
|
||||
msgid "Place"
|
||||
msgstr "Lieu"
|
||||
|
||||
#: agenda_culturel/forms.py:424
|
||||
#: agenda_culturel/forms.py:423
|
||||
msgid "Create a missing place"
|
||||
msgstr "Créer un lieu manquant"
|
||||
|
||||
#: agenda_culturel/forms.py:434
|
||||
#: agenda_culturel/forms.py:433
|
||||
msgid "Add \"{}\" to the aliases of the place"
|
||||
msgstr "Ajouter « {} » aux alias du lieu"
|
||||
|
||||
#: agenda_culturel/forms.py:461
|
||||
#: agenda_culturel/forms.py:460
|
||||
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 "
|
||||
@ -138,7 +138,7 @@ msgstr ""
|
||||
|
||||
#: agenda_culturel/models.py:49 agenda_culturel/models.py:94
|
||||
#: agenda_culturel/models.py:241 agenda_culturel/models.py:258
|
||||
#: agenda_culturel/models.py:1251 agenda_culturel/models.py:1324
|
||||
#: agenda_culturel/models.py:1273 agenda_culturel/models.py:1347
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
@ -212,7 +212,18 @@ msgstr "Position pour ordonner les catégories"
|
||||
msgid "Categories"
|
||||
msgstr "Catégories"
|
||||
|
||||
#: agenda_culturel/models.py:177 agenda_culturel/models.py:178
|
||||
#: agenda_culturel/models.py:178
|
||||
msgid "Fixed"
|
||||
msgstr "Résolu"
|
||||
|
||||
#: agenda_culturel/models.py:179
|
||||
msgid ""
|
||||
"This duplicated events is fixed, ie exactly one of the listed events is not "
|
||||
"masked."
|
||||
msgstr "Cet événement dupliqué est résolu, c'est-à-dire qu'exactement un seul "
|
||||
"des événements listés n'est pas masqué."
|
||||
|
||||
#: agenda_culturel/models.py:186 agenda_culturel/models.py:187
|
||||
msgid "Duplicated events"
|
||||
msgstr "Événements dupliqués"
|
||||
|
||||
@ -272,7 +283,7 @@ msgstr ""
|
||||
msgid "Places"
|
||||
msgstr "Lieux"
|
||||
|
||||
#: agenda_culturel/models.py:333 agenda_culturel/models.py:1365
|
||||
#: agenda_culturel/models.py:333 agenda_culturel/models.py:1388
|
||||
msgid "Published"
|
||||
msgstr "Publié"
|
||||
|
||||
@ -292,7 +303,7 @@ msgstr "Titre"
|
||||
msgid "Short title"
|
||||
msgstr "Titre court"
|
||||
|
||||
#: agenda_culturel/models.py:350 agenda_culturel/models.py:1448
|
||||
#: agenda_culturel/models.py:350 agenda_culturel/models.py:1474
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
|
||||
@ -326,7 +337,7 @@ msgstr "Heure de fin"
|
||||
msgid "Recurrence"
|
||||
msgstr "Récurrence"
|
||||
|
||||
#: agenda_culturel/models.py:390 agenda_culturel/models.py:1370
|
||||
#: agenda_culturel/models.py:390 agenda_culturel/models.py:1393
|
||||
msgid "Location"
|
||||
msgstr "Localisation"
|
||||
|
||||
@ -378,181 +389,193 @@ msgstr "Description de l'illustration"
|
||||
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:438
|
||||
msgid "Masked"
|
||||
msgstr "Masqué"
|
||||
|
||||
#: agenda_culturel/models.py:439
|
||||
msgid "This event is masked by a duplicated version."
|
||||
msgstr "L'événement est masqué par une version dupliquée."
|
||||
|
||||
#: agenda_culturel/models.py:447
|
||||
msgid "Importation source"
|
||||
msgstr "Source d'importation"
|
||||
|
||||
#: agenda_culturel/models.py:440
|
||||
#: agenda_culturel/models.py:448
|
||||
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:446
|
||||
#: agenda_culturel/models.py:454
|
||||
msgid "UUIDs"
|
||||
msgstr "UUIDs"
|
||||
|
||||
#: agenda_culturel/models.py:447
|
||||
#: agenda_culturel/models.py:455
|
||||
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:453
|
||||
#: agenda_culturel/models.py:461
|
||||
msgid "URLs"
|
||||
msgstr "URLs"
|
||||
|
||||
#: agenda_culturel/models.py:454
|
||||
#: agenda_culturel/models.py:462
|
||||
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:461
|
||||
#: agenda_culturel/models.py:469
|
||||
msgid "Tags"
|
||||
msgstr "Étiquettes"
|
||||
|
||||
#: agenda_culturel/models.py:462
|
||||
#: agenda_culturel/models.py:470
|
||||
msgid "A list of tags that describe the event."
|
||||
msgstr "Une liste d'étiquettes décrivant l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:469
|
||||
#: agenda_culturel/models.py:477
|
||||
msgid "Possibly duplicated"
|
||||
msgstr "Possibles doublons"
|
||||
|
||||
#: agenda_culturel/models.py:518
|
||||
#: agenda_culturel/models.py:539
|
||||
msgid "Event"
|
||||
msgstr "Événement"
|
||||
|
||||
#: agenda_culturel/models.py:519
|
||||
#: agenda_culturel/models.py:540
|
||||
msgid "Events"
|
||||
msgstr "Événements"
|
||||
|
||||
#: agenda_culturel/models.py:1242
|
||||
#: agenda_culturel/models.py:1264
|
||||
msgid "Contact message"
|
||||
msgstr "Message de contact"
|
||||
|
||||
#: agenda_culturel/models.py:1243
|
||||
#: agenda_culturel/models.py:1265
|
||||
msgid "Contact messages"
|
||||
msgstr "Messages de contact"
|
||||
|
||||
#: agenda_culturel/models.py:1246
|
||||
#: agenda_culturel/models.py:1268
|
||||
msgid "Subject"
|
||||
msgstr "Sujet"
|
||||
|
||||
#: agenda_culturel/models.py:1247
|
||||
#: agenda_culturel/models.py:1269
|
||||
msgid "The subject of your message"
|
||||
msgstr "Sujet de votre message"
|
||||
|
||||
#: agenda_culturel/models.py:1252
|
||||
#: agenda_culturel/models.py:1274
|
||||
msgid "Your name"
|
||||
msgstr "Votre nom"
|
||||
|
||||
#: agenda_culturel/models.py:1258
|
||||
#: agenda_culturel/models.py:1280
|
||||
msgid "Email address"
|
||||
msgstr "Adresse email"
|
||||
|
||||
#: agenda_culturel/models.py:1259
|
||||
#: agenda_culturel/models.py:1281
|
||||
msgid "Your email address"
|
||||
msgstr "Votre adresse email"
|
||||
|
||||
#: agenda_culturel/models.py:1264
|
||||
#: agenda_culturel/models.py:1286
|
||||
msgid "Message"
|
||||
msgstr "Message"
|
||||
|
||||
#: agenda_culturel/models.py:1264
|
||||
#: agenda_culturel/models.py:1286
|
||||
msgid "Your message"
|
||||
msgstr "Votre message"
|
||||
|
||||
#: agenda_culturel/models.py:1269 agenda_culturel/views.py:934
|
||||
#: agenda_culturel/models.py:1291 agenda_culturel/views.py:944
|
||||
msgid "Spam"
|
||||
msgstr "Spam"
|
||||
|
||||
#: agenda_culturel/models.py:1270
|
||||
#: agenda_culturel/models.py:1292
|
||||
msgid "This message is a spam."
|
||||
msgstr "Ce message est un spam."
|
||||
|
||||
#: agenda_culturel/models.py:1275 agenda_culturel/views.py:929
|
||||
#: agenda_culturel/models.py:1297 agenda_culturel/views.py:939
|
||||
msgid "Closed"
|
||||
msgstr "Fermé"
|
||||
|
||||
#: agenda_culturel/models.py:1277
|
||||
#: agenda_culturel/models.py:1299
|
||||
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:1282
|
||||
#: agenda_culturel/models.py:1304
|
||||
msgid "Comments"
|
||||
msgstr "Commentaires"
|
||||
|
||||
#: agenda_culturel/models.py:1283
|
||||
#: agenda_culturel/models.py:1305
|
||||
msgid "Comments on the message from the moderation team"
|
||||
msgstr "Commentaires sur ce message par l'équipe de modération"
|
||||
|
||||
#: agenda_culturel/models.py:1295 agenda_culturel/models.py:1428
|
||||
#: agenda_culturel/models.py:1317 agenda_culturel/models.py:1454
|
||||
msgid "Recurrent import"
|
||||
msgstr "Import récurrent"
|
||||
|
||||
#: agenda_culturel/models.py:1296
|
||||
#: agenda_culturel/models.py:1318
|
||||
msgid "Recurrent imports"
|
||||
msgstr "Imports récurrents"
|
||||
|
||||
#: agenda_culturel/models.py:1300
|
||||
#: agenda_culturel/models.py:1322
|
||||
msgid "ical"
|
||||
msgstr "ical"
|
||||
|
||||
#: agenda_culturel/models.py:1301
|
||||
#: agenda_culturel/models.py:1323
|
||||
msgid "ical no busy"
|
||||
msgstr "ical sans busy"
|
||||
|
||||
#: agenda_culturel/models.py:1302
|
||||
#: agenda_culturel/models.py:1324
|
||||
msgid "ical no VC"
|
||||
msgstr "ical sans VC"
|
||||
|
||||
#: agenda_culturel/models.py:1303
|
||||
#: agenda_culturel/models.py:1325
|
||||
msgid "lacoope.org"
|
||||
msgstr "lacoope.org"
|
||||
|
||||
#: agenda_culturel/models.py:1304
|
||||
#: agenda_culturel/models.py:1326
|
||||
msgid "la comédie"
|
||||
msgstr "la comédie"
|
||||
|
||||
#: agenda_culturel/models.py:1305
|
||||
#: agenda_culturel/models.py:1327
|
||||
msgid "le fotomat"
|
||||
msgstr "le fotomat"
|
||||
|
||||
#: agenda_culturel/models.py:1306
|
||||
#: agenda_culturel/models.py:1328
|
||||
#, fuzzy
|
||||
#| msgid "la puce à loreille"
|
||||
msgid "la puce à l'oreille"
|
||||
msgstr "la puce à loreille"
|
||||
|
||||
#: agenda_culturel/models.py:1307
|
||||
#: agenda_culturel/models.py:1329
|
||||
msgid "Plugin wordpress MEC"
|
||||
msgstr "Plugin wordpress MEC"
|
||||
|
||||
#: agenda_culturel/models.py:1308
|
||||
#: agenda_culturel/models.py:1330
|
||||
msgid "Événements d'une page FB"
|
||||
msgstr "Événements d'une page FB"
|
||||
|
||||
#: agenda_culturel/models.py:1309
|
||||
#: agenda_culturel/models.py:1331
|
||||
msgid "la cour des 3 coquins"
|
||||
msgstr "la cour des 3 coquins"
|
||||
|
||||
#: agenda_culturel/models.py:1312
|
||||
#: agenda_culturel/models.py:1332
|
||||
msgid "Arachnée concert"
|
||||
msgstr "Arachnée concert"
|
||||
|
||||
#: agenda_culturel/models.py:1335
|
||||
msgid "simple"
|
||||
msgstr "simple"
|
||||
|
||||
#: agenda_culturel/models.py:1313
|
||||
#: agenda_culturel/models.py:1336
|
||||
msgid "Headless Chromium"
|
||||
msgstr "chromium sans interface"
|
||||
|
||||
#: agenda_culturel/models.py:1314
|
||||
#: agenda_culturel/models.py:1337
|
||||
msgid "Headless Chromium (pause)"
|
||||
msgstr "chromium sans interface (pause)"
|
||||
|
||||
#: agenda_culturel/models.py:1319
|
||||
#: agenda_culturel/models.py:1342
|
||||
msgid "daily"
|
||||
msgstr "chaque jour"
|
||||
|
||||
#: agenda_culturel/models.py:1321
|
||||
#: agenda_culturel/models.py:1344
|
||||
msgid "weekly"
|
||||
msgstr "chaque semaine"
|
||||
|
||||
#: agenda_culturel/models.py:1326
|
||||
#: agenda_culturel/models.py:1349
|
||||
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."
|
||||
@ -560,135 +583,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:1333
|
||||
#: agenda_culturel/models.py:1356
|
||||
msgid "Processor"
|
||||
msgstr "Processeur"
|
||||
|
||||
#: agenda_culturel/models.py:1336
|
||||
#: agenda_culturel/models.py:1359
|
||||
msgid "Downloader"
|
||||
msgstr "Téléchargeur"
|
||||
|
||||
#: agenda_culturel/models.py:1343
|
||||
#: agenda_culturel/models.py:1366
|
||||
msgid "Import recurrence"
|
||||
msgstr "Récurrence d'import"
|
||||
|
||||
#: agenda_culturel/models.py:1350
|
||||
#: agenda_culturel/models.py:1373
|
||||
msgid "Source"
|
||||
msgstr "Source"
|
||||
|
||||
#: agenda_culturel/models.py:1351
|
||||
#: agenda_culturel/models.py:1374
|
||||
msgid "URL of the source document"
|
||||
msgstr "URL du document source"
|
||||
|
||||
#: agenda_culturel/models.py:1355
|
||||
#: agenda_culturel/models.py:1378
|
||||
msgid "Browsable url"
|
||||
msgstr "URL navigable"
|
||||
|
||||
#: agenda_culturel/models.py:1357
|
||||
#: agenda_culturel/models.py:1380
|
||||
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:1366
|
||||
#: agenda_culturel/models.py:1389
|
||||
msgid "Status of each imported event (published or draft)"
|
||||
msgstr "Status de chaque événement importé (publié ou brouillon)"
|
||||
|
||||
#: agenda_culturel/models.py:1371
|
||||
#: agenda_culturel/models.py:1394
|
||||
msgid "Address for each imported event"
|
||||
msgstr "Adresse de chaque événement importé"
|
||||
|
||||
#: agenda_culturel/models.py:1379
|
||||
#: agenda_culturel/models.py:1402
|
||||
msgid "Category of each imported event"
|
||||
msgstr "Catégorie de chaque événement importé"
|
||||
|
||||
#: agenda_culturel/models.py:1387
|
||||
#: agenda_culturel/models.py:1410
|
||||
msgid "Tags for each imported event"
|
||||
msgstr "Étiquettes de chaque événement importé"
|
||||
|
||||
#: agenda_culturel/models.py:1388
|
||||
#: agenda_culturel/models.py:1411
|
||||
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:1414
|
||||
#: agenda_culturel/models.py:1440
|
||||
msgid "Running"
|
||||
msgstr "En cours"
|
||||
|
||||
#: agenda_culturel/models.py:1415
|
||||
#: agenda_culturel/models.py:1441
|
||||
msgid "Canceled"
|
||||
msgstr "Annulé"
|
||||
|
||||
#: agenda_culturel/models.py:1416
|
||||
#: agenda_culturel/models.py:1442
|
||||
msgid "Success"
|
||||
msgstr "Succès"
|
||||
|
||||
#: agenda_culturel/models.py:1417
|
||||
#: agenda_culturel/models.py:1443
|
||||
msgid "Failed"
|
||||
msgstr "Erreur"
|
||||
|
||||
#: agenda_culturel/models.py:1420
|
||||
#: agenda_culturel/models.py:1446
|
||||
msgid "Batch importation"
|
||||
msgstr "Importation par lot"
|
||||
|
||||
#: agenda_culturel/models.py:1421
|
||||
#: agenda_culturel/models.py:1447
|
||||
msgid "Batch importations"
|
||||
msgstr "Importations par lot"
|
||||
|
||||
#: agenda_culturel/models.py:1429
|
||||
#: agenda_culturel/models.py:1455
|
||||
msgid "Reference to the recurrent import processing"
|
||||
msgstr "Référence du processus d'import récurrent"
|
||||
|
||||
#: agenda_culturel/models.py:1437
|
||||
#: agenda_culturel/models.py:1463
|
||||
msgid "URL (if not recurrent import)"
|
||||
msgstr "URL (si pas d'import récurrent)"
|
||||
|
||||
#: agenda_culturel/models.py:1439
|
||||
#: agenda_culturel/models.py:1465
|
||||
msgid "Source URL if no RecurrentImport is associated."
|
||||
msgstr "URL source si aucun import récurrent n'est associé"
|
||||
|
||||
#: agenda_culturel/models.py:1452
|
||||
#: agenda_culturel/models.py:1478
|
||||
msgid "Error message"
|
||||
msgstr "Votre message"
|
||||
|
||||
#: agenda_culturel/models.py:1456
|
||||
#: agenda_culturel/models.py:1482
|
||||
msgid "Number of collected events"
|
||||
msgstr "Nombre d'événements collectés"
|
||||
|
||||
#: agenda_culturel/models.py:1459
|
||||
#: agenda_culturel/models.py:1485
|
||||
msgid "Number of imported events"
|
||||
msgstr "Nombre d'événements importés"
|
||||
|
||||
#: agenda_culturel/models.py:1462
|
||||
#: agenda_culturel/models.py:1488
|
||||
msgid "Number of updated events"
|
||||
msgstr "Nombre d'événements mis à jour"
|
||||
|
||||
#: agenda_culturel/models.py:1465
|
||||
#: agenda_culturel/models.py:1491
|
||||
msgid "Number of removed events"
|
||||
msgstr "Nombre d'événements supprimés"
|
||||
|
||||
#: agenda_culturel/models.py:1473
|
||||
#: agenda_culturel/models.py:1499
|
||||
msgid "Weight"
|
||||
msgstr "Poids"
|
||||
|
||||
#: agenda_culturel/models.py:1474
|
||||
#: agenda_culturel/models.py:1500
|
||||
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:1481
|
||||
#: agenda_culturel/models.py:1507
|
||||
msgid "Category applied to the event"
|
||||
msgstr "Catégorie appliquée à l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:1486
|
||||
#: agenda_culturel/models.py:1512
|
||||
msgid "Contained in the title"
|
||||
msgstr "Contenu dans le titre"
|
||||
|
||||
#: agenda_culturel/models.py:1487
|
||||
#: agenda_culturel/models.py:1513
|
||||
msgid "Text contained in the event title"
|
||||
msgstr "Texte contenu dans le titre de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:1493
|
||||
#: agenda_culturel/models.py:1519
|
||||
msgid "Exact title extract"
|
||||
msgstr "Extrait exact du titre"
|
||||
|
||||
#: agenda_culturel/models.py:1495
|
||||
#: agenda_culturel/models.py:1521
|
||||
msgid ""
|
||||
"If checked, the extract will be searched for in the title using the exact "
|
||||
"form (capitals, accents)."
|
||||
@ -696,19 +719,19 @@ msgstr ""
|
||||
"Si coché, l'extrait sera recherché dans le titre en utilisant la forme "
|
||||
"exacte (majuscules, accents)"
|
||||
|
||||
#: agenda_culturel/models.py:1501
|
||||
#: agenda_culturel/models.py:1527
|
||||
msgid "Contained in the description"
|
||||
msgstr "Contenu dans la description"
|
||||
|
||||
#: agenda_culturel/models.py:1502
|
||||
#: agenda_culturel/models.py:1528
|
||||
msgid "Text contained in the description"
|
||||
msgstr "Texte contenu dans la description"
|
||||
|
||||
#: agenda_culturel/models.py:1508
|
||||
#: agenda_culturel/models.py:1534
|
||||
msgid "Exact description extract"
|
||||
msgstr "Extrait exact de description"
|
||||
|
||||
#: agenda_culturel/models.py:1510
|
||||
#: agenda_culturel/models.py:1536
|
||||
msgid ""
|
||||
"If checked, the extract will be searched for in the description using the "
|
||||
"exact form (capitals, accents)."
|
||||
@ -716,19 +739,19 @@ msgstr ""
|
||||
"Si coché, l'extrait sera recherché dans la description en utilisant la forme "
|
||||
"exacte (majuscules, accents)"
|
||||
|
||||
#: agenda_culturel/models.py:1516
|
||||
#: agenda_culturel/models.py:1542
|
||||
msgid "Contained in the location"
|
||||
msgstr "Contenu dans la localisation"
|
||||
|
||||
#: agenda_culturel/models.py:1517
|
||||
#: agenda_culturel/models.py:1543
|
||||
msgid "Text contained in the event location"
|
||||
msgstr "Texte contenu dans la localisation de l'événement"
|
||||
|
||||
#: agenda_culturel/models.py:1523
|
||||
#: agenda_culturel/models.py:1549
|
||||
msgid "Exact location extract"
|
||||
msgstr "Extrait exact de localisation"
|
||||
|
||||
#: agenda_culturel/models.py:1525
|
||||
#: agenda_culturel/models.py:1551
|
||||
msgid ""
|
||||
"If checked, the extract will be searched for in the location using the exact "
|
||||
"form (capitals, accents)."
|
||||
@ -736,56 +759,56 @@ msgstr ""
|
||||
"Si coché, l'extrait sera recherché dans la localisation en utilisant la "
|
||||
"forme exacte (majuscules, accents)"
|
||||
|
||||
#: agenda_culturel/models.py:1533
|
||||
#: agenda_culturel/models.py:1559
|
||||
msgid "Location from place"
|
||||
msgstr "Localisation depuis le lieu"
|
||||
|
||||
#: agenda_culturel/models.py:1540
|
||||
#: agenda_culturel/models.py:1566
|
||||
msgid "Categorisation rule"
|
||||
msgstr "Règle de catégorisation"
|
||||
|
||||
#: agenda_culturel/models.py:1541
|
||||
#: agenda_culturel/models.py:1567
|
||||
msgid "Categorisation rules"
|
||||
msgstr "Règles de catégorisation"
|
||||
|
||||
#: agenda_culturel/models.py:1608 agenda_culturel/models.py:1640
|
||||
#: agenda_culturel/models.py:1634 agenda_culturel/models.py:1666
|
||||
msgid "Question"
|
||||
msgstr "Question"
|
||||
|
||||
#: agenda_culturel/models.py:1609 agenda_culturel/models.py:1647
|
||||
#: agenda_culturel/models.py:1635 agenda_culturel/models.py:1673
|
||||
msgid "Text that will be shown to moderators"
|
||||
msgstr "Text tel que présenté aux modérateurices"
|
||||
|
||||
#: agenda_culturel/models.py:1615
|
||||
#: agenda_culturel/models.py:1641
|
||||
msgid "Moderation question"
|
||||
msgstr "Question de modération"
|
||||
|
||||
#: agenda_culturel/models.py:1616
|
||||
#: agenda_culturel/models.py:1642
|
||||
msgid "Moderation questions"
|
||||
msgstr "Questions de modération"
|
||||
|
||||
#: agenda_culturel/models.py:1641
|
||||
#: agenda_culturel/models.py:1667
|
||||
msgid "Associated question from moderation"
|
||||
msgstr "Question associée pour la modération"
|
||||
|
||||
#: agenda_culturel/models.py:1646
|
||||
#: agenda_culturel/models.py:1672
|
||||
msgid "Answer"
|
||||
msgstr "Réponse"
|
||||
|
||||
#: agenda_culturel/models.py:1653
|
||||
#: agenda_culturel/models.py:1679
|
||||
msgid "Adds tags"
|
||||
msgstr "Ajoute les étiquettes"
|
||||
|
||||
#: agenda_culturel/models.py:1654
|
||||
#: agenda_culturel/models.py:1680
|
||||
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:1660
|
||||
#: agenda_culturel/models.py:1686
|
||||
msgid "Removes tags"
|
||||
msgstr "Retire les étiquettes"
|
||||
|
||||
#: agenda_culturel/models.py:1661
|
||||
#: agenda_culturel/models.py:1687
|
||||
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."
|
||||
@ -890,97 +913,92 @@ msgstr "Intégration de {} url(s) dans notre processus d'import."
|
||||
msgid "Integrating {} into our import process."
|
||||
msgstr "Intégration de {} dans notre processus d'import."
|
||||
|
||||
#: agenda_culturel/views.py:889
|
||||
#: agenda_culturel/views.py:899
|
||||
msgid "Your message has been sent successfully."
|
||||
msgstr "Votre message a été envoyé avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:899
|
||||
#: agenda_culturel/views.py:909
|
||||
msgid "The contact message has been successfully deleted."
|
||||
msgstr "Le message de contact a été supprimé avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:913
|
||||
#: agenda_culturel/views.py:923
|
||||
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:929
|
||||
#: agenda_culturel/views.py:939
|
||||
msgid "Open"
|
||||
msgstr "Ouvert"
|
||||
|
||||
#: agenda_culturel/views.py:934
|
||||
#: agenda_culturel/views.py:944
|
||||
msgid "Non spam"
|
||||
msgstr "Non spam"
|
||||
|
||||
#: agenda_culturel/views.py:997
|
||||
#: agenda_culturel/views.py:1007
|
||||
#, fuzzy
|
||||
#| msgid "The event has been successfully deleted."
|
||||
msgid "Spam has been successfully deleted."
|
||||
msgstr "L'événement a été supprimé avec succès"
|
||||
|
||||
#: agenda_culturel/views.py:1014
|
||||
#: agenda_culturel/views.py:1024
|
||||
msgid "Search"
|
||||
msgstr "Rechercher"
|
||||
|
||||
#: agenda_culturel/views.py:1200
|
||||
#: agenda_culturel/views.py:1210
|
||||
msgid "The import has been run successfully."
|
||||
msgstr "L'import a été lancé avec succès"
|
||||
|
||||
#: agenda_culturel/views.py:1219
|
||||
#: agenda_culturel/views.py:1229
|
||||
msgid "The import has been canceled."
|
||||
msgstr "L'import a été annulé"
|
||||
|
||||
#: agenda_culturel/views.py:1293
|
||||
#: agenda_culturel/views.py:1303
|
||||
msgid "The recurrent import has been successfully modified."
|
||||
msgstr "L'import récurrent a été modifié avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:1302
|
||||
#: agenda_culturel/views.py:1312
|
||||
msgid "The recurrent import has been successfully deleted."
|
||||
msgstr "L'import récurrent a été supprimé avec succès"
|
||||
|
||||
#: agenda_culturel/views.py:1342
|
||||
#: agenda_culturel/views.py:1352
|
||||
msgid "The import has been launched."
|
||||
msgstr "L'import a été lancé"
|
||||
|
||||
#: agenda_culturel/views.py:1364
|
||||
#: agenda_culturel/views.py:1374
|
||||
msgid "Imports has been launched."
|
||||
msgstr "Les imports ont été lancés"
|
||||
|
||||
#: agenda_culturel/views.py:1449
|
||||
msgid "The merge has been successfully completed."
|
||||
msgstr "La fusion a été réalisée avec succès."
|
||||
#: agenda_culturel/views.py:1467
|
||||
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:1483
|
||||
#: agenda_culturel/views.py:1504
|
||||
msgid "Events have been marked as unduplicated."
|
||||
msgstr "Les événements ont été marqués comme non dupliqués."
|
||||
|
||||
#: agenda_culturel/views.py:1505
|
||||
msgid ""
|
||||
"The selected event has been retained, while the other has been moved to the "
|
||||
"recycle bin."
|
||||
#: agenda_culturel/views.py:1526
|
||||
msgid "The selected event has been retained, while the other has been masked."
|
||||
msgstr ""
|
||||
"L'événement sélectionné a été conservé, l'autre a été déplacé dans la "
|
||||
"corbeille."
|
||||
"L'événement sélectionné a été retenu, l'autre a été masqué."
|
||||
|
||||
#: agenda_culturel/views.py:1512
|
||||
#: agenda_culturel/views.py:1533
|
||||
msgid ""
|
||||
"The selected event has been retained, while the others have been moved to "
|
||||
"the recycle bin."
|
||||
"The selected event has been retained, while the others havec been masked."
|
||||
msgstr ""
|
||||
"L'événement sélectionné a été conservé, les autres ont été déplacés dans la "
|
||||
"corbeille."
|
||||
"L'événement sélectionné a été retenu, les autres ont été masqués."
|
||||
|
||||
#: agenda_culturel/views.py:1523
|
||||
#: agenda_culturel/views.py:1546
|
||||
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:1556
|
||||
#: agenda_culturel/views.py:1578
|
||||
msgid "Cleaning up duplicates: {} item(s) removed."
|
||||
msgstr "Nettoyage des dupliqués: {} élément(s) supprimés."
|
||||
|
||||
#: agenda_culturel/views.py:1600
|
||||
#: agenda_culturel/views.py:1625
|
||||
msgid "The event was successfully duplicated."
|
||||
msgstr "L'événement a été marqué dupliqué avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:1608
|
||||
#: agenda_culturel/views.py:1633
|
||||
msgid ""
|
||||
"The event has been successfully flagged as a duplicate. The moderation team "
|
||||
"will deal with your suggestion shortly."
|
||||
@ -988,63 +1006,63 @@ 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:1661
|
||||
#: agenda_culturel/views.py:1686
|
||||
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:1670
|
||||
#: agenda_culturel/views.py:1695
|
||||
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:1692 agenda_culturel/views.py:1739
|
||||
#: agenda_culturel/views.py:1717 agenda_culturel/views.py:1764
|
||||
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:1699 agenda_culturel/views.py:1746
|
||||
#: agenda_culturel/views.py:1724 agenda_culturel/views.py:1771
|
||||
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:1706 agenda_culturel/views.py:1753
|
||||
#: agenda_culturel/views.py:1731 agenda_culturel/views.py:1778
|
||||
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:1793
|
||||
#: agenda_culturel/views.py:1818
|
||||
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:1919 agenda_culturel/views.py:1981
|
||||
#: agenda_culturel/views.py:2019
|
||||
#: agenda_culturel/views.py:1944 agenda_culturel/views.py:2006
|
||||
#: agenda_culturel/views.py:2044
|
||||
msgid "{} events have been updated."
|
||||
msgstr "{} événements ont été mis à jour."
|
||||
|
||||
#: agenda_culturel/views.py:1922 agenda_culturel/views.py:1983
|
||||
#: agenda_culturel/views.py:2022
|
||||
#: agenda_culturel/views.py:1947 agenda_culturel/views.py:2008
|
||||
#: agenda_culturel/views.py:2047
|
||||
msgid "1 event has been updated."
|
||||
msgstr "1 événement a été mis à jour"
|
||||
|
||||
#: agenda_culturel/views.py:1924 agenda_culturel/views.py:1985
|
||||
#: agenda_culturel/views.py:2024
|
||||
#: agenda_culturel/views.py:1949 agenda_culturel/views.py:2010
|
||||
#: agenda_culturel/views.py:2049
|
||||
msgid "No events have been modified."
|
||||
msgstr "Aucun événement n'a été modifié."
|
||||
|
||||
#: agenda_culturel/views.py:1933
|
||||
#: agenda_culturel/views.py:1958
|
||||
msgid "The place has been successfully updated."
|
||||
msgstr "Le lieu a été modifié avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:1942
|
||||
#: agenda_culturel/views.py:1967
|
||||
msgid "The place has been successfully created."
|
||||
msgstr "Le lieu a été créé avec succès."
|
||||
|
||||
#: agenda_culturel/views.py:2007
|
||||
#: agenda_culturel/views.py:2032
|
||||
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:2011
|
||||
#: agenda_culturel/views.py:2036
|
||||
msgid "A new alias has been added to the selected place."
|
||||
msgstr "Un nouvel alias a été créé pour le lieu sélectionné."
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.9 on 2024-10-20 11:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('agenda_culturel', '0090_alter_recurrentimport_processor'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='duplicatedevents',
|
||||
name='fixed',
|
||||
field=models.BooleanField(blank=True, default=False, help_text='This duplicated events is fixed, ie exactly one of the listed events is not masked.', null=True, verbose_name='Fixed'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='masked',
|
||||
field=models.BooleanField(blank=True, default=False, help_text='This event is masked by a duplicated version.', null=True, verbose_name='Masked'),
|
||||
),
|
||||
]
|
@ -173,28 +173,60 @@ class Category(models.Model):
|
||||
|
||||
|
||||
class DuplicatedEvents(models.Model):
|
||||
|
||||
fixed = models.BooleanField(
|
||||
verbose_name=_("Fixed"),
|
||||
help_text=_("This duplicated events is fixed, ie exactly one of the listed events is not masked."),
|
||||
default=False,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Duplicated events")
|
||||
verbose_name_plural = _("Duplicated events")
|
||||
|
||||
def nb_duplicated(self):
|
||||
return Event.objects.filter(possibly_duplicated=self).count()
|
||||
return self.event_set.count()
|
||||
|
||||
def nb_duplicated_not_fixed(self):
|
||||
return self.event_set.filter(possibly_duplicated=self, fixed=False).count()
|
||||
|
||||
def get_duplicated(self):
|
||||
return Event.objects.filter(possibly_duplicated=self).order_by(
|
||||
return self.event_set.order_by(
|
||||
"created_date"
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("view_duplicate", kwargs={"pk": self.pk})
|
||||
|
||||
def get_one_event(self):
|
||||
return self.event_set.filter(masked=False).first()
|
||||
|
||||
def merge_into(self, other):
|
||||
# for all objects associated to this group
|
||||
for e in Event.objects.filter(possibly_duplicated=self):
|
||||
for e in self.event_set.all():
|
||||
# change their group membership
|
||||
e.possibly_duplicated = other
|
||||
# save them
|
||||
e.save()
|
||||
other.save(force_fixed=False)
|
||||
# then delete the empty group
|
||||
self.delete()
|
||||
|
||||
def fix(self, event=None):
|
||||
events = self.event_set.all()
|
||||
if event is None:
|
||||
events = events.sort_by("-created_date")
|
||||
for e in events:
|
||||
if event is None:
|
||||
event = e
|
||||
e.masked = e != event
|
||||
Event.objects.bulk_update(events, fields=["masked"])
|
||||
self.save()
|
||||
return len(events)
|
||||
|
||||
|
||||
def merge_groups(groups):
|
||||
if len(groups) == 0:
|
||||
return None
|
||||
@ -216,8 +248,8 @@ class DuplicatedEvents(models.Model):
|
||||
nb, d = singletons.delete()
|
||||
return nb
|
||||
|
||||
def remove_similar_entries():
|
||||
to_be_removed = []
|
||||
def fix_similar_entries():
|
||||
to_be_fixed = []
|
||||
|
||||
dup_events = Event.objects.order_by('possibly_duplicated').prefetch_related('possibly_duplicated', 'category')
|
||||
duplicates = defaultdict(list)
|
||||
@ -228,15 +260,28 @@ class DuplicatedEvents(models.Model):
|
||||
comp = Event.get_comparison(duplicates[d])
|
||||
similar = len([c for c in comp if not c["similar"]]) == 0
|
||||
if similar:
|
||||
to_be_removed.append(d)
|
||||
to_be_fixed.append(d)
|
||||
|
||||
nb = len(to_be_removed)
|
||||
nb = len(to_be_fixed)
|
||||
if nb > 0:
|
||||
logger.warning("Removing: " + str(nb) + " similar duplicated")
|
||||
for s in to_be_removed:
|
||||
s.delete()
|
||||
for s in to_be_fixed:
|
||||
s.fix()
|
||||
|
||||
return nb
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if "force_fixed" in kwargs:
|
||||
self.fixed = kwargs["force_fixed"]
|
||||
del kwargs["force_fixed"]
|
||||
elif not self.pk:
|
||||
self.fixed = False
|
||||
else:
|
||||
self.fixed = self.event_set.filter(masked=False).count() == 1
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
class ReferenceLocation(models.Model):
|
||||
name = models.CharField(verbose_name=_("Name"), help_text=_("Name of the location"), unique=True, null=False)
|
||||
location = LocationField(based_fields=["name"], zoom=12, default=Point(3.08333, 45.783329), srid=4326)
|
||||
@ -434,6 +479,14 @@ class Event(models.Model):
|
||||
max_length=1024,
|
||||
)
|
||||
|
||||
masked = models.BooleanField(
|
||||
verbose_name=_("Masked"),
|
||||
help_text=_("This event is masked by a duplicated version."),
|
||||
default=False,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
import_sources = ArrayField(
|
||||
models.CharField(max_length=512),
|
||||
verbose_name=_("Importation source"),
|
||||
@ -487,10 +540,13 @@ class Event(models.Model):
|
||||
last = self.get_consolidated_end_day()
|
||||
return [first + timedelta(n) for n in range(int((last - first).days) + 1)]
|
||||
|
||||
def get_nb_events_same_dates(self):
|
||||
def get_nb_events_same_dates(self, remove_same_dup=True):
|
||||
first = self.start_day
|
||||
last = self.get_consolidated_end_day()
|
||||
calendar = CalendarList(first, last, exact=True)
|
||||
ignore_dup = None
|
||||
if remove_same_dup:
|
||||
ignore_dup = self.possibly_duplicated
|
||||
calendar = CalendarList(first, last, exact=True, ignore_dup=ignore_dup)
|
||||
return [(len(d.events), d.date) for dstr, d in calendar.get_calendar_days().items()]
|
||||
|
||||
def is_single_day(self, intuitive=True):
|
||||
@ -911,6 +967,7 @@ class Event(models.Model):
|
||||
for attr in Event.data_fields(all=True, 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 is "" else v for v in values]
|
||||
# only consider fixed part of Facebook urls
|
||||
if attr == "image":
|
||||
values = [v.split("?")[0] if "fbcdn.net" in v else v for v in values]
|
||||
@ -941,7 +998,7 @@ class Event(models.Model):
|
||||
else:
|
||||
# otherwise merge existing groups
|
||||
group = DuplicatedEvents.merge_groups(groups)
|
||||
group.save()
|
||||
group.save(force_fixed=False)
|
||||
|
||||
# set the possibly duplicated group for the current object
|
||||
self.possibly_duplicated = group
|
||||
@ -1170,7 +1227,7 @@ class Event(models.Model):
|
||||
|
||||
return dtstart, dtend
|
||||
|
||||
def get_concurrent_events(self):
|
||||
def get_concurrent_events(self, remove_same_dup=True):
|
||||
day = self.current_date if hasattr(self, "current_date") else self.start_day
|
||||
day_events = CalendarDay(self.start_day).get_events()
|
||||
return [
|
||||
@ -1179,6 +1236,7 @@ class Event(models.Model):
|
||||
if e != self
|
||||
and self.is_concurrent_event(e, day)
|
||||
and e.status == Event.STATUS.PUBLISHED
|
||||
and (e.possibly_duplicated is None or e.possibly_duplicated != self.possibly_duplicated)
|
||||
]
|
||||
|
||||
def is_concurrent_event(self, e, day):
|
||||
|
@ -886,8 +886,8 @@ aside nav a.badge {
|
||||
float: right;
|
||||
}
|
||||
|
||||
aside nav.paragraph li a {
|
||||
display: inline-block;
|
||||
aside nav.paragraph li a, aside .no-breakline li a {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.body-fixed {
|
||||
@ -1027,6 +1027,9 @@ article>article {
|
||||
@extend .badge-circle;
|
||||
font-size: 140%;
|
||||
}
|
||||
.badge-secondary {
|
||||
background-color: var(--secondary);
|
||||
}
|
||||
li {
|
||||
list-style-type: none;
|
||||
}
|
||||
@ -1039,15 +1042,20 @@ article>article {
|
||||
background: rgba(255, 0, 76, 0.1);
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
}
|
||||
.badge-small {
|
||||
@extend .badge-circle;
|
||||
font-size: 70%;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.badge-small {
|
||||
@extend .badge-circle;
|
||||
font-size: 70%;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
span.badge-small {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.strike {
|
||||
|
@ -0,0 +1,31 @@
|
||||
{% load utils_extra %}
|
||||
{% load event_extra %}
|
||||
|
||||
<div class="grid">
|
||||
{% for e in object.get_duplicated %}
|
||||
<div class="grid entete-badge">
|
||||
<div class="badge-large{% if e.masked %} badge-secondary{% endif %}">
|
||||
{{ forloop.counter0|int_to_abc }}
|
||||
</div>
|
||||
<ul>
|
||||
<li>{{ e|picto_status }} <a href="{{ e.get_absolute_url }}">{{ e.title }}</a></li>
|
||||
<li>Masqué : {{ e.masked|yesno:"Oui,Non" }}</li>
|
||||
<li>Création : {{ e.created_date }}</li>
|
||||
<li>Dernière modification : {{ e.modified_date }}</li>
|
||||
{% if e.imported_date %}<li>Dernière importation : {{ e.imported_date }}</li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% for e in object.get_items_comparison %}
|
||||
<h3>{% event_field_verbose_name e.key %}</h3>
|
||||
{% if e.similar %}
|
||||
<div class="comparison-item">Identique : {% field_to_html e.values e.key %}</div>
|
||||
{% else %}
|
||||
<div class="grid comparison-item">
|
||||
{% for i in e.values %}
|
||||
<div class="duplicated"><div class="badge-small">{{ forloop.counter0|int_to_abc }} </div> {% field_to_html i e.key %}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
@ -0,0 +1,25 @@
|
||||
{% load cat_extra %}
|
||||
{% load utils_extra %}
|
||||
{% load event_extra %}
|
||||
|
||||
|
||||
<article>
|
||||
<header><a href="{% url 'view_duplicate' duplicate.pk %}">
|
||||
{% if duplicate.fixed %}Duplication{% else %}Possible duplication{% endif %}
|
||||
:</a> {{ events|length }} événements le {{ events.0.start_day }}
|
||||
</header>
|
||||
<ul>
|
||||
{% for e in events %}
|
||||
<li>{{ e.start_day }}{% if e.start_time %} à {{ e.start_time }}{% endif %} : {{ e|picto_status }} <a href="{{ e.get_absolute_url }}">{{ e.title }}</a> créé le {{ e.created_date }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if perms.agenda_culturel.change_duplicatedevents %}
|
||||
<footer class="infos-and-buttons">
|
||||
<div class="infos"></div>
|
||||
<div class="buttons">
|
||||
<a role="button" href="{% url 'view_duplicate' duplicate.pk %}">Consulter {% picto_from_name "eye" %}</a>
|
||||
<a role="button" href="{% url 'fix_duplicate' duplicate.pk %}">{% if duplicate.fixed %}Modifier{% else %}Corriger{% endif %} {% picto_from_name "tool" %}</a>
|
||||
</div>
|
||||
</footer>
|
||||
{% endif %}
|
||||
</article>
|
@ -0,0 +1,11 @@
|
||||
<article>
|
||||
<header><h2>Informations techniques</h2></header>
|
||||
{% for e in object.get_duplicated %}
|
||||
<article>
|
||||
<header>
|
||||
<h3>{{ e }}</h3>
|
||||
</header>
|
||||
{% include "agenda_culturel/event-info-inc.html" with object=e %}
|
||||
</article>
|
||||
{% endfor %}
|
||||
</article>
|
41
src/agenda_culturel/templates/agenda_culturel/duplicate.html
Normal file
41
src/agenda_culturel/templates/agenda_culturel/duplicate.html
Normal file
@ -0,0 +1,41 @@
|
||||
{% extends "agenda_culturel/page-admin.html" %}
|
||||
|
||||
{% load utils_extra %}
|
||||
{% load event_extra %}
|
||||
|
||||
|
||||
{% load cat_extra %}
|
||||
{% block entete_header %}
|
||||
{% css_categories %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<article>
|
||||
<header>
|
||||
<a href="{% url 'duplicates' %}" role="button">< Tous les dupliqués</a>
|
||||
|
||||
<h1>{% block title %}{% block og_title %}Événements {% if not object.fixed %}possiblement{% endif %} dupliqués{% endblock %}{% endblock %}</h1>
|
||||
{% if object.fixed %}
|
||||
<p>Les événements ci-dessous sont des duplicats du même événement, probablement issus de différentes
|
||||
sources. La version qui sera affichée aux internautes en priorité est la version
|
||||
{% for e in object.get_duplicated %}{% if not e.masked %}<span class="badge-small">{{ forloop.counter0|int_to_abc }}</span>{% endif %}{% endfor %}.
|
||||
</p>
|
||||
{% else %}
|
||||
<p>Les événements ci-dessous ont été détectés ou signalés comme possiblement dupliqué.
|
||||
Les éléments qui diffèrent ont été dupliqués et mis en évidence. </p>
|
||||
{% endif %}
|
||||
|
||||
<div class="infos-and-buttons">
|
||||
<div class="infos"></div>
|
||||
<div class="buttons">
|
||||
<a role="button" href="{% url 'fix_duplicate' object.pk %}">Corriger {% picto_from_name "tool" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{% include "agenda_culturel/duplicate-diff-inc.html" with object=object %}
|
||||
</article>
|
||||
|
||||
{% include "agenda_culturel/duplicate-info-inc.html" with object=object %}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -3,7 +3,7 @@
|
||||
{% load utils_extra %}
|
||||
{% load event_extra %}
|
||||
|
||||
{% block title %}{% block og_title %}Événements possiblement dupliqués{% endblock %}{% endblock %}
|
||||
{% block title %}{% block og_title %}Événements dupliqués{% endblock %}{% endblock %}
|
||||
|
||||
{% load cat_extra %}
|
||||
{% block entete_header %}
|
||||
@ -19,29 +19,19 @@
|
||||
<div class="grid two-columns">
|
||||
<article>
|
||||
<header>
|
||||
<h1>Événements possiblement dupliqués</h1>
|
||||
<h1>Événements dupliqués</h1>
|
||||
<form method="get" class="form django-form recent moderation-events">
|
||||
{{ filter.form.as_div }}<br />
|
||||
<button type="submit">Filtrer</button><br />
|
||||
</form>
|
||||
|
||||
<p>{{ paginator.count }} événement{{ paginator.count|pluralize }} dupliqués {% if filter.form.fixed.value %}sont résolus{% else %}doivent être résolus{% endif %}.</p>
|
||||
</header>
|
||||
|
||||
<div>
|
||||
{% for obj in paginator_filter %}
|
||||
{% with obj.get_duplicated as events %}
|
||||
<article>
|
||||
<header><a href="{% url 'view_duplicate' obj.pk %}">Possible duplication :</a> {{ events|length }} événements le {{ events.0.start_day }}
|
||||
</header>
|
||||
<ul>
|
||||
{% for e in events %}
|
||||
<li>{{ e.start_day }}{% if e.start_time %} à {{ e.start_time }}{% endif %} : {{ e|picto_status }} <a href="{{ e.get_absolute_url }}">{{ e.title }}</a> créé le {{ e.created_date }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if perms.agenda_culturel.change_duplicatedevents %}
|
||||
<footer class="infos-and-buttons">
|
||||
<div class="infos"></div>
|
||||
<div class="buttons">
|
||||
<a role="button" href="{% url 'fix_duplicate' obj.pk %}">Corriger {% picto_from_name "tool" %}</a>
|
||||
</div>
|
||||
</footer>
|
||||
{% endif %}
|
||||
</article>
|
||||
{% include "agenda_culturel/duplicate-inc.html" with duplicate=obj events=events %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -5,6 +5,7 @@
|
||||
{% if object.modified_date %}<li>Dernière modification : {{ object.modified_date }}</li>{% endif %}
|
||||
{% if object.moderated_date %}<li>Dernière modération : {{ object.moderated_date }}</li>{% endif %}
|
||||
{% if object.imported_date %}<li>Dernière importation : {{ object.imported_date }}</li>{% endif %}
|
||||
<li>Masqué : {{ object.masked }}</li>
|
||||
{% if object.uuids %}
|
||||
{% if object.uuids|length > 0 %}
|
||||
<li>UUIDs (identifiants uniques d'événements dans les sources) :
|
||||
|
@ -3,7 +3,6 @@
|
||||
{% load utils_extra %}
|
||||
{% load event_extra %}
|
||||
|
||||
{% block title %}{% block og_title %}Événements possiblement dupliqués{% endblock %}{% endblock %}
|
||||
|
||||
{% load cat_extra %}
|
||||
{% block entete_header %}
|
||||
@ -13,11 +12,17 @@
|
||||
{% block content %}
|
||||
<article>
|
||||
<header>
|
||||
<h1>Corriger des événements possiblement dupliqués</h1>
|
||||
<h1>{% block title %}{% block og_title %}{% if object.fixed %}Modifier{% else %}Corriger{% endif %} des événements {% if not object.fixed %}possiblement{% endif %} dupliqués{% endblock %}{% endblock %}</h1>
|
||||
{% if object.fixed %}
|
||||
<p>Les événements ci-dessous sont des duplicats du même événement, probablement issus de différentes
|
||||
sources. La version qui sera affichée aux internautes en priorité est la version
|
||||
{% for e in object.get_duplicated %}{% if not e.masked %}<span class="badge-small">{{ forloop.counter0|int_to_abc }}</span>{% endif %}{% endfor %}.
|
||||
</p>
|
||||
{% else %}
|
||||
<p>Les événements ci-dessous ont été détectés ou signalés comme possiblement dupliqué.
|
||||
Les éléments qui diffèrent ont été dupliqués et mis en évidence. </p>
|
||||
{% endif %}
|
||||
|
||||
{% if form %}
|
||||
<p>Choisissez dans la liste ci-dessous l'action que vous voulez réaliser. À noter que
|
||||
s'il y a plus de deux événements, toutes les possibilités ne sont pas disponibles, et
|
||||
il vous faudra peut-être réaliser certaines opérations à la main.</p>
|
||||
@ -29,52 +34,11 @@
|
||||
<input type="submit" value="Appliquer">
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<div class="infos-and-buttons">
|
||||
<div class="infos"></div>
|
||||
<div class="buttons">
|
||||
<a role="button" href="{% url 'fix_duplicate' object.pk %}">Corriger {% picto_from_name "tool" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</header>
|
||||
<div class="grid">
|
||||
{% for e in object.get_duplicated %}
|
||||
<div class="grid entete-badge">
|
||||
<div class="badge-large">
|
||||
{{ forloop.counter0|int_to_abc }}
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="{{ e.get_absolute_url }}">{{ e.title }}</a></li>
|
||||
<li>Création : {{ e.created_date }}</li>
|
||||
<li>Dernière modification : {{ e.modified_date }}</li>
|
||||
{% if e.imported_date %}<li>Dernière importation : {{ e.imported_date }}</li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% for e in object.get_items_comparison %}
|
||||
<h3>{% event_field_verbose_name e.key %}</h3>
|
||||
{% if e.similar %}
|
||||
<div class="comparison-item">Identique : {% field_to_html e.values e.key %}</div>
|
||||
{% else %}
|
||||
<div class="grid comparison-item">
|
||||
{% for i in e.values %}
|
||||
<div class="duplicated"><div class="badge-small">{{ forloop.counter0|int_to_abc }} </div> {% field_to_html i e.key %}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% include "agenda_culturel/duplicate-diff-inc.html" with object=object %}
|
||||
</article>
|
||||
|
||||
<article>
|
||||
<header><h2>Informations techniques</h2></header>
|
||||
{% for e in object.get_duplicated %}
|
||||
<article>
|
||||
<h3>{{ e }}</h3>
|
||||
{% include "agenda_culturel/event-info-inc.html" with object=e %}
|
||||
</article>
|
||||
{% endfor %}
|
||||
</article>
|
||||
{% include "agenda_culturel/duplicate-info-inc.html" with object=object %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
<header>
|
||||
<h1>Fusionner les événements dupliqués</h1>
|
||||
<p>Pour chacun des champs non identiques, choisissez la version qui vous convient pour créer un événement
|
||||
résultat de la fusion. Les événements source seront déplacés dans la corbeille.</p>
|
||||
résultat de la fusion. Les événements source seront masqués.</p>
|
||||
|
||||
</header>
|
||||
<form method="post">
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
{% load cat_extra %}
|
||||
{% load utils_extra %}
|
||||
{% load event_extra %}
|
||||
|
||||
|
||||
{% block title %}{% block og_title %}{{ event.title }}{% endblock %}{% endblock %}
|
||||
@ -84,22 +85,34 @@
|
||||
{% endwith %}
|
||||
</article>
|
||||
{% if event.possibly_duplicated %}
|
||||
{% with poss_dup=event.get_possibly_duplicated|only_allowed:user.is_authenticated %}
|
||||
{% if poss_dup.count > 0 %}
|
||||
<article>
|
||||
<header>
|
||||
{% if event.possibly_duplicated.fixed %}
|
||||
<h2>Sources multiples</h2>
|
||||
<p class="remarque">L'événement affiché a également été trouvé à partir
|
||||
{% if poss_dup.count == 1 %}
|
||||
d'une autre source
|
||||
{% else %}
|
||||
d'autres sources
|
||||
{% endif %} :</p>
|
||||
{% else %}
|
||||
<h2>Possibles doublons</h2>
|
||||
<p class="remarque">Notre algorithme a détecté que l'événement affiché pourrait être dupliqué sur l'agenda, et consultable dans
|
||||
{% if event.get_possibly_duplicated.count == 1 %}
|
||||
{% if poss_dup.count == 1 %}
|
||||
une autre version
|
||||
{% else %}
|
||||
d'autres versions
|
||||
{% endif %}
|
||||
ci-dessous.</p>
|
||||
{% endif %}
|
||||
</header>
|
||||
<nav>
|
||||
<ul>
|
||||
{% for e in event.get_possibly_duplicated %}
|
||||
<ul class="no-breakline">
|
||||
{% for e in poss_dup %}
|
||||
<li>
|
||||
<a href="{{ e.get_absolute_url }}">{{ e }}</a>
|
||||
{{ event|picto_status }} <a href="{{ e.get_absolute_url }}">{{ e }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@ -109,6 +122,8 @@
|
||||
<a role="button" href="{% url 'fix_duplicate' event.possibly_duplicated.pk %}">Corriger {% picto_from_name "tool" %}</a>
|
||||
</footer>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</article>
|
||||
{% endif %}
|
||||
<article>
|
||||
|
@ -18,6 +18,20 @@
|
||||
{% picto_from_name "map-pin" %}
|
||||
{% include "agenda_culturel/event-location-inc.html" with event=event %}
|
||||
</p>
|
||||
{% if event.possibly_duplicated %}
|
||||
<p class="remarque">
|
||||
{% if event.possibly_duplicated.fixed %}
|
||||
cet événement a été {% if user.is_authenticated %}<a href="{{ event.possibly_duplicated.get_absolute_url }}">importé plusieurs fois</a>{% else %}importé plusieurs fois{% endif %},
|
||||
{% if event.masked %}
|
||||
vous pouvez <a href="{{ event.possibly_duplicated.get_one_event.get_absolute_url }}">consulter l'import principal</a>
|
||||
{% else %}
|
||||
et vous consultez l'import principal
|
||||
{% endif %}
|
||||
{% else %}
|
||||
cet événement a probablement été {% if user.is_authenticated %}<a href="{{ event.possibly_duplicated.get_absolute_url }}">importé plusieurs fois</a>{% else %}importé plusieurs fois{% endif %}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
{% if event.has_image_url %}
|
||||
|
@ -2,7 +2,7 @@ from django import template
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.urls import reverse_lazy
|
||||
from django.template.defaultfilters import pluralize
|
||||
from django.db.models import Count
|
||||
from django.db.models import Count, Q
|
||||
|
||||
|
||||
|
||||
@ -16,13 +16,14 @@ register = template.Library()
|
||||
@register.simple_tag
|
||||
def show_badge_duplicated(placement="top"):
|
||||
|
||||
nb_duplicated = DuplicatedEvents.objects.annotate(nb_duplicated=Count('event')).filter(nb_duplicated__gte=1).count()
|
||||
nb_duplicated = DuplicatedEvents.objects.annotate(nb_duplicated=Count('event',
|
||||
filter=Q(fixed=False), distinct=True)).filter(nb_duplicated__gte=1).count()
|
||||
|
||||
if nb_duplicated != 0:
|
||||
return mark_safe(
|
||||
'<a href="'
|
||||
+ reverse_lazy("duplicates")
|
||||
+ '" class="badge" data-placement="'
|
||||
+ '?fixed=false" class="badge" data-placement="'
|
||||
+ placement
|
||||
+ '" data-tooltip="'
|
||||
+ str(nb_duplicated)
|
||||
|
@ -144,4 +144,12 @@ def robust_urlize(txt):
|
||||
def linebreaks2(txt):
|
||||
res = linebreaks(txt)
|
||||
|
||||
return mark_safe(re.sub("(<br> )+", "<br>", res))
|
||||
return mark_safe(re.sub("(<br> )+", "<br>", res))
|
||||
|
||||
|
||||
@register.filter
|
||||
def only_allowed(elist, is_authenticated):
|
||||
if not is_authenticated:
|
||||
return elist.filter(status=Event.STATUS.PUBLISHED)
|
||||
else:
|
||||
return elist
|
@ -1386,10 +1386,15 @@ def run_all_rimports(request, status=None):
|
||||
## duplicated events
|
||||
#########################
|
||||
|
||||
class DuplicatedEventsFilter(django_filters.FilterSet):
|
||||
class Meta:
|
||||
model = DuplicatedEvents
|
||||
fields = ["fixed"]
|
||||
|
||||
|
||||
class DuplicatedEventsDetailView(LoginRequiredMixin, DetailView):
|
||||
model = DuplicatedEvents
|
||||
template_name = "agenda_culturel/fix_duplicate.html"
|
||||
template_name = "agenda_culturel/duplicate.html"
|
||||
|
||||
|
||||
@login_required(login_url="/accounts/login/")
|
||||
@ -1445,18 +1450,14 @@ def merge_duplicate(request, pk):
|
||||
|
||||
# create a new event that merge the selected events
|
||||
new_event = Event(**new_event_data)
|
||||
new_event.masked = False
|
||||
new_event.status = Event.STATUS.PUBLISHED
|
||||
new_event.possibly_duplicated = edup
|
||||
new_event.set_skip_duplicate_check()
|
||||
new_event.save()
|
||||
|
||||
# move the old ones in trash
|
||||
for e in events:
|
||||
e.status = Event.STATUS.TRASH
|
||||
Event.objects.bulk_update(events, fields=["status"])
|
||||
# remove duplicate
|
||||
edup.delete()
|
||||
edup.fix(new_event)
|
||||
|
||||
messages.info(request, _("The merge has been successfully completed."))
|
||||
messages.info(request, _("Creation of a merged event has been successfully completed."))
|
||||
return HttpResponseRedirect(new_event.get_absolute_url())
|
||||
|
||||
return render(
|
||||
@ -1480,6 +1481,9 @@ def fix_duplicate(request, pk):
|
||||
if form.is_valid():
|
||||
if form.is_action_no_duplicates():
|
||||
events = edup.get_duplicated()
|
||||
for e in events:
|
||||
e.masked = False
|
||||
e.save()
|
||||
if len(events) == 0:
|
||||
date = None
|
||||
else:
|
||||
@ -1501,32 +1505,28 @@ def fix_duplicate(request, pk):
|
||||
|
||||
elif form.is_action_select():
|
||||
selected = form.get_selected_event(edup)
|
||||
not_selected = [e for e in edup.get_duplicated() if e != selected]
|
||||
nb = len(not_selected)
|
||||
for e in not_selected:
|
||||
e.status = Event.STATUS.TRASH
|
||||
Event.objects.bulk_update(not_selected, fields=["status"])
|
||||
url = selected.get_absolute_url()
|
||||
edup.delete()
|
||||
nb = edup.fix(selected) - 1
|
||||
if nb == 1:
|
||||
messages.success(
|
||||
request,
|
||||
_(
|
||||
"The selected event has been retained, while the other has been moved to the recycle bin."
|
||||
"The selected event has been retained, while the other has been masked."
|
||||
),
|
||||
)
|
||||
else:
|
||||
messages.success(
|
||||
request,
|
||||
_(
|
||||
"The selected event has been retained, while the others have been moved to the recycle bin."
|
||||
"The selected event has been retained, while the others havec been masked."
|
||||
),
|
||||
)
|
||||
return HttpResponseRedirect(url)
|
||||
return HttpResponseRedirect(edup.get_absolute_url())
|
||||
elif form.is_action_remove():
|
||||
event = form.get_selected_event(edup)
|
||||
event.possibly_duplicated = None
|
||||
event.masked = False
|
||||
event.save()
|
||||
edup.save()
|
||||
messages.success(
|
||||
request,
|
||||
_(
|
||||
@ -1534,7 +1534,7 @@ def fix_duplicate(request, pk):
|
||||
),
|
||||
)
|
||||
if edup.nb_duplicated() == 1:
|
||||
return HttpResponseRedirect(event.get_absolute_url())
|
||||
return HttpResponseRedirect(edup.get_absolute_url())
|
||||
else:
|
||||
form = FixDuplicates(nb_events=edup.nb_duplicated())
|
||||
else:
|
||||
@ -1559,16 +1559,19 @@ class DuplicatedEventsUpdateView(LoginRequiredMixin, UpdateView):
|
||||
@permission_required("agenda_culturel.view_duplicatedevents")
|
||||
def duplicates(request):
|
||||
nb_removed = DuplicatedEvents.remove_singletons()
|
||||
nb_similar = DuplicatedEvents.remove_similar_entries()
|
||||
nb_similar = DuplicatedEvents.fix_similar_entries()
|
||||
if nb_removed > 0 or nb_similar > 0:
|
||||
messages.success(
|
||||
request,
|
||||
_("Cleaning up duplicates: {} item(s) removed.").format(
|
||||
_("Cleaning up duplicates: {} item(s) fixed.").format(
|
||||
nb_removed + nb_similar
|
||||
),
|
||||
)
|
||||
|
||||
paginator = Paginator(DuplicatedEvents.objects.all(), 10)
|
||||
|
||||
filter = DuplicatedEventsFilter(
|
||||
request.GET, queryset=DuplicatedEvents.objects.all().order_by("-pk")
|
||||
)
|
||||
paginator = PaginatorFilter(filter, 10, request)
|
||||
page = request.GET.get("page")
|
||||
|
||||
try:
|
||||
@ -1581,7 +1584,7 @@ def duplicates(request):
|
||||
return render(
|
||||
request,
|
||||
"agenda_culturel/duplicates.html",
|
||||
{"filter": filter, "paginator_filter": response},
|
||||
{"filter": filter, "paginator_filter": response, "paginator": paginator},
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user