Ajout d'un mécanisme d'import par batches (pour l'instant pas connecté au celery)

This commit is contained in:
Jean-Marie Favreau 2023-12-23 09:43:34 +01:00
parent 6ac3afc0e5
commit e8712bd64c
10 changed files with 352 additions and 83 deletions

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: agenda_culturel\n" "Project-Id-Version: agenda_culturel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-12-16 20:13+0000\n" "POT-Creation-Date: 2023-12-23 08:38+0000\n"
"PO-Revision-Date: 2023-10-29 14:16+0000\n" "PO-Revision-Date: 2023-10-29 14:16+0000\n"
"Last-Translator: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n" "Last-Translator: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
"Language-Team: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n" "Language-Team: Jean-Marie Favreau <jeanmarie.favreau@free.fr>\n"
@ -17,262 +17,290 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: agenda_culturel/forms.py:36 #: agenda_culturel/forms.py:37
msgid "The start date cannot be earler than today."
msgstr "La date de début ne peut pas être avant aujourd'hui."
#: agenda_culturel/forms.py:46
msgid "The end date must be after the start date." msgid "The end date must be after the start date."
msgstr "La date de fin doit être après la date de début." msgstr "La date de fin doit être après la date de début."
#: agenda_culturel/forms.py:48 #: agenda_culturel/forms.py:52
msgid "The end date cannot be earler than today."
msgstr "La date de fin ne peut pas être avant aujourd'hui."
#: agenda_culturel/forms.py:63
msgid "The end time cannot be earlier than the start time." 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." msgstr "L'heure de fin ne peut pas être avant l'heure de début."
#: agenda_culturel/models.py:19 agenda_culturel/models.py:48 #: agenda_culturel/models.py:23 agenda_culturel/models.py:52
#: agenda_culturel/models.py:183 #: agenda_culturel/models.py:211
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
#: agenda_culturel/models.py:19 agenda_culturel/models.py:48 #: agenda_culturel/models.py:23 agenda_culturel/models.py:52
msgid "Category name" msgid "Category name"
msgstr "Nom de la catégorie" msgstr "Nom de la catégorie"
#: agenda_culturel/models.py:20 #: agenda_culturel/models.py:24
msgid "Content" msgid "Content"
msgstr "Contenu" msgstr "Contenu"
#: agenda_culturel/models.py:20 #: agenda_culturel/models.py:24
msgid "Text as shown to the visitors" msgid "Text as shown to the visitors"
msgstr "Text tel que présenté aux visiteureuses" msgstr "Text tel que présenté aux visiteureuses"
#: agenda_culturel/models.py:21 #: agenda_culturel/models.py:25
msgid "URL path" msgid "URL path"
msgstr "" msgstr ""
#: agenda_culturel/models.py:21 #: agenda_culturel/models.py:25
msgid "URL path where the content is included." msgid "URL path where the content is included."
msgstr "" msgstr ""
#: agenda_culturel/models.py:49 #: agenda_culturel/models.py:53
msgid "Alternative Name" msgid "Alternative Name"
msgstr "Nom alternatif" msgstr "Nom alternatif"
#: agenda_culturel/models.py:49 #: agenda_culturel/models.py:53
msgid "Alternative name used with a time period" msgid "Alternative name used with a time period"
msgstr "Nom alternatif utilisé avec une période de temps" msgstr "Nom alternatif utilisé avec une période de temps"
#: agenda_culturel/models.py:50 #: agenda_culturel/models.py:54
msgid "Short name" msgid "Short name"
msgstr "Nom court" msgstr "Nom court"
#: agenda_culturel/models.py:50 #: agenda_culturel/models.py:54
msgid "Short name of the category" msgid "Short name of the category"
msgstr "Nom court de la catégorie" msgstr "Nom court de la catégorie"
#: agenda_culturel/models.py:51 #: agenda_culturel/models.py:55
msgid "Color" msgid "Color"
msgstr "Couleur" msgstr "Couleur"
#: agenda_culturel/models.py:51 #: agenda_culturel/models.py:55
msgid "Color used as background for the category" msgid "Color used as background for the category"
msgstr "Couleur utilisée comme fond de la catégorie" msgstr "Couleur utilisée comme fond de la catégorie"
#: agenda_culturel/models.py:88 agenda_culturel/models.py:105 #: agenda_culturel/models.py:92 agenda_culturel/models.py:109
msgid "Category" msgid "Category"
msgstr "Catégorie" msgstr "Catégorie"
#: agenda_culturel/models.py:89 #: agenda_culturel/models.py:93
msgid "Categories" msgid "Categories"
msgstr "Catégories" msgstr "Catégories"
#: agenda_culturel/models.py:94 #: agenda_culturel/models.py:98
msgid "Published" msgid "Published"
msgstr "Publié" msgstr "Publié"
#: agenda_culturel/models.py:95 #: agenda_culturel/models.py:99
msgid "Draft" msgid "Draft"
msgstr "Brouillon" msgstr "Brouillon"
#: agenda_culturel/models.py:96 #: agenda_culturel/models.py:100
msgid "Trash" msgid "Trash"
msgstr "Corbeille" msgstr "Corbeille"
#: agenda_culturel/models.py:101 #: agenda_culturel/models.py:105
msgid "Title" msgid "Title"
msgstr "Titre" msgstr "Titre"
#: agenda_culturel/models.py:101 #: agenda_culturel/models.py:105
msgid "Short title" msgid "Short title"
msgstr "Titre court" msgstr "Titre court"
#: agenda_culturel/models.py:103 #: agenda_culturel/models.py:107 agenda_culturel/models.py:238
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Status"
#: agenda_culturel/models.py:105 #: agenda_culturel/models.py:109
msgid "Category of the event" msgid "Category of the event"
msgstr "Catégorie de l'événement" msgstr "Catégorie de l'événement"
#: agenda_culturel/models.py:107 #: agenda_culturel/models.py:111
msgid "Day of the event" msgid "Day of the event"
msgstr "Date de l'événement" msgstr "Date de l'événement"
#: agenda_culturel/models.py:108 #: agenda_culturel/models.py:112
msgid "Starting time" msgid "Starting time"
msgstr "Heure de début" msgstr "Heure de début"
#: agenda_culturel/models.py:110 #: agenda_culturel/models.py:114
msgid "End day of the event" msgid "End day of the event"
msgstr "Fin de l'événement" msgstr "Fin de l'événement"
#: agenda_culturel/models.py:110 #: agenda_culturel/models.py:114
msgid "End day of the event, only required if different from the start day." msgid "End day of the event, only required if different from the start day."
msgstr "" msgstr ""
"Date de fin de l'événement, uniquement nécessaire s'il est différent du " "Date de fin de l'événement, uniquement nécessaire s'il est différent du "
"premier jour de l'événement" "premier jour de l'événement"
#: agenda_culturel/models.py:111 #: agenda_culturel/models.py:115
msgid "Final time" msgid "Final time"
msgstr "Heure de fin" msgstr "Heure de fin"
#: agenda_culturel/models.py:113 #: agenda_culturel/models.py:117
msgid "Location" msgid "Location"
msgstr "Localisation" msgstr "Localisation"
#: agenda_culturel/models.py:113 #: agenda_culturel/models.py:117
msgid "Address of the event" msgid "Address of the event"
msgstr "Adresse de l'événement" msgstr "Adresse de l'événement"
#: agenda_culturel/models.py:115 #: agenda_culturel/models.py:119
msgid "Description" msgid "Description"
msgstr "Description" msgstr "Description"
#: agenda_culturel/models.py:115 #: agenda_culturel/models.py:119
msgid "General description of the event" msgid "General description of the event"
msgstr "Description générale de l'événement" msgstr "Description générale de l'événement"
#: agenda_culturel/models.py:117 #: agenda_culturel/models.py:121
msgid "Illustration (local image)" msgid "Illustration (local image)"
msgstr "Illustration (image locale)" msgstr "Illustration (image locale)"
#: agenda_culturel/models.py:117 #: agenda_culturel/models.py:121
msgid "Illustration image stored in the agenda server" msgid "Illustration image stored in the agenda server"
msgstr "Image d'illustration stockée sur le serveur de l'agenda" msgstr "Image d'illustration stockée sur le serveur de l'agenda"
#: agenda_culturel/models.py:119 #: agenda_culturel/models.py:123
msgid "Illustration" msgid "Illustration"
msgstr "Illustration" msgstr "Illustration"
#: agenda_culturel/models.py:119 #: agenda_culturel/models.py:123
msgid "URL of the illustration image" msgid "URL of the illustration image"
msgstr "URL de l'image illustrative" msgstr "URL de l'image illustrative"
#: agenda_culturel/models.py:120 #: agenda_culturel/models.py:124
msgid "Illustration description" msgid "Illustration description"
msgstr "Description de l'illustration" msgstr "Description de l'illustration"
#: agenda_culturel/models.py:120 #: agenda_culturel/models.py:124
msgid "Alternative text used by screen readers for the image" msgid "Alternative text used by screen readers for the image"
msgstr "Texte alternatif utiliser par les lecteurs d'écrans pour l'image" msgstr "Texte alternatif utiliser par les lecteurs d'écrans pour l'image"
#: agenda_culturel/models.py:122 #: agenda_culturel/models.py:126
msgid "URLs" msgid "URLs"
msgstr "URLs" msgstr "URLs"
#: agenda_culturel/models.py:122 #: agenda_culturel/models.py:126
msgid "List of all the urls where this event can be found." 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é." msgstr "Liste de toutes les urls où l'événement peut être trouvé."
#: agenda_culturel/models.py:124 #: agenda_culturel/models.py:128
msgid "Tags" msgid "Tags"
msgstr "Étiquettes" msgstr "Étiquettes"
#: agenda_culturel/models.py:124 #: agenda_culturel/models.py:128
msgid "A list of tags that describe the event." msgid "A list of tags that describe the event."
msgstr "Une liste d'étiquettes décrivant l'événement" msgstr "Une liste d'étiquettes décrivant l'événement"
#: agenda_culturel/models.py:149 #: agenda_culturel/models.py:158
msgid "Event" msgid "Event"
msgstr "Événement" msgstr "Événement"
#: agenda_culturel/models.py:150 #: agenda_culturel/models.py:159
msgid "Events" msgid "Events"
msgstr "Événements" msgstr "Événements"
#: agenda_culturel/models.py:182 #: agenda_culturel/models.py:210
msgid "Subject" msgid "Subject"
msgstr "Sujet" msgstr "Sujet"
#: agenda_culturel/models.py:182 #: agenda_culturel/models.py:210
msgid "The subject of your message" msgid "The subject of your message"
msgstr "Sujet de votre message" msgstr "Sujet de votre message"
#: agenda_culturel/models.py:183 #: agenda_culturel/models.py:211
msgid "Your name" msgid "Your name"
msgstr "Votre nom" msgstr "Votre nom"
#: agenda_culturel/models.py:184 #: agenda_culturel/models.py:212
msgid "Email address" msgid "Email address"
msgstr "Adresse email" msgstr "Adresse email"
#: agenda_culturel/models.py:184 #: agenda_culturel/models.py:212
msgid "Your email address" msgid "Your email address"
msgstr "Votre adresse email" msgstr "Votre adresse email"
#: agenda_culturel/models.py:185 #: agenda_culturel/models.py:213
msgid "Message" msgid "Message"
msgstr "Message" msgstr "Message"
#: agenda_culturel/models.py:185 #: agenda_culturel/models.py:213
msgid "Your message" msgid "Your message"
msgstr "Votre message" msgstr "Votre message"
#: agenda_culturel/models.py:189 agenda_culturel/views.py:334 #: agenda_culturel/models.py:217 agenda_culturel/views.py:341
msgid "Closed" msgid "Closed"
msgstr "Fermé" msgstr "Fermé"
#: agenda_culturel/models.py:189 #: agenda_culturel/models.py:217
msgid "this message has been processed and no longer needs to be handled" 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" msgstr "Ce message a été traité et ne nécessite plus d'être pris en charge"
#: agenda_culturel/models.py:190 #: agenda_culturel/models.py:218
msgid "Comments" msgid "Comments"
msgstr "Commentaires" msgstr "Commentaires"
#: agenda_culturel/models.py:190 #: agenda_culturel/models.py:218
msgid "Comments on the message from the moderation team" msgid "Comments on the message from the moderation team"
msgstr "Commentaires sur ce message par l'équipe de modération" msgstr "Commentaires sur ce message par l'équipe de modération"
#: agenda_culturel/settings/base.py:128 #: agenda_culturel/models.py:227
msgid "Running"
msgstr ""
#: agenda_culturel/models.py:228
msgid "Canceled"
msgstr "Annulé"
#: agenda_culturel/models.py:229
msgid "Success"
msgstr "Succès"
#: agenda_culturel/models.py:230
msgid "Failed"
msgstr "Erreur"
#: agenda_culturel/models.py:235
msgid "Source"
msgstr "Source"
#: agenda_culturel/models.py:235
msgid "URL of the source document"
msgstr "URL du document source"
#: agenda_culturel/models.py:236
msgid "Browsable url"
msgstr "URL navigable"
#: agenda_culturel/models.py:236
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/settings/base.py:134
msgid "English" msgid "English"
msgstr "anglais" msgstr "anglais"
#: agenda_culturel/settings/base.py:129 #: agenda_culturel/settings/base.py:135
msgid "French" msgid "French"
msgstr "français" msgstr "français"
#: agenda_culturel/views.py:182 #: agenda_culturel/views.py:188
msgid "The static content has been successfully updated." msgid "The static content has been successfully updated."
msgstr "Le contenu statique a été modifié avec succès." msgstr "Le contenu statique a été modifié avec succès."
#: agenda_culturel/views.py:188 #: agenda_culturel/views.py:194
msgid "The event has been successfully modified." msgid "The event has been successfully modified."
msgstr "L'événement a été modifié avec succès." msgstr "L'événement a été modifié avec succès."
#: agenda_culturel/views.py:199 #: agenda_culturel/views.py:205
msgid "The event has been successfully deleted." msgid "The event has been successfully deleted."
msgstr "L'événement a été supprimé avec succès" msgstr "L'événement a été supprimé avec succès"
#: agenda_culturel/views.py:237 #: agenda_culturel/views.py:222
msgid "The status has been successfully modified."
msgstr "Le status a été modifié avec succès."
#: agenda_culturel/views.py:244
msgid "The event is saved." msgid "The event is saved."
msgstr "L'événement est enregistré." msgstr "L'événement est enregistré."
#: agenda_culturel/views.py:240 #: agenda_culturel/views.py:247
msgid "" msgid ""
"The event has been submitted and will be published as soon as it has been " "The event has been submitted and will be published as soon as it has been "
"validated by the moderation team." "validated by the moderation team."
@ -280,7 +308,7 @@ msgstr ""
"L'événement a été soumis et sera publié dès qu'il aura été validé par " "L'événement a été soumis et sera publié dès qu'il aura été validé par "
"l'équipe de modération." "l'équipe de modération."
#: agenda_culturel/views.py:270 #: agenda_culturel/views.py:277
msgid "" msgid ""
"The event has been successfully extracted, and you can now submit it after " "The event has been successfully extracted, and you can now submit it after "
"modifying it if necessary." "modifying it if necessary."
@ -288,7 +316,7 @@ msgstr ""
"L'événement a été extrait avec succès, vous pouvez maintenant le soumettre " "L'événement a été extrait avec succès, vous pouvez maintenant le soumettre "
"après l'avoir modifié au besoin." "après l'avoir modifié au besoin."
#: agenda_culturel/views.py:274 #: agenda_culturel/views.py:281
msgid "" msgid ""
"Unable to extract an event from the proposed URL. Please use the form below " "Unable to extract an event from the proposed URL. Please use the form below "
"to submit the event." "to submit the event."
@ -296,12 +324,12 @@ msgstr ""
"Impossible d'extraire un événement depuis l'URL proposée. Veuillez utiliser " "Impossible d'extraire un événement depuis l'URL proposée. Veuillez utiliser "
"le formulaire ci-dessous pour soumettre l'événement." "le formulaire ci-dessous pour soumettre l'événement."
#: agenda_culturel/views.py:283 #: agenda_culturel/views.py:290
msgid "This URL has already been submitted, and you can find the event below." msgid "This URL has already been submitted, and you can find the event below."
msgstr "" msgstr ""
"Cette URL a déjà été soumise, et vous trouverez l'événement ci-dessous." "Cette URL a déjà été soumise, et vous trouverez l'événement ci-dessous."
#: agenda_culturel/views.py:287 #: agenda_culturel/views.py:294
msgid "" msgid ""
"This URL has already been submitted, but has not been selected for " "This URL has already been submitted, but has not been selected for "
"publication by the moderation team." "publication by the moderation team."
@ -309,26 +337,34 @@ msgstr ""
"Cette URL a déjà été soumise, mais n'a pas été retenue par l'équipe de " "Cette URL a déjà été soumise, mais n'a pas été retenue par l'équipe de "
"modération pour la publication." "modération pour la publication."
#: agenda_culturel/views.py:289 #: agenda_culturel/views.py:296
msgid "This URL has already been submitted and is awaiting moderation." msgid "This URL has already been submitted and is awaiting moderation."
msgstr "Cette URL a déjà été soumise, et est en attente de modération" msgstr "Cette URL a déjà été soumise, et est en attente de modération"
#: agenda_culturel/views.py:311 #: agenda_culturel/views.py:318
msgid "Your message has been sent successfully." msgid "Your message has been sent successfully."
msgstr "L'événement a été supprimé avec succès" msgstr "L'événement a été supprimé avec succès"
#: agenda_culturel/views.py:319 #: agenda_culturel/views.py:326
msgid "The contact message properties has been successfully modified." msgid "The contact message properties has been successfully modified."
msgstr "Les propriétés du message de contact ont été modifié avec succès." msgstr "Les propriétés du message de contact ont été modifié avec succès."
#: agenda_culturel/views.py:334 #: agenda_culturel/views.py:341
msgid "Open" msgid "Open"
msgstr "Ouvert" msgstr "Ouvert"
#: agenda_culturel/views.py:374 #: agenda_culturel/views.py:381
msgid "Search" msgid "Search"
msgstr "Rechercher" msgstr "Rechercher"
#: agenda_culturel/views.py:491
msgid "The import has been run successfully."
msgstr "L'import a été lancé avec succès"
#: agenda_culturel/views.py:507
msgid "The import has been canceled."
msgstr "L'import a été annulé"
msgid "Add another" msgid "Add another"
msgstr "Ajouter un autre" msgstr "Ajouter un autre"
@ -336,4 +372,4 @@ msgid "Browse..."
msgstr "Naviguer..." msgstr "Naviguer..."
msgid "No file selected." msgid "No file selected."
msgstr "Pas de fichier sélectionné." msgstr "Pas de fichier sélectionné."

View File

@ -0,0 +1,24 @@
# Generated by Django 4.2.7 on 2023-12-23 08:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('agenda_culturel', '0010_alter_contactmessage_comments'),
]
operations = [
migrations.CreateModel(
name='BatchImportation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_date', models.DateTimeField(auto_now_add=True)),
('source', models.URLField(blank=True, help_text='URL of the source document', max_length=1024, null=True, verbose_name='Source')),
('browsable_url', models.URLField(blank=True, help_text='URL of the corresponding document that will be shown to visitors.', max_length=1024, null=True, verbose_name='Browsable url')),
('running', models.BooleanField(default=True, help_text='This batch importation is still running', verbose_name='Running')),
('success', models.BooleanField(default=False, help_text='This batch importation successfully finished', verbose_name='Success')),
],
),
]

