vote undo

todo: only accept undo endpoint when allowed
This commit is contained in:
2024-02-22 23:19:12 +01:00
parent 1fb29e637d
commit d73910ab02
6 changed files with 62 additions and 49 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

+32 -8
View File
@@ -12,7 +12,7 @@ body {
min-height: 520px; min-height: 520px;
width:560px; width:560px;
overflow-y:scroll; overflow-y:scroll;
overflow-x:visible; overflow-x:hidden;
display: flex; display: flex;
flex-flow: column nowrap; flex-flow: column nowrap;
justify-content: space-between; justify-content: space-between;
@@ -22,6 +22,8 @@ body {
#main-window { #main-window {
margin: 0; margin: 0;
transform: none !important; transform: none !important;
left: 0;
width: calc(100% - 6px);
} }
} }
@@ -71,7 +73,6 @@ input[type=submit] {
height: 32px; height: 32px;
padding: 16px; padding: 16px;
background-position: center center; background-position: center center;
background-attachment: fixed;
background-repeat: no-repeat; background-repeat: no-repeat;
background-image: url('img/check.png'); background-image: url('img/check.png');
} }
@@ -89,12 +90,6 @@ input[type=submit] {
background-image: url('img/warning.png'); background-image: url('img/warning.png');
} }
@media (max-width: 600px) {
.window:not([role="tabpanel"]) {
left: 0;
width: calc(100% - 6px);
}
}
.window { .window {
flex-grow: 1; flex-grow: 1;
@@ -255,6 +250,13 @@ input[type="range"]::-moz-range-thumb {
width: 128px; width: 128px;
} }
#vote-stars {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
}
#vote-stars .star-wrapper { #vote-stars .star-wrapper {
height: 31px; height: 31px;
width:160px; width:160px;
@@ -279,3 +281,25 @@ input[type="range"]::-moz-range-thumb {
#vote-stars a:hover ~ a { #vote-stars a:hover ~ a {
background-image: url(img/star-inactive.png) !important; background-image: url(img/star-inactive.png) !important;
} }
.undo-wrapper {
display: flex;
flex-flow: row nowrap;
justify-content: center;
text-align: center;
flex-grow: 1;
align-items: center;
}
.undo-wrapper p {
flex-grow: 1;
padding: 0 5px;
}
.undo {
background-image: url(img/undo.png);
background-repeat: no-repeat;
background-position: 50% 0;
padding: 32px 0 4px 0;
height: 50px;
}
+9 -30
View File
@@ -25,42 +25,13 @@ Stemmen
<button id="playpause">⏵️</button> <button id="playpause">⏵️</button>
</div> </div>
<div
id="vote-buttons"
hx-vals='{"spotify_id": "{{ track.id }}"}'
style="margin-top:10px;"
>
<fieldset>
<legend>Dit vind ik een leuk nummer!</legend>
<button
hx-vals='{"vote": "2"}'
hx-post="{% url 'vote' %}"
>Helemaal mee eens</button>
<button
hx-vals='{"vote": "1"}'
hx-post="{% url 'vote' %}"
>Mee eens</button>
<button
hx-vals='{"vote": "0"}'
hx-post="{% url 'vote' %}"
>Neutraal</button>
<button
hx-vals='{"vote": "-1"}'
hx-post="{% url 'vote' %}"
>Niet mee eens</button>
<button
hx-vals='{"vote": "-2"}'
hx-post="{% url 'vote' %}"
>Helemaal niet mee eens</button>
</fieldset>
</div>
<div <div
id="vote-stars" id="vote-stars"
hx-vals='{"spotify_id": "{{ track.id }}"}' hx-vals='{"spotify_id": "{{ track.id }}"}'
style="margin-top:10px;" style="margin-top:10px;"
> >
<fieldset> <fieldset>
<legend>Hoeveel sterren geef jij dit nummer?</legend> <legend>Hoeveel sterren geef jij dit?</legend>
<div class="star-wrapper"> <div class="star-wrapper">
<a <a
hx-vals='{"vote": "-2"}' hx-vals='{"vote": "-2"}'
@@ -84,6 +55,14 @@ Stemmen
></a> ></a>
</div> </div>
</fieldset> </fieldset>
{% if undo %}
<!--<form class="undo-wrapper" method="post" action="{% url 'undo' %}" hx-vals='{"spotify_id": "{{ undo.track.id }}"}' >-->
<div class="undo-wrapper" hx-vals='{"spotify_id": "{{ undo.track.id }}"}' >
{% csrf_token %}
<p>Je hebt {{undo.track}} een score van {{undo.points | add:3}} sterren gegeven!</p>
<button class="undo" hx-post="{% url 'undo' %}" >Undo</button>
</div>
{% endif %}
</div> </div>
</div> </div>
<script> <script>
-1
View File
@@ -7,7 +7,6 @@
<style> <style>
{% include 'background.css' with background=user.profile.background %} {% include 'background.css' with background=user.profile.background %}
</style> </style>
<link href="{% static 'style.css'%}" rel="stylesheet" type="text/css" />
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'apple-touch-icon.png' %}"> <link rel="apple-touch-icon" sizes="180x180" href="{% static 'apple-touch-icon.png' %}">
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'favicon-32x32.png' %}"> <link rel="icon" type="image/png" sizes="32x32" href="{% static 'favicon-32x32.png' %}">
+1
View File
@@ -6,6 +6,7 @@ from django.conf.urls.static import static
urlpatterns = [ urlpatterns = [
path('track/', views.NominateView.as_view(), name="nominate"), path('track/', views.NominateView.as_view(), name="nominate"),
path('vote/', views.VoteView.as_view(), name="vote"), path('vote/', views.VoteView.as_view(), name="vote"),
path('vote/undo', views.UndoView.as_view(), name="undo"),
path('settings/', views.SettingsView.as_view(), name="settings"), path('settings/', views.SettingsView.as_view(), name="settings"),
path('', views.AuthView.as_view()), path('', views.AuthView.as_view()),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+19 -9
View File
@@ -14,17 +14,16 @@ spt = spotify.Spotify()
class AuthView(View): class AuthView(View):
def get(self, request): def get(self, request):
if request.user.is_authenticated: if request.user.is_authenticated:
#return TemplateResponse(request, "Nominate.html", {}) return HttpResponseRedirect('/vote/')
return HttpResponseRedirect('/vote')
else: else:
return TemplateResponse(request, "Login.html", {}) return TemplateResponse(request, "Login.html", {})
class VoteView(LoginRequiredMixin, View): class VoteView(LoginRequiredMixin, View):
def get(self, request, error=None): def get(self, request, undo=None):
track = get_unvoted(request.user) track = get_unvoted(request.user)
if track and not track.album.image: if track and not track.album.image:
get_and_dither_image(track.album.image_url, track.album, "image") get_and_dither_image(track.album.image_url, track.album, "image")
return TemplateResponse(request, "Vote.html", {"track": track, "error": error}) return TemplateResponse(request, "Vote.html", {"track": track, "undo": undo})
def post(self, request): def post(self, request):
try: try:
spotify_id = self.request.POST['spotify_id'] spotify_id = self.request.POST['spotify_id']
@@ -37,13 +36,10 @@ class VoteView(LoginRequiredMixin, View):
pass pass
else: else:
raise Exception(f"{request.user} already voted for {track}") raise Exception(f"{request.user} already voted for {track}")
Vote.objects.create(track=track, user=request.user, points=score) vote = Vote.objects.create(track=track, user=request.user, points=score)
print(track) return self.get(request, undo=vote)
except Exception as e: except Exception as e:
print(e) print(e)
return self.get(request, str(e))
else:
return self.get(request)
class NominateView(LoginRequiredMixin, View): class NominateView(LoginRequiredMixin, View):
def get(self, request): def get(self, request):
@@ -128,3 +124,17 @@ class SettingsView(LoginRequiredMixin, View):
pass pass
finally: finally:
return self.get(request) return self.get(request)
class UndoView(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)
vote = None
try:
vote = Vote.objects.get(user=request.user, track=track)
except Vote.DoesNotExist:
raise Exception(f"{request.user} did not vote for {track}")
vote.delete()
return HttpResponseRedirect('/vote/')