Added shadow users

This commit is contained in:
Sebastian Lohff 2017-01-25 01:53:22 +01:00
parent c9e76b468a
commit c2309a4086
8 changed files with 148 additions and 41 deletions

View File

@ -1,5 +1,5 @@
from django.contrib import admin
from .models import Frequency, Band, Reference, QSO, User, Contest
from .models import Frequency, Band, Reference, QSO, User, Contest, ShadowCall
admin.site.register(User)
admin.site.register(QSO)
@ -7,3 +7,4 @@ admin.site.register(Band)
admin.site.register(Frequency)
admin.site.register(Reference)
admin.site.register(Contest)
admin.site.register(ShadowCall)

View File

@ -2,10 +2,10 @@ from django import forms
from django.contrib.auth.forms import UserCreationForm
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from crispy_forms.layout import Submit, Layout
from django.urls import reverse
from .models import User, Reference, QSO
from .models import User, Reference, QSO, ShadowCall
from .validators import CallUsernameValidator, CallLogValidator
class CustomUserCreationForm(UserCreationForm):
@ -102,3 +102,26 @@ class QSOFormWithTime(QSOForm):
model = QSO
fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "otherNo", "refStr", "remarks"]
class ShadowCallAddForm(forms.ModelForm):
class Meta:
model = ShadowCall
fields = ['username']
def __init__(self, *args, **kwargs):
super(ShadowCallAddForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = "form-inline "
self.helper.form_style = 'inline'
self.helper.field_template = "bootstrap3/layout/inline_field.html"
self.helper.action = reverse("contest:registerRefs")
self.helper.add_input(Submit('submit', 'Add shadow'))
self.helper.layout = Layout(['username'])
def clean_username(self):
data = self.cleaned_data["username"]
if User.objects.filter(username=data).count() > 0:
raise forms.ValidationError("A user with this call already exists, this is not a shadow!")
return data

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2017-01-24 23:28
from __future__ import unicode_literals
import contest.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('contest', '0009_auto_20170123_0139'),
]
operations = [
migrations.CreateModel(
name='ShadowCall',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('username', models.CharField(db_index=True, max_length=20, unique=True, validators=[contest.validators.CallUsernameValidator()])),
('ref', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contest.Reference')),
],
),
]

View File

@ -21,6 +21,13 @@ class Reference(models.Model):
def __str__(self):
return self.name
class ShadowCall(models.Model):
username = models.CharField(max_length=20, unique=True, db_index=True, validators=[CallUsernameValidator()])
ref = models.ForeignKey(Reference, models.SET_NULL,null=True, blank=True)
def __str__(self):
return self.username
class User(AbstractUser):
ref = models.ForeignKey(Reference, models.SET_NULL,null=True, blank=True)

View File