View File

@ -0,0 +1,26 @@
# Generated by Django 4.2.7 on 2023-12-23 08:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('agenda_culturel', '0011_batchimportation'),
]
operations = [
migrations.RemoveField(
model_name='batchimportation',
name='running',
),
migrations.RemoveField(
model_name='batchimportation',
name='success',
),
migrations.AddField(
model_name='batchimportation',
name='status',
field=models.CharField(choices=[('running', 'Running'), ('canceled', 'Canceled'), ('success', 'Success'), ('failed', 'Failed')], default='running', max_length=20, verbose_name='Status'),
),
]

View File

@ -219,3 +219,20 @@ class ContactMessage(models.Model):
def nb_open_contactmessages(): def nb_open_contactmessages():
return ContactMessage.objects.filter(closed=False).count() return ContactMessage.objects.filter(closed=False).count()
class BatchImportation(models.Model):
class STATUS(models.TextChoices):
RUNNING = "running", _("Running")
CANCELED = "canceled", _("Canceled")
SUCCESS = "success", _("Success")
FAILED = "failed", _("Failed")
created_date = models.DateTimeField(auto_now_add=True)
source = models.URLField(verbose_name=_('Source'), help_text=_("URL of the source document"), max_length=1024, blank=True, null=True)
browsable_url = models.URLField(verbose_name=_('Browsable url'), help_text=_("URL of the corresponding document that will be shown to visitors."), max_length=1024, blank=True, null=True)
status = models.CharField(_("Status"), max_length=20, choices=STATUS.choices, default=STATUS.RUNNING)

