Compare commits

..

No commits in common. "0859b36f9849445fb0de2f9e6243e2a5eb5337bb" and "43ec6aafc496466cdbd991a21be6f33d8322eee1" have entirely different histories.

5 changed files with 32 additions and 146 deletions

View file

@ -64,9 +64,3 @@ article.message {
color: var(--pico-color-red-500);
}
}
.form-error::before {
margin-right: .5em;
font-family: remixicon;
content: "\eca0";
}

View file

@ -1,4 +1,8 @@
{% for error in form.non_field_errors %}<article class="message error">{{ error }}</article>{% endfor %}
{% if form.non_field_errors %}
<ul class="form-errors">
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
</ul>
{% endif %}
<form method="post" {% if action %}action="{% url action %}"{% endif %}>
{% csrf_token %}
<fieldset>
@ -6,10 +10,12 @@
<label>
{{ field.label }}
{{ field }}
{% if field.errors %}
<small id="{{ field.errors.field_id }}_error" class="form-error">{{ field.errors|join:", " }}</small>
{% endif %}
</label>
{% if field.errors %}
<ul class="form-errors">
{% for error in field.errors %}<li>{{ error }}</li>{% endfor %}
</ul>
{% endif %}
{% endfor %}
</fieldset>
<input type="submit" {% if submit %}value="{{ submit }}"{% endif %}>

View file

@ -1,53 +0,0 @@
# Generated by Django 5.2.3 on 2025-06-14 08:13
import django.db.models.functions.text
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("game", "0012_alter_musikgame_playlist"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterUniqueTogether(
name="group",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="musicgameorder",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="musicvideo",
unique_together=set(),
),
migrations.AddConstraint(
model_name="group",
constraint=models.UniqueConstraint(
django.db.models.functions.text.Lower("name"),
models.F("owner"),
name="unique_group_name",
),
),
migrations.AddConstraint(
model_name="musicgameorder",
constraint=models.UniqueConstraint(
fields=("game", "player", "music_video"), name="unique_music_in_game"
),
),
migrations.AddConstraint(
model_name="musicgameorder",
constraint=models.UniqueConstraint(
fields=("game", "order"), name="unique_order"
),
),
migrations.AddConstraint(
model_name="musicvideo",
constraint=models.UniqueConstraint(
fields=("yt_id", "owner", "group"), name="unique_music_in_group"
),
),
]

View file

@ -1,6 +1,5 @@
from django.contrib.auth.models import User
from django.db import models
from django.db.models.functions import Lower
from django.urls import reverse
@ -20,9 +19,7 @@ class Group(models.Model):
return reverse("group_detail", kwargs={"pk": self.pk})
class Meta:
constraints = [
models.UniqueConstraint(Lower("name"), "owner", name="unique_group_name")
]
unique_together = ["name", "owner"]
class MusicVideo(models.Model):
@ -34,11 +31,7 @@ class MusicVideo(models.Model):
blacklisted = models.BooleanField(default=False)
class Meta:
constraints = [
models.UniqueConstraint(
fields=("yt_id", "owner", "group"), name="unique_music_in_group"
)
]
unique_together = ["yt_id", "owner", "group"]
class MusikGame(models.Model):
@ -59,10 +52,5 @@ class MusicGameOrder(models.Model):
order = models.PositiveIntegerField()
class Meta:
constraints = [
models.UniqueConstraint(
fields=("game", "player", "music_video"), name="unique_music_in_game"
),
models.UniqueConstraint(fields=("game", "order"), name="unique_order"),
]
unique_together = [["game", "player", "music_video"], ["game", "order"]]
ordering = ["order"]

View file

