Clippy update

Plus some refactors of the templates and styling
This commit is contained in:
2024-02-13 23:44:59 +01:00
parent d77ad8fec9
commit c7bd7fda9b
8 changed files with 226 additions and 130 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ SECRET_KEY = 'oefjei1lwe918Alkfwuf3ionwu-@kt)6m1e)ah$&^_i9y!qffhm-a$#m6+++'
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
ALLOWED_HOSTS = [] ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [ INSTALLED_APPS = [
+90 -3
View File
@@ -1,8 +1,9 @@
.popup { .window:not([role="tabpanel"]) {
position: fixed; position: fixed;
z-index:99; z-index:99;
min-width: 380px; min-width: 380px;
max-width:540px; min-height: 520px;
width:max(560px, 50vw);
resize: both; resize: both;
overflow-y:scroll; overflow-y:scroll;
overflow-x:visible; overflow-x:visible;
@@ -11,12 +12,38 @@
justify-content: space-between; justify-content: space-between;
} }
@media (max-width: 600px) {
.window:not([role="tabpanel"]) {
left: 0;
width: calc(100% - 6px);
}
}
.window {
flex-grow: 1;
flex-shrink: 0;
}
.window-body {
flex-grow: 1;
display: flex;
flex-flow: column nowrap;
}
/* tab menu fix */
menu[role="tablist"] > li > a {
padding: 6px;
margin: 0;
}
iframe { iframe {
opacity: 0; opacity: 0;
position: fixed; position: fixed;
left: 100%; left: 100%;
} }
/* Media player */
#album { #album {
background: black; background: black;
width: 100%; width: 100%;
@@ -58,5 +85,65 @@ input[type="range"]::-moz-range-thumb {
background: transparent; background: transparent;
border: 3px solid lightgray; border: 3px solid lightgray;
border-bottom-color: darkgrey; border-bottom-color: darkgrey;
box-shadow: 1px 0 0 #fff,1px 1px 0 #fff,0 1px 0 #fff,-1px 0 0 #a9a9a9,-1px -1px 0 #a9a9a9,0 -1px 0 #a9a9a9,-1px 1px 0 #fff,1px -1px #a9a9a9; }
/* Clippy */
.clippy {
position: fixed;
z-index:99;
right: 5px;
bottom: 0px;
display: flex;
flex-flow: column nowrap;
align-items: flex-end;
width: 256px;
}
.clippy .body {
background: lightyellow;
color: black;
padding: 10px;
border-radius: 10px;
border: 1px solid black;
position: relative;
}
.clippy .body.hide {
display: none;
}
.clippy .body::after {
content: "";
position: absolute;
bottom: -13px;
left: 128px;
border-width: 13px 17px 0;
border-style: solid;
border-color: lightyellow transparent;
display: block;
width: 0;
}
.clippy .body::before {
content: "";
position: absolute;
bottom: -14px;
left: 126px;
border-width: 14px 19px 0;
border-style: solid;
border-color: black transparent;
display: block;
width: 0;
}
.clippy .body button {
background: lightyellow;
border: 1px #999 solid;
border-radius: 2px;
box-shadow: none;
margin-top: 5px;
}
.clippy img {
width: 128px;
} }
+19 -8
View File
@@ -11,12 +11,7 @@
</head> </head>
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' style="background:#01817F;"> <body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' style="background:#01817F;">
<header> <div class="window">
</header>
<main>
</main>
<div class="window" style="max-width:960px">
<div class="title-bar"> <div class="title-bar">
<div class="title-bar-text"> <div class="title-bar-text">
{% block window-title %}{% endblock %} {% block window-title %}{% endblock %}
@@ -43,8 +38,24 @@
{% block main-content %}{% endblock %} {% block main-content %}{% endblock %}
</div> </div>
</div> </div>
{% block popup %}{% endblock %}
</div> </div>
</div>
{% block clippy %}{% endblock %}
<script>
position = { x: 0, y: 0 }
interact('.title-bar').draggable({
listeners: {
move (event) {
position.x += event.dx
position.y += event.dy
event.target.parentElement.style.transform =
`translate(${position.x}px, ${position.y}px)`
},
}
})
</script>
</body> </body>
</html> </html>
+17
View File
@@ -0,0 +1,17 @@
{% load static %}
<script>
function closeclippy(e) {
console.log(e)
e.parentElement.classList.add("hide")
}
</script>
<div class="clippy">
<div class="body">
{{ body }}
<br /><button onclick="closeclippy(this)">Ok</button>
</div>
{% if img %}
<img src="{% static img %}" />
{% endif %}
</div>
-75
View File
@@ -1,75 +0,0 @@
{% if track %}
<div id="vote-box" hx-target="#vote-box">
{% if error %}<div class="error">{{ error }}</div>{% endif %}
<div id="embed"></div>
<div id="album">
{% if track.album.image_url %}
<img src="{{track.album.image_url}}" />
{% else %}
<img src="https://kagi.com/proxy/windows-95-logo-png-1.png?c=xjdP8sWN58YWflc6NcGN5ZvzREJyOwtrou-TSsaXxcx37J0VVJbSeycOcAptMJEUpzzvqmbKQ3JRuSmPN8HCK43OxjkRe_cQvncxVzlCblc%3D" />
{% endif %}
<h1>{{track.name}}</h1>
<h2>{{track.artist}}</h2>
</div>
<input id="seek" type="range" min="0" step="0.1" max="100" value="0" />
<button id="playpause">||</button>
<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-track' %}"
>Helemaal mee eens</button>
<button
hx-vals='{"vote": "1"}'
hx-post="{% url 'vote-track' %}"
>Mee eens</button>
<button
hx-vals='{"vote": "0"}'
hx-post="{% url 'vote-track' %}"
>Neutraal</button>
<button
hx-vals='{"vote": "-1"}'
hx-post="{% url 'vote-track' %}"
>Niet mee eens</button>
<button
hx-vals='{"vote": "-2"}'
hx-post="{% url 'vote-track' %}"
>Helemaal niet mee eens</button>
</fieldset>
</div>
{% if track.banter %}
{% block popup %}
{% include "Popup.html" with body=track.banter title=track img="img/draakje/draakje-headphones3.gif" %}
{% endblock %}
{% endif %}
</div>
<script>
window.onSpotifyIframeApiReady = (IFrameAPI) => {
let element = document.getElementById('embed');
let options = {
uri: 'spotify:track:{{track.id}}'
};
const callback = (EmbedController) => {
document.getElementById("playpause").addEventListener('click', () => {
//EmbedController.loadUri(episode.dataset.spotifyId)
EmbedController.togglePlay()
});
EmbedController.addListener('playback_update', e => {
console.log(e);
document.getElementById('seek').value = `${parseInt(e.data.position) / parseInt(e.data.duration) * 100}`;
})
};
IFrameAPI.createController(element, options, callback);
};
{% else %}
<p hx-boost="true">
Je hebt niets meer om te stemmen. Lekker bezig!
<a href="{% url 'nominate' %}">Nomineer zelf iets</a>, als je nog quota hebt.
</p>
{% endif %}
+72 -2
View File
@@ -5,7 +5,77 @@ Stemmen
{% endblock %} {% endblock %}
{% block main-content %} {% block main-content %}
<div hx-get="{% url 'vote-track' %}" hx-trigger="load"> {% if track %}
Laden... <div id="vote-box" hx-target="body">
{% if error %}<div class="error">{{ error }}</div>{% endif %}
<div id="embed"></div>
<div id="album">
{% if track.album.image_url %}
<img src="{{track.album.image_url}}" />
{% else %}
<img src="https://kagi.com/proxy/windows-95-logo-png-1.png?c=xjdP8sWN58YWflc6NcGN5ZvzREJyOwtrou-TSsaXxcx37J0VVJbSeycOcAptMJEUpzzvqmbKQ3JRuSmPN8HCK43OxjkRe_cQvncxVzlCblc%3D" />
{% endif %}
<h1>{{track.name}}</h1>
<h2>{{track.artist}}</h2>
</div> </div>
<input id="seek" type="range" min="0" step="0.1" max="100" value="0" />
<button id="playpause">⏵️</button>
<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>
<script>
window.onSpotifyIframeApiReady = (IFrameAPI) => {
let element = document.getElementById('embed');
let options = {
uri: 'spotify:track:{{track.id}}'
};
const callback = (EmbedController) => {
document.getElementById("playpause").addEventListener('click', () => {
EmbedController.togglePlay()
});
EmbedController.addListener('playback_update', e => {
document.getElementById('seek').value = `${parseInt(e.data.position) / parseInt(e.data.duration) * 100}`;
})
};
IFrameAPI.createController(element, options, callback);
};
</script>
{% else %}
<p hx-boost="true">
Je hebt niets meer om te stemmen. Lekker bezig!
<a href="{% url 'nominate' %}">Nomineer zelf iets</a>, als je nog quota hebt.
</p>
{% endif %}
{% endblock %}
{% block clippy %}
{% include "Clippy.html" with body=track.banter img="img/draakje/draakje-headphones3.gif" %}
{% endblock %} {% endblock %}
+1 -2
View File
@@ -2,10 +2,9 @@ from django.urls import path
from . import views from . import views
urlpatterns = [ urlpatterns = [
path('track/<str:spotify_id>', views.TrackDetailView.as_view(), name="track-detail"),
path('track/', views.NominateView.as_view(), name="nominate"), path('track/', views.NominateView.as_view(), name="nominate"),
path('track/<str:spotify_id>/banter', views.BanterView.as_view(), name="track-banter"), path('track/<str:spotify_id>/banter', views.BanterView.as_view(), name="track-banter"),
path('vote/', views.VoteView.as_view(), name="vote"), path('vote/', views.VoteView.as_view(), name="vote"),
path('vote/track', views.VoteTrackView.as_view(), name="vote-track"), #path('vote/track', views.VoteTrackView.as_view(), name="vote-track"),
path('', views.AuthView.as_view()), path('', views.AuthView.as_view()),
] ]
+2 -15
View File
@@ -15,23 +15,10 @@ class AuthView(View):
def get(self, request): def get(self, request):
return TemplateResponse(request, "Login.html", {}) return TemplateResponse(request, "Login.html", {})
class TrackDetailView(LoginRequiredMixin, View):
def get(self, request, spotify_id):
try:
track = Track.objects.get(pk=spotify_id)
return HttpResponse(str(track))
except Track.DoesNotExist:
return HttpResponse("No track")
class VoteView(LoginRequiredMixin, View): class VoteView(LoginRequiredMixin, View):
def get(self, request):
songs = Track.objects.all()
return TemplateResponse(request, "Vote.html", {"songs": songs})
class VoteTrackView(LoginRequiredMixin, View):
def get(self, request, error=None): def get(self, request, error=None):
track = get_unvoted(request.user) track = get_unvoted(request.user)
return TemplateResponse(request, "SpotifyEmbed.html", {"track": track, "error": error}) return TemplateResponse(request, "Vote.html", {"track": track, "error": error})
def post(self, request): def post(self, request):
try: try:
spotify_id = self.request.POST['spotify_id'] spotify_id = self.request.POST['spotify_id']
@@ -41,7 +28,7 @@ class VoteTrackView(LoginRequiredMixin, View):
try: try:
Vote.objects.get(user=request.user, track=track) Vote.objects.get(user=request.user, track=track)
except Vote.DoesNotExist: except Vote.DoesNotExist:
pass #expected behaviour 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.objects.create(track=track, user=request.user, points=score)