View File

@ -0,0 +1,24 @@
{% extends "agenda_culturel/page.html" %}
{% load static %}
{% block title %}Importation par lot{% endblock %}
{% block content %}
<h1>Importation par lot</h1>
<article>
<form method="post">{% csrf_token %}
{{ form.as_p }}
<p>
<label for="id_json">JSON (facultatif) :</label>
<textarea id="id_json" name="json" rows="10"></textarea>
<span class="helptext">JSON au format attendu pour l'import. Si le JSON est fourni ici, on ne lancera pas une récupération depuis l'URL donnée en paramètre.</span>
</p>
<input type="submit" value="Envoyer">
</form>
</article>
{% endblock %}

View File

@ -0,0 +1,25 @@
{% extends "agenda_culturel/page.html" %}
{% block title %}Supprimer {{ object.title }}{% endblock %}
{% block content %}
<article>
<header>
<h1>Annulation de l'import {{ object.id }} ({{ object.created_date }})</h1>
</header>
<form method="post">{% csrf_token %}
<p>Êtes-vous sûr·e de vouloir annuler l'importation «&nbsp;{{ object.id }}&nbsp;»&nbsp;?</p>
{{ form }}
<footer>
<div class="grid">
<a href="{{ cancel_url }}" role="button" class="secondary">Annuler</a>
<input type="submit" value="Confirmer">
</div>
</footer>
</form>
</article>
{% endblock %}

