diff --git a/beesgospel/forms.py b/beesgospel/forms.py
index a0c5d67..c6be86c 100644
--- a/beesgospel/forms.py
+++ b/beesgospel/forms.py
@@ -4,7 +4,7 @@ from django import forms
from django.contrib.auth import forms as auth_forms
from django.db import transaction
-from .models import Chant, Membre, User
+from .models import Chant, ChantDoc, Membre, User
class BootstrapMixin:
@@ -59,3 +59,20 @@ class ChantEditForm(BootstrapMixin, forms.ModelForm):
class Meta:
model = Chant
fields = ["numero", "titre", "particularite"]
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.formset = None
+ if self.instance.pk:
+ DocFormSet = forms.inlineformset_factory(Chant, ChantDoc, fields=["fichier", "titre"], extra=1)
+ self.formset = DocFormSet(data=kwargs.get("data"), files=kwargs.get("files"), instance=self.instance)
+
+ def is_valid(self):
+ return all([super().is_valid()] + [self.formset.is_valid()] if self.formset else [])
+
+ @transaction.atomic()
+ def save(self, **kwargs):
+ obj = super().save(**kwargs)
+ if self.formset:
+ self.formset.save()
+ return obj
diff --git a/beesgospel/migrations/0007_chantdoc.py b/beesgospel/migrations/0007_chantdoc.py
new file mode 100644
index 0000000..8336b84
--- /dev/null
+++ b/beesgospel/migrations/0007_chantdoc.py
@@ -0,0 +1,21 @@
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('beesgospel', '0006_chant'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ChantDoc',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('fichier', models.FileField(blank=True, upload_to='chants', verbose_name='Fichier')),
+ ('titre', models.CharField(max_length=200, verbose_name='Titre')),
+ ('chant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='beesgospel.chant')),
+ ],
+ ),
+ ]
diff --git a/beesgospel/models.py b/beesgospel/models.py
index 3457239..e9cafe2 100644
--- a/beesgospel/models.py
+++ b/beesgospel/models.py
@@ -118,3 +118,12 @@ class Chant(models.Model):
def __str__(self):
return f"{self.numero}. {self.titre}"
+
+
+class ChantDoc(models.Model):
+ chant = models.ForeignKey(Chant, on_delete=models.CASCADE)
+ fichier = models.FileField("Fichier", upload_to="chants", blank=True)
+ titre = models.CharField("Titre", max_length=200)
+
+ def __str__(self):
+ return f"Document {self.titre} pour le chant {self.chant}"
diff --git a/beesgospel/static/ficons/README b/beesgospel/static/ficons/README
new file mode 100644
index 0000000..e9cca77
--- /dev/null
+++ b/beesgospel/static/ficons/README
@@ -0,0 +1,2 @@
+Many thanks to Daniel M. Hendricks, http://daniel.hn
+https://github.com/dmhendricks/file-icon-vectors/
diff --git a/beesgospel/static/ficons/docx.svg b/beesgospel/static/ficons/docx.svg
new file mode 100644
index 0000000..ac084a0
--- /dev/null
+++ b/beesgospel/static/ficons/docx.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/beesgospel/static/ficons/image.svg b/beesgospel/static/ficons/image.svg
new file mode 100644
index 0000000..8d4cac8
--- /dev/null
+++ b/beesgospel/static/ficons/image.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/beesgospel/static/ficons/master.svg b/beesgospel/static/ficons/master.svg
new file mode 100644
index 0000000..2537cbe
--- /dev/null
+++ b/beesgospel/static/ficons/master.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/beesgospel/static/ficons/mp3.svg b/beesgospel/static/ficons/mp3.svg
new file mode 100644
index 0000000..7d5a0a8
--- /dev/null
+++ b/beesgospel/static/ficons/mp3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/beesgospel/static/ficons/odt.svg b/beesgospel/static/ficons/odt.svg
new file mode 100644
index 0000000..f30088b
--- /dev/null
+++ b/beesgospel/static/ficons/odt.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/beesgospel/static/ficons/pdf.svg b/beesgospel/static/ficons/pdf.svg
new file mode 100644
index 0000000..e6472df
--- /dev/null
+++ b/beesgospel/static/ficons/pdf.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/beesgospel/static/ficons/tsv.svg b/beesgospel/static/ficons/tsv.svg
new file mode 100644
index 0000000..318ba05
--- /dev/null
+++ b/beesgospel/static/ficons/tsv.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/beesgospel/static/js/main.js b/beesgospel/static/js/main.js
index cbd6606..3ec05b6 100644
--- a/beesgospel/static/js/main.js
+++ b/beesgospel/static/js/main.js
@@ -11,4 +11,7 @@ window.addEventListener('DOMContentLoaded', () => {
let resp = confirm("Voulez-vous vraiment supprimer cette ligne ?");
if (!resp) { ev.preventDefault(); ev.stopImmediatePropagation(); }
});
+
+ const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
+ const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
})
diff --git a/beesgospel/templatetags/bees_utils.py b/beesgospel/templatetags/bees_utils.py
new file mode 100644
index 0000000..6c58526
--- /dev/null
+++ b/beesgospel/templatetags/bees_utils.py
@@ -0,0 +1,27 @@
+from pathlib import Path
+
+from django.template import Library
+from django.templatetags.static import static
+
+IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".tif", ".tiff", ".gif"]
+
+register = Library()
+
+
+@register.filter
+def icon_url(file_name):
+ ext = Path(file_name).suffix.lower()
+ icon = "master" # default
+ if ext in IMAGE_EXTS:
+ icon = "image"
+ elif ext == ".pdf":
+ icon = "pdf"
+ elif ext in [".mp3", ".wav"]:
+ icon = "mp3"
+ elif ext in (".xls", ".xlsx", ".ods", ".csv"):
+ icon = "tsv"
+ elif ext == ".odt":
+ icon = "odt"
+ elif ext in (".doc", ".docx"):
+ icon = "docx"
+ return static(f"ficons/{icon}.svg")
diff --git a/beesgospel/views.py b/beesgospel/views.py
index 53b26a2..fc7619f 100644
--- a/beesgospel/views.py
+++ b/beesgospel/views.py
@@ -115,7 +115,7 @@ class ListeChantsView(LoginRequiredMixin, ListView):
template_name = "membres/liste_chants.html"
def get_queryset(self):
- return super().get_queryset().order_by("numero")
+ return super().get_queryset().prefetch_related("chantdoc_set").order_by("numero")
class ChantAddView(PermissionRequiredMixin, CreateView):
diff --git a/templates/membres/chant_edit.html b/templates/membres/chant_edit.html
index bb439d2..3420565 100644
--- a/templates/membres/chant_edit.html
+++ b/templates/membres/chant_edit.html
@@ -3,8 +3,19 @@
{% block content %}
Édition/ajout de chant
-
{% endblock content %}
diff --git a/templates/membres/liste_chants.html b/templates/membres/liste_chants.html
index 0d2c1ef..561fa3e 100644
--- a/templates/membres/liste_chants.html
+++ b/templates/membres/liste_chants.html
@@ -1,23 +1,31 @@
{% extends "base.html" %}
+{% load bees_utils %}
{% block content %}
Liste des chants
-
- | N° | Titre | | |
+
+ | N° | Titre | | |
+ {% if perms.beesgospel.change_chant %} | {% endif %}
{% for chant in object_list %}
| {{ chant.numero }} |
{{ chant.titre }} |
+ {% for doc in chant.chantdoc_set.all %}
+
+
+ {% endfor %}
+ |
{{ chant.particularite }} |
- {% if perms.beesgospel.change_chant %}
+ {% if perms.beesgospel.change_chant %}
+ |
- {% endif %}
|
+ {% endif %}
{% endfor %}