First iteration on suggestions forms
parent
1befe28bb1
commit
2134f44b49
|
@ -1,18 +1,27 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from db.base.models import Satellite, Transponder
|
||||
from db.base.models import Satellite, Transponder, Suggestion
|
||||
|
||||
|
||||
@admin.register(Satellite)
|
||||
class SatelliteAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'norad_cat_id')
|
||||
|
||||
|
||||
@admin.register(Transponder)
|
||||
class TransponderAdmin(admin.ModelAdmin):
|
||||
list_display = ('description', 'satellite', 'uplink_low',
|
||||
'uplink_high', 'downlink_low', 'downlink_high')
|
||||
search_fields = ('satellite', )
|
||||
list_filter = ('mode', 'invert', 'approved')
|
||||
list_filter = ('mode', 'invert')
|
||||
|
||||
|
||||
admin.site.register(Satellite, SatelliteAdmin)
|
||||
admin.site.register(Transponder, TransponderAdmin)
|
||||
@admin.register(Suggestion)
|
||||
class SuggestionAdmin(admin.ModelAdmin):
|
||||
list_display = ('description', 'suggestion', 'user', 'satellite', 'uplink_low',
|
||||
'uplink_high', 'downlink_low', 'downlink_high', 'approved')
|
||||
search_fields = ('satellite', 'approved')
|
||||
list_filter = ('mode', 'invert')
|
||||
|
||||
def get_queryset(self, request):
|
||||
return Transponder.objects_all.filter(approved=False)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
from django import forms
|
||||
from django.forms import ModelForm
|
||||
|
||||
from db.base.models import Transponder
|
||||
|
||||
|
||||
class SatelliteSearchForm(forms.Form):
|
||||
term = forms.CharField()
|
||||
|
||||
|
||||
class TransponderSuggestionForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Transponder
|
||||
exclude = ['approved']
|
|
@ -10,7 +10,7 @@ class Command(BaseCommand):
|
|||
help = 'Create initial fixtures'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
TransponderFactory.create_batch(20, suggestion=None)
|
||||
TransponderFactory.create_batch(20, suggestion=None, approved=True, user=None)
|
||||
|
||||
satellites = Satellite.objects.all()
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('base', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Suggestion',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('base.transponder',),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='transponder',
|
||||
name='citation',
|
||||
field=models.URLField(max_length=255, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='transponder',
|
||||
name='user',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='transponder',
|
||||
name='satellite',
|
||||
field=models.ForeignKey(related_name='transponders', to='base.Satellite', null=True),
|
||||
),
|
||||
]
|
|
@ -1,17 +1,23 @@
|
|||
from django.core.validators import MinValueValidator
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
MODE_CHOICES = ['FM', 'AFSK', 'BFSK', 'APRS', 'SSTV', 'CW', 'FMN']
|
||||
|
||||
|
||||
class TransponderApprovedManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return super(TransponderApprovedManager, self).get_queryset().filter(approved=True)
|
||||
|
||||
|
||||
class Satellite(models.Model):
|
||||
"""Model for SatNOGS satellites."""
|
||||
norad_cat_id = models.PositiveIntegerField()
|
||||
name = models.CharField(max_length=45)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
return '{0} - {1}'.format(self.norad_cat_id, self.name)
|
||||
|
||||
|
||||
class Transponder(models.Model):
|
||||
|
@ -26,12 +32,23 @@ class Transponder(models.Model):
|
|||
max_length=10)
|
||||
invert = models.BooleanField(default=False)
|
||||
baud = models.FloatField(validators=[MinValueValidator(0)])
|
||||
satellite = models.ForeignKey(Satellite, related_name='transponder',
|
||||
satellite = models.ForeignKey(Satellite, related_name='transponders',
|
||||
null=True)
|
||||
approved = models.BooleanField(default=False)
|
||||
suggestion = models.ForeignKey('self', blank=True, null=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="suggestions")
|
||||
citation = models.URLField(max_length=255, blank=True)
|
||||
user = models.ForeignKey(User, blank=True, null=True,
|
||||
on_delete=models.SET_NULL)
|
||||
|
||||
objects = TransponderApprovedManager()
|
||||
objects_all = models.Manager()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.description
|
||||
|
||||
|
||||
class Suggestion(Transponder):
|
||||
class Meta:
|
||||
proxy = True
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
from django.contrib.auth.models import User
|
||||
|
||||
import factory
|
||||
from factory import fuzzy
|
||||
|
||||
from db.base.models import MODE_CHOICES, Satellite, Transponder
|
||||
|
||||
|
||||
class UserFactory(factory.django.DjangoModelFactory):
|
||||
"""User model factory"""
|
||||
username = factory.Sequence(lambda n: "user_%d" % n)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
|
||||
|
||||
class SatelliteFactory(factory.django.DjangoModelFactory):
|
||||
"""Sattelite model factory."""
|
||||
norad_cat_id = fuzzy.FuzzyInteger(2000, 4000)
|
||||
|
@ -26,6 +36,8 @@ class TransponderFactory(factory.django.DjangoModelFactory):
|
|||
satellite = factory.SubFactory(SatelliteFactory)
|
||||
approved = fuzzy.FuzzyChoice(choices=[True, False])
|
||||
suggestion = factory.SubFactory('db.base.tests.TransponderFactory')
|
||||
citation = fuzzy.FuzzyText()
|
||||
user = factory.SubFactory('db.base.tests.UserFactory')
|
||||
|
||||
class Meta:
|
||||
model = Transponder
|
||||
|
|
|
@ -3,4 +3,5 @@ from django.conf.urls import patterns, url
|
|||
urlpatterns = patterns(
|
||||
'db.base.views',
|
||||
url(r'^$', 'home', name='home'),
|
||||
url(r'^suggestion/$', 'suggestion', name='suggestion'),
|
||||
)
|
||||
|
|
|
@ -1,15 +1,54 @@
|
|||
from django.shortcuts import render
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.contrib.auth.models import User
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from db.base.models import Transponder, Satellite
|
||||
|
||||
from db.base.models import Transponder, Satellite, MODE_CHOICES
|
||||
from db.base.forms import SatelliteSearchForm, TransponderSuggestionForm
|
||||
|
||||
|
||||
def home(request):
|
||||
"""View to render index page."""
|
||||
satellites = Satellite.objects.all()
|
||||
transponders = Transponder.objects.all()
|
||||
contributors = User.objects.filter(is_active=1)
|
||||
|
||||
if request.method == 'POST':
|
||||
satellite_form = SatelliteSearchForm(request.POST)
|
||||
if satellite_form.is_valid():
|
||||
term = satellite_form.cleaned_data['term']
|
||||
norad_cat_id = term.split()[0]
|
||||
try:
|
||||
satellite = Satellite.objects.get(norad_cat_id=norad_cat_id)
|
||||
except:
|
||||
messages.error(request, 'Please select one of the available Satellites')
|
||||
return redirect(reverse('home'))
|
||||
|
||||
return render(request, 'base/home.html', {'satellites': satellites,
|
||||
'transponders': transponders,
|
||||
'satellite': satellite,
|
||||
'contributors': contributors,
|
||||
'satellite_form': satellite_form,
|
||||
'modes': MODE_CHOICES})
|
||||
|
||||
return render(request, 'base/home.html', {'satellites': satellites,
|
||||
'transponders': transponders,
|
||||
'contributors': contributors})
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def suggestion(request):
|
||||
suggestion_form = TransponderSuggestionForm(request.POST)
|
||||
if suggestion_form.is_valid():
|
||||
suggestion = suggestion_form.save(commit=False)
|
||||
suggestion.user = request.user
|
||||
suggestion.save()
|
||||
|
||||
messages.success(request, 'Your suggestion was stored successfully. Thanks for contibuting!')
|
||||
return redirect(reverse('home'))
|
||||
|
||||
messages.error(request, 'We are sorry, but some error occured :(')
|
||||
return redirect(reverse('home'))
|
||||
|
|
|
@ -1,4 +1,17 @@
|
|||
$(document).ready(function() {
|
||||
'use strict';
|
||||
|
||||
$('#search-input').focus();
|
||||
|
||||
$('#search-input').keypress(function (e) {
|
||||
if (e.which == 13) {
|
||||
$('#search-form').submit();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$('#search-button').click(function (e) {
|
||||
$('#search-form').submit();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,34 +20,42 @@
|
|||
|
||||
<div class="row" id="search">
|
||||
<div class="col-md-12">
|
||||
<form method="post" action="">
|
||||
<input type="text" list="satellites-list"
|
||||
<form method="post" action="{% url 'home' %}" id="search-form">{% csrf_token %}
|
||||
<div class="input-group">
|
||||
<input type="text" name="term" list="satellites-list" id="search-input"
|
||||
class="form-control input-lg satellite-search"
|
||||
placeholder="Search for satellite (NORAD Cat ID or Name)">
|
||||
placeholder="Select Satellite (Type NORAD Cat ID or Name)" autocomplete="off">
|
||||
<div class="input-group-addon">
|
||||
<a href="#" id="search-button">
|
||||
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<datalist id="satellites-list">
|
||||
{% for sat in satellites %}
|
||||
<option value="{{ sat.name }}">
|
||||
<option value="{{ sat }}">
|
||||
{% endfor %}
|
||||
</datalist>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 satellite-panels">
|
||||
{% for sat in satellites %}
|
||||
{% if satellite %}
|
||||
<div class="row">
|
||||
<div class="col-md-12 satellite-panels">
|
||||
<div class="panel panel-default panel-satellite">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<span class="satellite-title">{{ sat.norad_cat_id }} {{ sat.name }}</span>
|
||||
<span class="satellite-title">{{ satellite }}</span>
|
||||
<button type="button"
|
||||
class="btn btn-default btn-sm pull-right add-transponder">
|
||||
class="btn btn-default btn-sm pull-right add-transponder"
|
||||
data-toggle="modal" data-target="#NewSuggestionModal">
|
||||
<span class="glyphicon glyphicon-plus" title="Suggest new transponder"></span>
|
||||
</button>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{% for transponder in sat.transponder.all %}
|
||||
{% for transponder in satellite.transponders.all %}
|
||||
<div class="row panel-body">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default panel-transponder">
|
||||
|
@ -57,7 +65,7 @@
|
|||
<button type="button"
|
||||
class="btn btn-default btn-sm pull-right suggest-transponder"
|
||||
data-toggle="modal"
|
||||
data-target="#editModal">
|
||||
data-target="#EditSuggestionModal">
|
||||
<span class="glyphicon glyphicon-edit" title="Suggest edits"></span>
|
||||
</button>
|
||||
</h3>
|
||||
|
@ -65,19 +73,170 @@
|
|||
<div class="panel-body">
|
||||
<div class="container transponder-element">
|
||||
<div class="col-md-3">
|
||||
<span class="label label-default">{{ transponder.key }}</span>
|
||||
<span class="pull-right">{{ transponder.value }}</span>
|
||||
<span class="label label-default">Uplink Low</span>
|
||||
<span class="pull-right">{{ transponder.uplink_low }} - {{ transponder.approved }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Suggestion Modal -->
|
||||
<div class="modal fade" id="EditSuggestionModal" tabindex="-1" role="dialog" aria-labelledby="EditSuggestionModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="EditSuggestionModalLabel">Suggest an edit to this Transponder</h4>
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
<form action="{% url 'suggestion' %}" method="post" id="editsuggestion-form">{% csrf_token %}
|
||||
<div class="modal-body">
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Description</div>
|
||||
<input type="text" class="form-control" name="description" value="{{ transponder.description }}">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<input type="checkbox" value="1" name="alive" {% if transponder.alive %}checked{% endif %}> Alive
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Uplink Low</div>
|
||||
<input type="text" class="form-control" name="uplink_low" value="{{ transponder.uplink_low }}">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Uplink High</div>
|
||||
<input type="text" class="form-control" name="uplink_high" value="{{ transponder.uplink_high }}">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Downlink Low</div>
|
||||
<input type="text" class="form-control" name="downlink_low" value="{{ transponder.downlink_low }}">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Downlink High</div>
|
||||
<input type="text" class="form-control" name="downlink_high" value="{{ transponder.downlink_high }}">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Mode</div>
|
||||
<select class="form-control" name="mode">
|
||||
{% for mode in modes %}
|
||||
<option value="{{ mode }}" {% ifequal transponder.mode mode %}selected{% endifequal %}>
|
||||
{{ mode }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<input type="checkbox" value="1" name="invert" {% if transponder.invert %}checked{% endif %}> Invert
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Baud Rate</div>
|
||||
<input type="text" class="form-control" name="baud" value="{{ transponder.baud }}">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Citation URL</div>
|
||||
<input type="url" class="form-control" name="citation" value="{{ transponder.citation }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Send</button>
|
||||
</div>
|
||||
<input type="hidden" name="suggestion" value="{{ transponder.pk }}">
|
||||
<input type="hidden" name="satellite" value="{{ satellite.pk }}">
|
||||
</form>
|
||||
{% else %}
|
||||
<div class="modal-body">
|
||||
<div class="text-danger">You need to login first to add a new suggestion.</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<a href="{% url 'account_login' %}" class="btn btn-primary">Log In</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Suggestion Modal -->
|
||||
<div class="modal fade" id="NewSuggestionModal" tabindex="-1" role="dialog" aria-labelledby="NewSuggestionModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="NewSuggestionModalLabel">Suggest a new Transponder</h4>
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
<form action="{% url 'suggestion' %}" method="post" id="newsuggestion-form">{% csrf_token %}
|
||||
<div class="modal-body">
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Description</div>
|
||||
<input type="text" class="form-control" name="description">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<input type="checkbox" value="1" name="alive"> Alive
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Uplink_Low</div>
|
||||
<input type="text" class="form-control" name="uplink_low">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Uplink High</div>
|
||||
<input type="text" class="form-control" name="uplink_high">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Downlink Low</div>
|
||||
<input type="text" class="form-control" name="downlink_low">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Downlink High</div>
|
||||
<input type="text" class="form-control" name="downlink_high">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Mode</div>
|
||||
<select class="form-control" name="mode">
|
||||
{% for mode in modes %}
|
||||
<option value="{{ mode }}">
|
||||
{{ mode }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<input type="checkbox" value="1" name="invert"> Invert
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Baud Rate</div>
|
||||
<input type="text" class="form-control" name="baud">
|
||||
</div>
|
||||
<div class="input-group transponder-element-suggest">
|
||||
<div class="input-group-addon">Citation URL</div>
|
||||
<input type="url" class="form-control" name="citation">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Send</button>
|
||||
</div>
|
||||
<input type="hidden" name="satellite" value="{{ satellite.pk }}">
|
||||
</form>
|
||||
{% else %}
|
||||
<div class="modal-body">
|
||||
<div class="text-danger">You need to login first to add a new suggestion.</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<a href="{% url 'account_login' %}" class="btn btn-primary">Log In</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="info row">
|
||||
<div class="col-md-4">
|
||||
|
|
|
@ -9,7 +9,7 @@ urlpatterns = patterns(
|
|||
'',
|
||||
|
||||
# Base
|
||||
url(r'^$', include('db.base.urls')),
|
||||
url(r'^', include('db.base.urls')),
|
||||
|
||||
# Accounts
|
||||
url(r'^accounts/', include('allauth.urls')),
|
||||
|
|
Loading…
Reference in New Issue