View File

@ -0,0 +1,61 @@
{% extends "agenda_culturel/page.html" %}
{% block title %}Importations par lot{% endblock %}
{% load utils_extra %}
{% load cat_extra %}
{% block entete_header %}
{% css_categories %}
{% endblock %}
{% block content %}
<div class="grid two-columns">
<article>
<header>
<a class="slide-buttons" href="{% url 'add_import'%}" role="button">Nouvel import</a>
<h1>Importations par lot</h1>
</header>
<table role="grid">
<thead>
<tr>
<th>Identifiant</th>
<th>Date</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for obj in paginator_filter %}
<tr>
<td>{{ obj.id }}</a></td>
<td>{{ obj.created_date }}</td>
<td>{{ obj.status }}</td>
<td>{% if obj.status == "running" %}<a href="{% url 'cancel_import' obj.id %}">Annuler</a>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
<footer>
<span>
{% if paginator_filter.has_previous %}
<a href="?page=1" role="button">&laquo; premier</a>
<a href="?page={{ paginator_filter.previous_page_number }}" role="button">précédent</a>
{% endif %}
<span>
Page {{ paginator_filter.number }} sur {{ paginator_filter.paginator.num_pages }}
</span>
{% if paginator_filter.has_next %}
<a href="?page={{ paginator_filter.next_page_number }}" role="button">suivant</a>
<a href="?page={{ paginator_filter.paginator.num_pages }}" role="button">dernier &raquo;</a>
{% endif %}
</span>
</footer>
</article>
{% include "agenda_culturel/side-nav.html" with current="imports" %}
</div>
{% endblock %}

