Add 'insert' view for inserting ratings on paper

main
Luca 2 years ago
parent bb7e7b5089
commit d0694ed38a

@ -214,3 +214,23 @@ svg {
max-width: var(--max-size); max-width: var(--max-size);
width: 3em; width: 3em;
} }
.row {
display: flex;
margin-bottom: 0.2em;
}
.row > :not(:first-child) {
margin-left: 0.5em !important;
}
.row > .rating-container {
justify-content: center;
margin: 0;
padding: 0;
}
.row > .rating-container > .rating > .rating-point {
height: 1em;
width: 1em;
}

@ -1,5 +1,11 @@
from django import forms from django import forms
from django.conf import settings from django.conf import settings
class InsertForm(forms.Form):
name = forms.CharField()
rating = forms.ChoiceField(choices=settings.RATING_CHOICES, required=False, widget=forms.RadioSelect)
InsertFormSet = forms.formset_factory(InsertForm)
class RateArtistForm(forms.Form): class RateArtistForm(forms.Form):
rating = forms.ChoiceField(choices=settings.RATING_CHOICES, required=False, widget=forms.RadioSelect) rating = forms.ChoiceField(choices=settings.RATING_CHOICES, required=False, widget=forms.RadioSelect)

@ -0,0 +1,126 @@
{% extends "core/base.html" %}
{% block title %}A/D-Wandler{% endblock %}
{% block body %}
<form action="" method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div class="row">
{{ form.name }}
<div class="rating-container">
<div class="rating" style="--num-choices: {{ form.rating | length }}">
{% for radio in form.rating %}
{{ radio.tag }}
<label class="rating-point" for="{{ radio.id_for_label }}"></label>
{% endfor %}
</div>
</div>
<button class="reset" type="button">Zurücksetzen</button>
</div>
{% endfor %}
<button id="add" type="button">+</button>
<button type="submit">Speichern</button>
</form>
{{ playlist | json_script:"playlist" }}
<script>
const playlist = JSON.parse(document.getElementById('playlist').textContent);
const findBestMatch = value => playlist.find(name => name.toLowerCase().includes(value) || value.includes(name.toLowerCase())) || '';
const registerEvents = row => {
const input = row.querySelector('input[name$=name]');
input.addEventListener('input', () => {
const value = (input.dataset.value || '') + input.value.toLowerCase();
input.dataset.value = value;
const bestMatch = findBestMatch(value);
input.placeholder = bestMatch;
input.value = '';
input.dataset.bestMatch = bestMatch;
});
input.addEventListener('keydown', event => {
if (event.key === 'Backspace') {
if (input.value !== '') {
input.value = '';
} else {
const value = (input.dataset.value || '').slice(0, -1);
input.dataset.value = value;
if (value === '') {
input.placeholder = '';
input.dataset.bestMatch = '';
} else {
const bestMatch = findBestMatch(value);
input.placeholder = bestMatch;
input.dataset.bestMatch = bestMatch;
}
}
event.preventDefault();
} else if (event.key === 'Tab') {
input.placeholder = '';
input.value = input.dataset.bestMatch || '';
input.dataset.bestMatch = '';
input.dataset.value = '';
event.preventDefault();
}
});
row.querySelector('.reset').addEventListener('click', event => {
event.target.parentElement.querySelectorAll('.rating-container > .rating > input').forEach(input => {
input.checked = false;
});
});
};
document.querySelectorAll('.row').forEach(registerEvents);
const totalForms = document.getElementById('id_form-TOTAL_FORMS');
let numForms = Number.parseInt(totalForms.value);
const replace = value => value.replace(/form-\d+-(.+)/, `form-${numForms}-$1`);
const addBtn = document.getElementById('add');
addBtn.addEventListener('click', () => {
const row = document.querySelector('.row').cloneNode(true);
row.querySelectorAll('[name^=form-]').forEach(input => {
const label = row.querySelector(`label[for=${input.id}]`);
if (label) {
label.htmlFor = replace(label.htmlFor);
}
input.id = replace(input.id);
input.name = replace(input.name);
});
const input = row.querySelector('input[name$=name]');
input.placeholder = '';
input.value = '';
input.dataset.bestMatch = '';
input.dataset.value = '';
row.querySelectorAll('.rating-container > .rating > input').forEach(input => {
input.checked = false;
});
registerEvents(row);
addBtn.before(row);
numForms += 1;
totalForms.value = numForms;
});
</script>
{% endblock %}

@ -4,6 +4,7 @@ from . import views
urlpatterns = [ urlpatterns = [
path('create_token/', views.create_token, name='create_token'), path('create_token/', views.create_token, name='create_token'),
path('insert/<slug:session>/', views.insert, name='insert'),
path('join/<slug:session>/', views.join_session, name='join_session'), path('join/<slug:session>/', views.join_session, name='join_session'),
path('participate/<slug:token>/', views.participate, name='participate'), path('participate/<slug:token>/', views.participate, name='participate'),
path('<slug:playlist>/', include([ path('<slug:playlist>/', include([

@ -1,10 +1,11 @@
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse from django.urls import reverse
from .forms import RateArtistForm from .forms import InsertFormSet, RateArtistForm
from .models import Participant, Rating from .models import Participant, Rating
from ..core.models import Session from ..core.models import Artist, Session
# Create your views here. # Create your views here.
@ -21,6 +22,34 @@ def create_token(request):
return render(request, 'vote/create_token.html', {'token': token}) return render(request, 'vote/create_token.html', {'token': token})
@login_required
@transaction.atomic
def insert(request, session):
session = get_object_or_404(Session, pk=session)
formset = InsertFormSet()
if request.method == 'POST':
formset = InsertFormSet(request.POST)
if formset.is_valid():
participant = Participant(session=session)
participant.save()
for form in formset:
if not form.cleaned_data.get('name'):
continue
artist = get_object_or_404(Artist, name=form.cleaned_data['name'])
rating = Rating(artist=artist, participant=participant, value=form.cleaned_data['rating'])
rating.save()
formset = InsertFormSet() # clear formset if successful
playlist = list(session.playlist.artist_set.values_list('name', flat=True))
return render(request, 'vote/insert.html', {'formset': formset, 'playlist': playlist})
def join_session(request, session): def join_session(request, session):
session = get_object_or_404(Session, pk=session) session = get_object_or_404(Session, pk=session)

Loading…
Cancel
Save