@ -21,7 +21,8 @@ import contest.views as contest_views
urlpatterns = [
url(r'^$', contest_views.contestIndex, name='index'),
url(r'^regref/$', contest_views.registerRefs, name='registerRefs'),
url(r'^regref/edit/(?P<uid>\d+)/$', contest_views.updateRef, name='updateRef'),
url(r'^regref/edit/(?P<uid>\d+)/$', contest_views.updateRef, {"shadow": False}, name='updateRef'),
url(r'^regref/shadow/edit/(?P<uid>\d+)/$', contest_views.updateRef, {"shadow": True}, name='updateShadowRef'),
url(r'^overview/$', contest_views.overview, name='overview'),
url(r'^log/$', contest_views.log, name='log'),
url(r'^log/edit/(?P<qsoid>\d+)/$', contest_views.logEdit, name='logEdit'),

View File

@ -1,8 +1,8 @@
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required
from django.db.models import Q
#from django.db.models import Q
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm
from django.http import HttpResponseRedirect
from django.contrib import messages
@ -11,8 +11,8 @@ from django.contrib.auth import login as auth_login
import datetime
from .models import User, Contest, Frequency, Reference, QSO
from .forms import UpdateRefForm, QSOForm, QSOFormWithTime, CustomUserCreationForm
from .models import User, Contest, Frequency, Reference, QSO, ShadowCall
from .forms import UpdateRefForm, QSOForm, QSOFormWithTime, CustomUserCreationForm, ShadowCallAddForm
def index(request):
if request.user.is_authenticated():
@ -106,24 +106,37 @@ def logDelete(request, qsoid):
@staff_member_required
def registerRefs(request):
allUser = User.objects.all()
refsMissingUser = User.objects.filter(ref=None).order_by("username")
refsNotMissingUser = User.objects.filter(~Q(ref=None)).order_by("username")
shadows = ShadowCall.objects.all()
qsos = QSO.objects.all().order_by("-time")
return render(request, 'contest/registerRefs.html', {'alluser': allUser, 'refsMissingUser': refsMissingUser, "refsNotMissinguser": refsNotMissingUser, "qsos": qsos})
shadowForm = None
if request.method == 'POST':
shadowForm = ShadowCallAddForm(data=request.POST)
if shadowForm.is_valid():
shadowForm.instance.save()
messages.success(request, "Successfully added shadow user %s" % (shadowForm.instance.username,))
return HttpResponseRedirect(reverse("contest:registerRefs"))
else:
shadowForm = ShadowCallAddForm()
return render(request, 'contest/registerRefs.html', {'alluser': allUser, "qsos": qsos, "shadowForm": shadowForm, "shadows": shadows})
@staff_member_required
def updateRef(request, uid):
user = User.objects.get(id=uid)
def updateRef(request, shadow, uid):
user = None
form = None
if shadow:
user = get_object_or_404(ShadowCall, id=uid)
else:
user = get_object_or_404(User, id=uid)
if request.method == 'POST':
form = UpdateRefForm(data=request.POST)
if form.is_valid():
ref = None
if form.cleaned_data["existingRef"]:
print("Got an existing Ref")
ref = form.cleaned_data["existingRef"]
else:
ref = Reference(name=form.cleaned_data["newRefName"])
@ -132,12 +145,12 @@ def updateRef(request, uid):
user.ref = ref
user.save()
messages.success(request, "%s ref set to %s" % (user, ref))
messages.success(request, "%s%s ref set to %s" % ("(shadow) " if shadow else "", user, ref))
return HttpResponseRedirect(reverse("contest:registerRefs"))
else:
form = UpdateRefForm()
return render(request, 'contest/updateRef.html', {'user': user, 'form': form})
return render(request, 'contest/updateRef.html', {'userobj': user, 'form': form, "shadow": shadow})
def overview(request):
# FIXME: Hardcoded for cqtu... everywhere

View File

@ -1,30 +1,67 @@
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">Contest Stations</div>
<div class="panel-body">
Here is a Table with all OMs/YLs in the contest!
<table class="table">
<thead>
<tr>
<th>Call</th>
<th>Ref</th>
<th></th>
</tr>
</thead>
<tbody>
{% for u in alluser %}
<tr class="{% if not u.ref %}danger{% endif %}">
<td>{{ u.username }}</td>
<td>{{ u.ref|default:"unknown / unset" }}</td>
<td><a href="{% url "contest:updateRef" u.id %}">Update / Create ref</a></td>
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Contest Stations</div>
<div class="panel-body">
Here is a Table with all OMs/YLs in the contest!
<table class="table">
<thead>
<tr>
<th>Call</th>
<th>Ref</th>
<th></th>
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for u in alluser %}
<tr class="{% if not u.ref %}danger{% endif %}">
<td>{{ u.username }}</td>
<td>{{ u.ref|default:"unknown / unset" }}</td>
<td><a href="{% url "contest:updateRef" u.id %}">Update / Create ref</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">Shadow Stations <small>(unregistered, but active)</small></div>
<div class="panel-body">
{% if shadowForm.errors %}
<div class="alert alert-danger">
{{ shadowForm.errors }}
</div>
{% endif %}
{% crispy shadowForm %}
<table class="table">
<thead>
<tr>
<th>Call</th>
<th>Ref</th>
<th></th>
</tr>
</thead>
<tbody>
{% for shadow in shadows %}
<tr>
<td>{{ shadow.username }}</td>
<td>{{ shadow.ref|default:"unknown / unset" }}</td>
<td><a href="{% url "contest:updateShadowRef" shadow.id %}">Update / create ref</a>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>

View File

@ -9,14 +9,14 @@
<div class="panel-heading">Edit Exchange for User</div>
<div class="panel-body">
<p>
Create a ref for user {{ user }} or choose an existing ref!
Create a ref for {% if shadow %}shadow call{% else %}user{% endif %} {{ userobj }} or choose an existing ref!
</p>
<form method="post" action="{% url "contest:updateRef" user.id %}">
<form method="post" action="{% if shadow %}{% url "contest:updateShadowRef" userobj.id %}{% else %}{% url "contest:updateRef" userobj.id %}{% endif %}">
{% csrf_token %}
<div class="form-group">
<label class="control-label" for="id_div_user">User</label>
<div id="id_div_user" class="controls readonly">{{ user }}</div>
<label class="control-label" for="id_div_user">Call</label>
<div id="id_div_user" class="controls readonly">{{ userobj }}</div>
</div>
{{ form|crispy }}
<input type="submit" value="Save">