1
0
Fork 0

Add utilization factor to station model and UI

environments/stage/deployments/303
Pierros Papadeas 2019-02-07 20:06:39 +02:00
parent e5be997a7a
commit 5e925a4ed6
No known key found for this signature in database
GPG Key ID: 8DB97129D9982991
10 changed files with 205 additions and 69 deletions

View File

@ -88,7 +88,8 @@ class StationSerializer(serializers.ModelSerializer):
model = Station
fields = ('id', 'name', 'altitude', 'min_horizon', 'lat', 'lng',
'qthlocator', 'location', 'antenna', 'created', 'last_seen',
'status', 'observations', 'description', 'client_version')
'status', 'observations', 'description', 'client_version',
'target_utilization')
def get_altitude(self, obj):
return obj.alt

View File

@ -74,6 +74,7 @@ class StationViewApiTest(TestCase):
u'name': self.station.name,
u'observations': 0,
u'qthlocator': self.station.qthlocator,
u'target_utilization': self.station.target_utilization,
u'status': self.station.get_status_display()}
response = self.client.get('/api/stations/')

View File

@ -26,7 +26,7 @@ class AntennaAdmin(admin.ModelAdmin):
@admin.register(Station)
class StationAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'owner', 'get_email', 'lng', 'lat', 'qthlocator',
'client_version', 'created_date', 'state')
'client_version', 'created_date', 'state', 'target_utilization')
list_filter = ('status', 'created', 'client_version')
actions = [export_as_csv]
@ -62,7 +62,7 @@ class TransmitterAdmin(admin.ModelAdmin):
list_display = ('uuid', 'description', 'satellite', 'type', 'alive', 'mode', 'uplink_low',
'uplink_high', 'uplink_drift', 'downlink_low', 'downlink_high',
'downlink_drift', 'baud', 'sync_to_db')
search_fields = ('satellite', 'uuid', 'satellite__name', 'satellite__norad_cat_id')
search_fields = ('uuid', 'satellite__name', 'satellite__norad_cat_id')
list_filter = ('type', 'mode', 'alive', 'sync_to_db')
readonly_fields = ('uuid', 'description', 'satellite', 'type', 'uplink_low', 'uplink_high',
'uplink_drift', 'downlink_low', 'downlink_high', 'downlink_drift',

View File

@ -7,7 +7,8 @@ class StationForm(forms.ModelForm):
class Meta:
model = Station
fields = ['name', 'image', 'alt', 'lat', 'lng', 'qthlocator',
'horizon', 'antenna', 'testing', 'description']
'horizon', 'antenna', 'testing', 'description',
'target_utilization']
image = forms.ImageField(required=False)

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.18 on 2019-02-07 17:52
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0053_remove_station_uuid'),
]
operations = [
migrations.AddField(
model_name='station',
name='target_utilization',
field=models.IntegerField(blank=True, help_text=b'Target utilization factor for your station', null=True, validators=[django.core.validators.MaxValueValidator(100), django.core.validators.MinValueValidator(0)]),
),
]

View File

@ -167,6 +167,11 @@ class Station(models.Model):
horizon = models.PositiveIntegerField(help_text='In degrees above 0', default=10)
description = models.TextField(max_length=500, blank=True, help_text='Max 500 characters')
client_version = models.CharField(max_length=45, blank=True)
target_utilization = models.IntegerField(validators=[MaxValueValidator(100),
MinValueValidator(0)],
help_text='Target utilization factor for '
' your station',
null=True, blank=True)
class Meta:
ordering = ['-status']

View File

@ -115,3 +115,11 @@
font-size: 2em;
}
}
#horizon_value, #utilization_value {
margin: 0 0 0 20px;
.slider-selection {
background: #5bc0de;
}
}

View File

@ -0,0 +1,27 @@
$(document).ready(function() {
'use strict';
$('.selectpicker').selectpicker();
var horizon_value = $('#horizon').val();
$('#horizon').slider({
id: 'horizon_value',
min: 0,
max: 90,
step: 1,
value: horizon_value});
var utilization_value = $('#utilization').val();
$('#utilization').slider({
id: 'utilization_value',
min: 0,
max: 100,
step: 1,
value: utilization_value});
var station_image = $('#station-image').data('existing');
$('#station-image').fileinput({
initialPreview: station_image,
initialPreviewAsData: true,
});
});