View File

@ -10,6 +10,7 @@
<li><a {% if current == "moderation" %}class="selected" {% endif %}href="{% url 'moderation' %}">Derniers événements soumis</a>{% show_badges_events %}</li> <li><a {% if current == "moderation" %}class="selected" {% endif %}href="{% url 'moderation' %}">Derniers événements soumis</a>{% show_badges_events %}</li>
<li><a {% if current == "tags" %}class="selected" {% endif %}href="{% url 'view_all_tags' %}">Toutes les étiquettes</a></li> <li><a {% if current == "tags" %}class="selected" {% endif %}href="{% url 'view_all_tags' %}">Toutes les étiquettes</a></li>
<li><a {% if current == "contactmessages" %}class="selected" {% endif %}href="{% url 'contactmessages' %}">Messages de contact</a>{% show_badge_contactmessages %}</li> <li><a {% if current == "contactmessages" %}class="selected" {% endif %}href="{% url 'contactmessages' %}">Messages de contact</a>{% show_badge_contactmessages %}</li>
<li><a {% if current == "imports" %}class="selected" {% endif %}href="{% url 'imports' %}">Importations par lot</a>{% show_badge_contactmessages %}</li>
</ul> </ul>
</nav> </nav>
</article> </article>

View File

@ -34,6 +34,9 @@ urlpatterns = [
path('contact', ContactMessageCreateView.as_view(), name='contact'), path('contact', ContactMessageCreateView.as_view(), name='contact'),
path('contactmessages', contactmessages, name='contactmessages'), path('contactmessages', contactmessages, name='contactmessages'),
path('contactmessage/<int:pk>', ContactMessageUpdateView.as_view(), name='contactmessage'), path('contactmessage/<int:pk>', ContactMessageUpdateView.as_view(), name='contactmessage'),
path("imports/", imports, name="imports"),
path("imports/add", BatchImportationCreateView.as_view(), name="add_import"),
path("imports/<int:pk>/cancel", cancel_import, name="cancel_import"),
] ]
if settings.DEBUG: if settings.DEBUG:

