Added shadow users
This commit is contained in:
parent
c9e76b468a
commit
c2309a4086
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Contest Stations</div>
|
||||
<div class="panel-body">
|
||||
|
@ -28,6 +32,39 @@
|
|||
</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>
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Current QSOs</div>
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in New Issue