From 58e8bbbbef00837933d47c1370c2cd14b7c614dc Mon Sep 17 00:00:00 2001 From: Mark Hoekveen Date: Sat, 20 Jul 2024 09:52:50 +0200 Subject: [PATCH] skip queue --- playlist/models/vote.py | 1 + playlist/static/img/download.png | Bin 0 -> 419 bytes playlist/static/style.css | 12 ++++++++++++ playlist/templates/Vote.html | 11 ++++++++--- playlist/urls.py | 1 + playlist/utils.py | 13 ++++++++++--- playlist/views.py | 31 +++++++++++++++++++++++++++---- 7 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 playlist/static/img/download.png diff --git a/playlist/models/vote.py b/playlist/models/vote.py index d05712c..e927613 100644 --- a/playlist/models/vote.py +++ b/playlist/models/vote.py @@ -7,3 +7,4 @@ class Vote(models.Model): track = models.ForeignKey('Track', on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE) points = models.IntegerField() + skipped = models.BooleanField(default=False) diff --git a/playlist/static/img/download.png b/playlist/static/img/download.png new file mode 100644 index 0000000000000000000000000000000000000000..5d96a1b63ddc02bb20175757acd6a97f90b5d982 GIT binary patch literal 419 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF@P5Lb|bhKBzP4F5rZ z;lP0d3=KdrARmGo%rq~66f>3t`2{mLJiCzw;v{*yyD$s#_-x;Tb#TsJ*q$k(92)A~?dy+NRP@k6#Hv$fR~*mgEv^j&`L-l4l^gQGnD zEZ5HsesEr5@l^4ME=~#7iD|s59NNW)H`u#Y^6$Rq-zcAGK6A^}FF`Bob9k1i)&J75 z{L;DP!GZL$Ju!SQi~{{c-+mJ);FYh;6T1=}$dV1TUA4qDq9i4;B-JXpC>2OC7#SE^ z=o*;m8kvL`8Cw~cTA3Q?8kkra7<}EkeJYBE-29Zxv`X9>S|0Fg0yQvry85}Sb4q9e E0P^^O{r~^~ literal 0 HcmV?d00001 diff --git a/playlist/static/style.css b/playlist/static/style.css index 5442288..d494e70 100644 --- a/playlist/static/style.css +++ b/playlist/static/style.css @@ -457,6 +457,7 @@ input[type="range"]#volume::-webkit-slider-thumb { .undo-wrapper p { flex-grow: 1; padding: 0 5px; + text-align: right; } .undo { @@ -465,6 +466,17 @@ input[type="range"]#volume::-webkit-slider-thumb { background-position: 50% 0; padding: 32px 0 4px 0; height: 50px; + min-width: 40px; +} + +.skip { + background-image: url(img/download.png); + background-repeat: no-repeat; + background-position: 50% 20%; + padding: 32px 0 4px 0; + height: 50px; + min-width: 40px; + margin-left: 5px; } .progress-indicator { diff --git a/playlist/templates/Vote.html b/playlist/templates/Vote.html index adb2646..327b6d6 100644 --- a/playlist/templates/Vote.html +++ b/playlist/templates/Vote.html @@ -41,14 +41,19 @@ Stemmen > +
+ {% if not skipped %} + {% csrf_token %} + + {% endif %} +
+
{% if undo %} - -
{% csrf_token %}

Je hebt {{undo.track}} een score van {{undo.points}} sterren gegeven!

-
{% endif %} +
{% else %} diff --git a/playlist/urls.py b/playlist/urls.py index 28c8394..f7d4d77 100644 --- a/playlist/urls.py +++ b/playlist/urls.py @@ -7,6 +7,7 @@ urlpatterns = [ path('track/', views.NominateView.as_view(), name="nominate"), path('vote/', views.VoteView.as_view(), name="vote"), path('vote/undo', views.UndoView.as_view(), name="undo"), + path('vote/skip', views.SkipView.as_view(), name="skip"), path('settings/', views.SettingsView.as_view(), name="settings"), path('overview/', views.OverView.as_view(), name="overview"), path('overview/playlist', views.PlaylistListView.as_view(), name="playlist-list"), diff --git a/playlist/utils.py b/playlist/utils.py index f0ef518..788beba 100644 --- a/playlist/utils.py +++ b/playlist/utils.py @@ -10,11 +10,18 @@ def from_json(cls, json): return cls.objects.create(**subset) def get_unvoted(user): + """Gets next voting track for user. Returns a pair with track and flag if this was a skipped track""" votes = set(Vote.objects.filter(user=user).values_list('track_id', flat=True)) tracks = set(Track.objects.filter(banter_done=True).values_list('pk', flat=True)) seed(user.username) try: - random_track = choice(list(tracks - votes)) - return Track.objects.get(pk=random_track) + queue = list(tracks - votes) + skipped = False + if not queue: + skipped = True + queue = list(Vote.objects.filter(user=user).filter(skipped=True).values_list('track_id', flat=True)) + random_track = choice(queue) + choice + return (Track.objects.get(pk=random_track), skipped) except IndexError: - return None + return (None, False) diff --git a/playlist/views.py b/playlist/views.py index 79f8aca..c6ae980 100644 --- a/playlist/views.py +++ b/playlist/views.py @@ -26,10 +26,10 @@ class AuthView(View): class VoteView(LoginRequiredMixin, View): def get(self, request, undo=None): - track = get_unvoted(request.user) + (track, skipped) = get_unvoted(request.user) if track and not track.album.image: get_and_dither_image(track.album.image_url, track.album, "image") - return TemplateResponse(request, "Vote.html", {"track": track, "undo": undo}) + return TemplateResponse(request, "Vote.html", {"track": track, "undo": undo, "skipped": skipped}) def post(self, request): (profile,_) = Profile.objects.get_or_create(user=request.user) try: @@ -40,11 +40,14 @@ class VoteView(LoginRequiredMixin, View): score = min(max(1, score), 5) track = Track.objects.get(pk=spotify_id) try: - Vote.objects.get(user=request.user, track=track) + prevote = Vote.objects.get(user=request.user, track=track) except Vote.DoesNotExist: pass else: - raise Exception(f"{request.user} already voted for {track}") + if not prevote.skipped: + raise Exception(f"{request.user} already voted for {track}") + else: + prevote.delete() vote = Vote.objects.create(track=track, user=request.user, points=score) (profile,_) = Profile.objects.get_or_create(user=request.user) profile.last_voted = track @@ -186,6 +189,26 @@ class UndoView(LoginRequiredMixin, View): vote.delete() return HttpResponseRedirect('/vote/') +class SkipView(LoginRequiredMixin, View): + def get(self, request): + return HttpResponseRedirect('/vote/') + def post(self, request): + spotify_id = self.request.POST['spotify_id'] + track = Track.objects.get(pk=spotify_id) + (profile,_) = Profile.objects.get_or_create(user=request.user) + if not profile.can_vote: + raise Exception(f"{request.user} tried to vote after closing for {track}") + vote = None + try: + vote = Vote.objects.get(user=request.user, track=track) + except Vote.DoesNotExist: + pass + profile.last_voted = None + profile.save() + vote = Vote.objects.create(track=track, user=request.user, points=0, skipped=True) + profile.save() + return self.get(request) + class OverView(LoginRequiredMixin, View): def get(self, request): votes = Vote.objects.select_related().distinct()