Clippy update
Plus some refactors of the templates and styling
This commit is contained in:
+1
-1
@@ -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 = [
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,41 +10,52 @@
|
|||||||
<script src="https://open.spotify.com/embed/iframe-api/v1" async></script>
|
<script src="https://open.spotify.com/embed/iframe-api/v1" async></script>
|
||||||
|
|
||||||
</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>
|
<div class="title-bar">
|
||||||
<main>
|
<div class="title-bar-text">
|
||||||
</main>
|
{% block window-title %}{% endblock %}
|
||||||
|
</div>
|
||||||
<div class="window" style="max-width:960px">
|
<div class="title-bar-controls">
|
||||||
<div class="title-bar">
|
<button aria-label="Help"></button>
|
||||||
<div class="title-bar-text">
|
<button aria-label="Close"></button>
|
||||||
{% block window-title %}{% endblock %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="title-bar-controls">
|
<div class="window-body">
|
||||||
<button aria-label="Help"></button>
|
<menu role="tablist" hx-boost="true">
|
||||||
<button aria-label="Close"></button>
|
<li role="tab" {% if request.path == '/vote/' %}aria-selected="true" {% endif %}>
|
||||||
|
<a href="{% url 'vote' %}">Stemmen</a>
|
||||||
|
</li>
|
||||||
|
<li role="tab" {% if request.path == '/track/' %}aria-selected="true" {% endif %}>
|
||||||
|
<a href="{% url 'nominate' %}">Nomineren</a>
|
||||||
|
</li>
|
||||||
|
<li role="tab" {% if request.path == '/' %}aria-selected="true" {% endif %}>
|
||||||
|
<a href="/">Statistieken</a>
|
||||||
|
</li>
|
||||||
|
</menu>
|
||||||
|
<div class="window" role="tabpanel">
|
||||||
|
<div class="window-body">
|
||||||
|
{% block main-content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="window-body">
|
{% block clippy %}{% endblock %}
|
||||||
<menu role="tablist" hx-boost="true">
|
<script>
|
||||||
<li role="tab" {% if request.path == '/vote/' %}aria-selected="true" {% endif %}>
|
position = { x: 0, y: 0 }
|
||||||
<a href="{% url 'vote' %}">Stemmen</a>
|
|
||||||
</li>
|
interact('.title-bar').draggable({
|
||||||
<li role="tab" {% if request.path == '/track/' %}aria-selected="true" {% endif %}>
|
listeners: {
|
||||||
<a href="{% url 'nominate' %}">Nomineren</a>
|
move (event) {
|
||||||
</li>
|
position.x += event.dx
|
||||||
<li role="tab" {% if request.path == '/' %}aria-selected="true" {% endif %}>
|
position.y += event.dy
|
||||||
<a href="/">Statistieken</a>
|
|
||||||
</li>
|
event.target.parentElement.style.transform =
|
||||||
</menu>
|
`translate(${position.x}px, ${position.y}px)`
|
||||||
<div class="window" role="tabpanel">
|
},
|
||||||
<div class="window-body">
|
}
|
||||||
{% block main-content %}{% endblock %}
|
})
|
||||||
</div>
|
</script>
|
||||||
</div>
|
|
||||||
{% block popup %}{% endblock %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
@@ -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 %}
|
|
||||||
@@ -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 %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block clippy %}
|
||||||
|
{% include "Clippy.html" with body=track.banter img="img/draakje/draakje-headphones3.gif" %}
|
||||||
|
{% endblock %}
|
||||||
+1
-2
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user