View File

@ -13,7 +13,7 @@ import urllib
from .forms import EventSubmissionForm, EventForm from .forms import EventSubmissionForm, EventForm
from .models import Event, Category, StaticContent, ContactMessage from .models import Event, Category, StaticContent, ContactMessage, BatchImportation
from django.utils import timezone from django.utils import timezone
from enum import StrEnum from enum import StrEnum
from datetime import date, timedelta from datetime import date, timedelta
@ -219,6 +219,7 @@ def change_status_event(request, pk, status):
if request.method == 'POST': if request.method == 'POST':
event.status = Event.STATUS(status) event.status = Event.STATUS(status)
event.save(update_fields=["status"]) event.save(update_fields=["status"])
messages.success(request, _("The status has been successfully modified."))
if request.user.is_authenticated: if request.user.is_authenticated:
return HttpResponseRedirect(event.get_absolute_url()) return HttpResponseRedirect(event.get_absolute_url())
@ -460,3 +461,54 @@ def event_search(request, full=False):
def event_search_full(request): def event_search_full(request):
return event_search(request, True) return event_search(request, True)
#########################
## batch importations
#########################
@login_required(login_url="/accounts/login/")
def imports(request):
paginator = Paginator(BatchImportation.objects.all().order_by("-created_date"), 10)
page = request.GET.get('page')
try:
response = paginator.page(page)
except PageNotAnInteger:
response = paginator.page(1)
except EmptyPage:
response = paginator.page(paginator.num_pages)
return render(request, 'agenda_culturel/imports.html', {'paginator_filter': response} )
class BatchImportationCreateView(SuccessMessageMixin, LoginRequiredMixin, CreateView):
model = BatchImportation
fields = ['source', 'browsable_url']
success_url = reverse_lazy('imports')
success_message = _('The import has been run successfully.')
def form_valid(self, form):
# TODO run a celery script
return super().form_valid(form)
@login_required(login_url="/accounts/login/")
def cancel_import(request, pk):
import_process = get_object_or_404(BatchImportation, pk=pk)
if request.method == 'POST':
# TODO cancel the celery import
import_process.status = BatchImportation.STATUS.CANCELED
import_process.save(update_fields=["status"])
messages.success(request, _("The import has been canceled."))
return HttpResponseRedirect(reverse_lazy("imports"))
else:
cancel_url = reverse_lazy("imports")
return render(request, 'agenda_culturel/cancel_import_confirm.html', {"object": import_process, "cancel_url": cancel_url})