View File

@ -4,6 +4,12 @@
{% block title %}{% if station %} - Edit Ground Station {{ station.name }}{% else %} - Add Ground Station{% endif %}{% endblock %}
{% block css %}
<link href="{% static 'lib/bootstrap-select/dist/css/bootstrap-select.min.css' %}" rel="stylesheet" >
<link href="{% static 'lib/bootstrap-slider/dist/css/bootstrap-slider.min.css' %}" rel="stylesheet" >
<link href="{% static 'lib/bootstrap-fileinput/css/fileinput.min.css' %}" rel="stylesheet" >
{% endblock css %}
{% block content %}
<div class="row">
<div class="col-md-6">
@ -18,77 +24,135 @@
</div>
<div class="row">
<div class="col-md-8">
<form role="form" enctype="multipart/form-data" method="post">{% csrf_token %}
<div class="form-group">
<label for="name" class="control-label">Name</label>
<input value="{{ form.name.value|default_if_none:"" }}" id="name" type="text" class="form-control" name="name" required>
</div>
<div class="form-group">
<label for="image" class="control-label">Image</label>
<input id="image" type="file" name="image">
{% if form.image.value %}
<img src="{{ MEDIA_URL }}{{ form.image.value }}"
class="station-edit-image">
{% endif %}
</div>
<div class="form-group">
<label for="alt" class="control-label">Altitude</label>
<input value="{{ form.alt.value|default_if_none:"" }}" id="alt" type="number" class="form-control" name="alt" placeholder="{{ form.alt.help_text }}" required>
</div>
<div class="form-group">
<label for="lat" class="control-label">Latitude</label>
<input value="{{ form.lat.value|default_if_none:"" }}" id="lat" type="text" class="form-control" name="lat" placeholder="{{ form.lat.help_text }}" required>
</div>
<div class="form-group">
<label for="lng" class="control-label">Longtitude</label>
<input value="{{ form.lng.value|default_if_none:"" }}" id="lng" type="text" class="form-control" name="lng" placeholder="{{ form.lng.help_text }}" required>
</div>
<div class="form-group">
<label for="qthlocator" class="control-label">QTH Locator</label>
<input class="form-control"
id="qthlocator"
type="text"
name="qthlocator"
value="{{ form.qthlocator.value|default_if_none:"" }}"
readonly>
</div>
<div class="form-group">
<label for="horizon" class="control-label">Minimum Horizon</label>
<input value="{{ form.horizon.value|default_if_none:"" }}" id="horizon" type="number" class="form-control" name="horizon" placeholder="{{ form.horizon.help_text }}">
</div>
<div class="form-group">
<label for="antennas" class="control-label">Antennas</label>
<select multiple class="form-control" name="antenna">
{% for antenna in antennas %}
<option value="{{ antenna.id }}" {% if antenna in station.antenna.all %}selected{% endif %}>
{{ antenna.band}} {{ antenna.get_antenna_type_display }} | {{ antenna.frequency|frq }} - {{ antenna.frequency_max|frq }}
</option>
{% endfor %}
</select>
<span class="help-block">{{ form.antenna.help_text|safe }}</span>
</div>
<div class="form-group">
<label for="description" class="control-label">Description</label>
<textarea class="form-control" name="description"
id="description" rows="3" maxlength="500">{{ form.description.value|default_if_none:"" }}</textarea>
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" name="testing" {% if form.testing.value %}checked="True"{% endif %} {% if not station.id %}disabled{% endif %}>
Testing?
<span class="glyphicon glyphicon-question-sign" aria-hidden="true" data-toggle="tooltip"
title="Make sure you station is performing well for a period of time before you remove the Testing flag"></span>
</label>
<form role="form" enctype="multipart/form-data" method="post">{% csrf_token %}
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">General Info</h3>
</div>
<div class="panel-body">
<div class="form-group">
<label for="name" class="control-label">Name</label>
<input value="{{ form.name.value|default_if_none:"" }}" id="station-name" type="text" class="form-control" name="name" required>
</div>
<div class="form-group">
<label for="description" class="control-label">Description</label>
<textarea class="form-control" name="description"
id="description" rows="3" maxlength="500">{{ form.description.value|default_if_none:"" }}</textarea>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Location</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label for="lat" class="control-label">Latitude</label>
<input value="{{ form.lat.value|default_if_none:"" }}" id="lat" type="text" class="form-control" name="lat" placeholder="{{ form.lat.help_text }}" required>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="lng" class="control-label">Longtitude</label>
<input value="{{ form.lng.value|default_if_none:"" }}" id="lng" type="text" class="form-control" name="lng" placeholder="{{ form.lng.help_text }}" required>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="alt" class="control-label">Altitude (ASL)</label>
<input value="{{ form.alt.value|default_if_none:"" }}" id="alt" type="number" class="form-control" name="alt" placeholder="{{ form.alt.help_text }}" required>
</div>
</div>
</div>
<div class="form-group">
<label for="qthlocator" class="control-label">QTH Locator</label>
<input class="form-control"
id="qthlocator"
type="text"
name="qthlocator"
value="{{ form.qthlocator.value|default_if_none:"" }}"
readonly>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Image</h3>
</div>
<div class="panel-body">
<div class="form-group">
<input id="station-image" type="file" name="image" data-existing="{{ MEDIA_URL }}{{ form.image.value }}">
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Settings</h3>
</div>
<div class="panel-body">
<div class="form-group">
<label for="horizon" class="control-label">Minimum Horizon</label>
<input id="horizon" type="number" value="{{ form.horizon.value|default_if_none:"" }}" class="form-control" name="horizon" placeholder="{{ form.horizon.help_text }}">
<span class="glyphicon glyphicon-question-sign" aria-hidden="true" data-toggle="tooltip"
title="Your station minimum observable elevation"></span>
</div>
<div class="form-group">
<label for="antennas" class="control-label">Antennas</label>
<select id="antenna-selection" class="form-control selectpicker" multiple name="antenna"
data-selected-text-format="count" data-count-selected-text="Selected {0} antennas">
{% for antenna in antennas %}
<option value="{{ antenna.id }}" {% if antenna in station.antenna.all %}selected{% endif %} data-content="
<span class='label label-info'>{{ antenna.band }} {{ antenna.get_antenna_type_display }}</span> {{ antenna.frequency|frq }} - {{ antenna.frequency_max|frq }}
">
{% endfor %}
</select>
<span class="help-block">{{ form.antenna.help_text|safe }}</span>
</div>
<hr>
<div class="form-group">
<label for="utilization" class="control-label">Target Utilization</label>
<input id="utilization" type="number" value="{{ form.target_utilization.value|default_if_none:"" }}" class="form-control" name="target_utilization" placeholder="{{ form.utilization.help_text }}">
<span class="glyphicon glyphicon-question-sign" aria-hidden="true" data-toggle="tooltip"
title="Your station target utilization"></span>
</div>
<hr>
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" name="testing" {% if form.testing.value %}checked="True"{% endif %} {% if not station.id %}disabled{% endif %}>
Testing?
<span class="glyphicon glyphicon-question-sign" aria-hidden="true" data-toggle="tooltip"
title="Make sure you station is performing well for a period of time before you remove the Testing flag"></span>
</label>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</form>
</div>
{% endblock %}
{% block javascript %}
<script src="{% static 'js/gridsquare.js' %}"></script>
<script src="{% static 'lib/bootstrap-select/dist/js/bootstrap-select.min.js' %}"></script>
<script src="{% static 'lib/bootstrap-slider/dist/bootstrap-slider.min.js' %}"></script>
<script src="{% static 'lib/bootstrap-fileinput/js/fileinput.min.js' %}"></script>
<script src="{% static 'js/station_edit.js' %}"></script>
{% endblock javascript %}

View File

@ -81,6 +81,14 @@
{{ station.horizon }}°
</span>
</div>
{% if station.target_utilization %}
<div class="front-line">
<span class="label label-default">Target Utilization</span>
<span class="front-data">
{{ station.target_utilization }} %
</span>
</div>
{% endif %}
{% if station.antenna %}
<div class="font-line station-antennas">
<span class="label label-default">Antennas</span>