@ -4,13 +4,12 @@ import google.oauth2.credentials
import google_auth_oauthlib
import googleapiclient.discovery
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.db import IntegrityError
from django.db.models import Count, Q
from django.shortcuts import redirect
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect
from django.views import View
from django.views.generic.detail import DetailView, SingleObjectMixin
from django.views.generic.edit import CreateView, DeleteView, UpdateView
@ -38,22 +37,13 @@ class GroupMixin:
fields = ["name"]
class GroupIntegrityMixin:
def form_valid(self, form):
try:
return super().form_valid(form)
except IntegrityError:
form.add_error("name", "Ce nom de groupe existe déjà.")
return super().form_invalid(form)
class GroupCreateView(LoginRequiredMixin, GroupMixin, GroupIntegrityMixin, CreateView):
class GroupCreateView(LoginRequiredMixin, GroupMixin, CreateView):
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
class GroupUpdateView(OwnerFilterMixin, GroupMixin, GroupIntegrityMixin, UpdateView):
class GroupUpdateView(OwnerFilterMixin, GroupMixin, UpdateView):
pass
@ -89,26 +79,14 @@ class GroupAddMusicView(MemberFilterMixin, SingleObjectMixin, View):
group = self.get_object()
yt_id = request.POST.get("yt_id")
if not yt_id:
messages.add_message(request, messages.ERROR, "Aucun identifiant donné")
return redirect(group)
return JsonResponse({"error": "You must provide a YouTube ID."}, status=400)
yt_id = utils.parse_musik(yt_id)
title = utils.get_yt_title(yt_id)
if not title:
messages.add_message(
request, messages.ERROR, f"Vidéo Youtube invalide : {yt_id}"
)
return redirect(group)
try:
group.musicvideo_set.create(yt_id=yt_id, title=title, owner=request.user)
except IntegrityError:
messages.add_message(
request, messages.ERROR, f"Vidéo Youtube déjà ajoutée : {yt_id}"
)
messages.add_message(
request, messages.SUCCESS, f"Vidéo Youtube ajoutée : {yt_id}"
)
return JsonResponse({"error": "Invalid YouTube ID."}, status=400)
group.musicvideo_set.create(yt_id=yt_id, title=title, owner=request.user)
group.save()
return redirect(group)
@ -119,15 +97,6 @@ class GroupAddMemberView(OwnerFilterMixin, SingleObjectMixin, View):
group = self.get_object()
username = request.POST.get("username")
user = User.objects.get(username=username)
if user == group.owner:
messages.add_message(
request, messages.WARNING, f"{user} est le propriétaire du groupe."
)
return redirect(group)
if user in group.members.all():
messages.add_message(
request, messages.WARNING, f"{user} est déjà membre du groupe."
)
group.members.add(user)
return redirect(group)
@ -143,25 +112,17 @@ class GroupRemoveMusicView(OwnerFilterMixin, SingleObjectMixin, View):
return redirect(group)
class GroupRemoveMemberView(OwnerFilterMixin, SingleObjectMixin, View):
model = models.Group
class GroupRemoveMemberView(View):
def get(self, request, pk, user_pk):
group = self.get_object()
user = User.objects.get(pk=user_pk)
relation = models.Group.members.through.objects.filter(
group=group, user=user
).first()
if not relation:
messages.add_message(
request,
messages.ERROR,
f"L'utilisateur {user} n'est pas membre du groupe.",
)
else:
relation.delete()
relation = get_object_or_404(
models.Group.members.through,
group_id=pk,
user_id=user_pk,
group__owner=request.user,
)
group = relation.group
relation.delete()
return redirect(group)
@ -176,11 +137,6 @@ class GroupRemoveGameView(SingleObjectMixin, SuccessMessageMixin, View):
game = self.get_object()
group = game.group
game.delete()
messages.add_message(
request,
messages.SUCCESS,
f"Le jeu du {game.date.strftime('%x')} a été supprimé avec succès.",
)
return redirect(group)
@ -294,11 +250,9 @@ class YoutubeLoginView(LoginRequiredMixin, View):
class YoutubeCallbackView(LoginRequiredMixin, View):
def get(self, request):
if err := request.GET.get("error"):
messages.add_message(
request, messages.ERROR, f"Échec de la connexion à Youtube : {err}"
)
if request.GET.get("error"):
return redirect("/")
print(request.GET)
state = self.request.session.get("state")
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
@ -324,8 +278,6 @@ class YoutubeCallbackView(LoginRequiredMixin, View):
}
},
)
messages.add_message(request, messages.SUCCESS, "Connexion à Youtube réussie.")
return redirect("/")
@ -335,5 +287,4 @@ class GroupClearBlacklistView(OwnerFilterMixin, SingleObjectMixin, View):
def get(self, request, pk):
group = self.get_object()
group.musicvideo_set.filter(blacklisted=True).update(blacklisted=False)
messages.add_message(request, messages.SUCCESS, "La blacklist a été vidée.")
return redirect(group)