1
0
Fork 0

More transmitter submission improvements

Relates to #233
Fixes #364

More improvements to the transmitter submission process to auto-convert PPB to Hz and back, as well as popover.js tooltips from help_text in the model.

Signed-off-by: Corey Shields <cshields@gmail.com>
spacecruft
Corey Shields 2020-08-01 22:12:13 -04:00
parent 2b80a3a88f
commit 0ba46f0913
6 changed files with 136 additions and 30 deletions

View File

@ -31,8 +31,8 @@ class TransmitterModelForm(BSModalModelForm): # pylint: disable=too-many-ancest
]
# yapf: enable
labels = {
'downlink_low': _('Downlink'),
'uplink_low': _('Uplink'),
'downlink_low': _('Downlink freq.'),
'uplink_low': _('Uplink freq.'),
'invert': _('Inverted Transponder?'),
}
widgets = {
@ -52,8 +52,8 @@ class TransmitterUpdateForm(BSModalModelForm): # pylint: disable=too-many-ances
]
# yapf: enable
labels = {
'downlink_low': _('Downlink'),
'uplink_low': _('Uplink'),
'downlink_low': _('Downlink freq.'),
'uplink_low': _('Uplink freq.'),
'invert': _('Inverted Transponder?'),
'created': _('Updated'),
}

View File

@ -284,9 +284,14 @@ class Satellite(models.Model):
class TransmitterEntry(models.Model):
"""Model for satellite transmitters."""
uuid = ShortUUIDField(db_index=True)
description = models.TextField()
description = models.TextField(
help_text='Short description for this entry, like: UHF 9k6 AFSK Telemetry'
)
status = models.CharField(
choices=list(zip(TRANSMITTER_STATUS, TRANSMITTER_STATUS)), max_length=8, default='active'
choices=list(zip(TRANSMITTER_STATUS, TRANSMITTER_STATUS)),
max_length=8,
default='active',
help_text='Functional state of this transmitter'
)
type = models.CharField(
choices=list(zip(TRANSMITTER_TYPE, TRANSMITTER_TYPE)),
@ -300,7 +305,8 @@ class TransmitterEntry(models.Model):
MinValueValidator(MIN_FREQ, message=MIN_FREQ_MSG),
MaxValueValidator(MAX_FREQ, message=MAX_FREQ_MSG)
],
help_text="Hz"
help_text='Frequency (in Hz) for the uplink, or bottom of the uplink range for a \
transponder'
)
uplink_high = models.BigIntegerField(
blank=True,
@ -309,13 +315,14 @@ class TransmitterEntry(models.Model):
MinValueValidator(MIN_FREQ, message=MIN_FREQ_MSG),
MaxValueValidator(MAX_FREQ, message=MAX_FREQ_MSG)
],
help_text="Hz"
help_text='Frequency (in Hz) for the top of the uplink range for a transponder'
)
uplink_drift = models.IntegerField(
blank=True,
null=True,
validators=[MinValueValidator(-99999), MaxValueValidator(99999)],
help_text="PPB"
help_text='Receiver drift from the published uplink frequency, stored in parts \
per billion (PPB)'
)
downlink_low = models.BigIntegerField(
blank=True,
@ -324,7 +331,8 @@ class TransmitterEntry(models.Model):
MinValueValidator(MIN_FREQ, message=MIN_FREQ_MSG),
MaxValueValidator(MAX_FREQ, message=MAX_FREQ_MSG)
],
help_text="Hz"
help_text='Frequency (in Hz) for the downlink, or bottom of the downlink range \
for a transponder'
)
downlink_high = models.BigIntegerField(
blank=True,
@ -333,40 +341,57 @@ class TransmitterEntry(models.Model):
MinValueValidator(MIN_FREQ, message=MIN_FREQ_MSG),
MaxValueValidator(MAX_FREQ, message=MAX_FREQ_MSG)
],
help_text="Hz"
help_text='Frequency (in Hz) for the top of the downlink range for a transponder'
)
downlink_drift = models.IntegerField(
blank=True,
null=True,
validators=[MinValueValidator(-99999), MaxValueValidator(99999)],
help_text="PPB"
help_text='Transmitter drift from the published downlink frequency, stored in \
parts per billion (PPB)'
)
downlink_mode = models.ForeignKey(
Mode,
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='transmitter_downlink_entries'
related_name='transmitter_downlink_entries',
help_text='Modulation mode for the downlink'
)
uplink_mode = models.ForeignKey(
Mode,
blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='transmitter_uplink_entries'
related_name='transmitter_uplink_entries',
help_text='Modulation mode for the uplink'
)
invert = models.BooleanField(
default=False, help_text='True if this is an inverted transponder'
)
baud = models.FloatField(
validators=[MinValueValidator(0)],
blank=True,
null=True,
help_text='The number of modulated symbols that the transmitter sends every second'
)
invert = models.BooleanField(default=False)
baud = models.FloatField(validators=[MinValueValidator(0)], blank=True, null=True)
satellite = models.ForeignKey(
Satellite, null=True, related_name='transmitter_entries', on_delete=models.SET_NULL
)
reviewed = models.BooleanField(default=False)
approved = models.BooleanField(default=False)
created = models.DateTimeField(default=now)
citation = models.CharField(max_length=512, default='CITATION NEEDED - https://xkcd.com/285/')
created = models.DateTimeField(default=now, help_text='Timestamp for this entry or edit')
citation = models.CharField(
max_length=512,
default='CITATION NEEDED - https://xkcd.com/285/',
help_text='A reference (preferrably URL) for this entry or edit'
)
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
service = models.CharField(
choices=zip(SERVICE_TYPE, SERVICE_TYPE), max_length=34, default='Unknown'
choices=zip(SERVICE_TYPE, SERVICE_TYPE),
max_length=34,
default='Unknown',
help_text='The published usage category for this transmitter'
)
# NOTE: future fields will need to be added to forms.py and to

View File

@ -295,7 +295,7 @@ CSP_SCRIPT_SRC = config(
'https://*.google-analytics.com,'
'https://kit-free.fontawesome.com,'
'https://kit.fontawesome.com,'
"'sha256-poSsg4msM/d4NUuFqtWj+1p7OhspHij16g58RBWo7Nk='," # transmitter_modal.js
"'sha256-wMIRCqWVu9YgOwizZzrYvTWAiAn0Y8PQTRdiHy2BNRk='," # transmitter_modal.js
)
CSP_IMG_SRC = config(
'CSP_IMG_SRC',

View File

@ -6,11 +6,25 @@
// to have the hash recalculated and changed in settings.py under
// CSP_SCRIPT_SRC
function ppb_to_freq(freq, drift) {
var freq_obs = freq + ((freq * drift) / Math.pow(10,9));
return Math.round(freq_obs);
}
function freq_to_ppb(freq_obs, freq) {
if(freq == 0){
return 0;
} else {
return Math.round(((freq_obs / freq) - 1) * Math.pow(10,9));
}
}
function transmitter_suggestion_type(selection) {
switch(selection){
case 'Transmitter':
$('.input-group').has('input[name=\'uplink_low\']').addClass('d-none');
$('.input-group').has('input[name=\'uplink_high\']').addClass('d-none');
$('.input-group').has('input[name=\'uplink_drift_hz\']').addClass('d-none');
$('.input-group').has('input[name=\'uplink_drift\']').addClass('d-none');
$('.input-group').has('input[name=\'downlink_high\']').addClass('d-none');
$('.input-group').has('input[name=\'invert\']').addClass('d-none');
@ -20,21 +34,23 @@ function transmitter_suggestion_type(selection) {
$('select[name=\'invert\']').removeAttr('checked');
$('input[name=\'uplink_low\']').val('');
$('input[name=\'uplink_drift\']').val('');
$('input[name=\'uplink_drift_hz\']').val('');
$('select[name=\'uplink_mode\']').val('');
$('.input-group-prepend:contains(\'Downlink Low\')').html('Downlink');
$('.input-group-prepend:contains(\'Downlink Low\')').html('Downlink Freq.');
break;
case 'Transceiver':
$('.input-group').has('input[name=\'uplink_high\']').addClass('d-none');
$('.input-group').has('input[name=\'downlink_high\']').addClass('d-none');
$('.input-group').has('input[name=\'invert\']').addClass('d-none');
$('.input-group').has('input[name=\'uplink_low\']').removeClass('d-none');
$('.input-group').has('input[name=\'uplink_drift_hz\']').removeClass('d-none');
$('.input-group').has('input[name=\'uplink_drift\']').removeClass('d-none');
$('.input-group').has('select[name=\'uplink_mode\']').removeClass('d-none');
$('input[name=\'uplink_high\']').val('');
$('input[name=\'downlink_high\']').val('');
$('select[name=\'invert\']').removeAttr('checked');
$('input[name=\'downlink_low\']').prev().html('Downlink');
$('input[name=\'uplink_low\']').prev().html('Uplink');
$('input[name=\'downlink_low\']').prev().html('Downlink Freq.');
$('input[name=\'uplink_low\']').prev().html('Uplink Freq.');
break;
case 'Transponder':
$('.input-group').has('input[name=\'uplink_high\']').removeClass('d-none');
@ -42,6 +58,7 @@ function transmitter_suggestion_type(selection) {
$('.input-group').has('input[name=\'invert\']').removeClass('d-none');
$('.input-group').has('input[name=\'uplink_low\']').removeClass('d-none');
$('.input-group').has('input[name=\'uplink_drift\']').removeClass('d-none');
$('.input-group').has('input[name=\'uplink_drift_hz\']').removeClass('d-none');
$('.input-group').has('select[name=\'uplink_mode\']').removeClass('d-none');
$('input[name=\'downlink_low\']').prev().html('Downlink low');
$('input[name=\'uplink_low\']').prev().html('Uplink low');
@ -50,10 +67,36 @@ function transmitter_suggestion_type(selection) {
}
$(function () {
$('input[name=\'uplink_drift\']').prop('readonly', true);
var uplink_ppb = $('input[name=\'uplink_drift\']').val();
if (uplink_ppb != 0) {
var uplink_freq = parseInt($('input[name=\'uplink_low\']').val());
$('input[name=\'uplink_drift_hz\']').val(ppb_to_freq(uplink_freq, uplink_ppb));
}
$('input[name=\'uplink_drift_hz\']').on('change click', function(){
var freq_obs = parseInt($(this).val());
var freq = parseInt($('input[name=\'uplink_low\']:visible').val());
$('input[name=\'uplink_drift\']').val(freq_to_ppb(freq_obs,freq));
});
$('input[name=\'downlink_drift\']').prop('readonly', true);
var downlink_ppb = $('input[name=\'downlink_drift\']').val();
if (downlink_ppb != 0) {
var downlink_freq = parseInt($('input[name=\'downlink_low\']').val());
$('input[name=\'downlink_drift_hz\']').val(ppb_to_freq(downlink_freq, downlink_ppb));
}
$('input[name=\'downlink_drift_hz\']').on('change click', function(){
var freq_obs = parseInt($(this).val());
var freq = parseInt($('input[name=\'downlink_low\']:visible').val());
$('input[name=\'downlink_drift\']').val(freq_to_ppb(freq_obs,freq));
});
transmitter_suggestion_type($('#id_type option:selected').text());
$('#id_type').on('change click', function () {
var selection = $(this).val();
transmitter_suggestion_type(selection);
});
});
});
// Enable tooltips
$('[data-toggle="tooltip"]').tooltip();

View File

@ -19,11 +19,30 @@
</div>
{% for field in form %}
<div class="input-group my-1">
{% if 'drift' in field.id_for_label %}
<div class="input-group my-1"
{% if field.help_text %}
data-toggle="tooltip" data-placement="bottom" title="Drifted frequency, when different from the published frequency"
{% endif %}
>
<label class="input-group-prepend input-group-text" for="{{ field.id_for_label }}_hz">{{ field.label }} freq.</label>
<input type="number" name="{{ field.name }}_hz" min="-9223372036854775808" max="9223372036854775807"
placeholder="Drifted Frequency" class="form-control" id="{{ field.id_for_label }}_hz">
<label class="input-group-text input-group-append">Hz</label>
</div>
{% endif %}
<div class="input-group my-1"
{% if field.help_text %}
data-toggle="tooltip" data-placement="bottom" title="{{ field.help_text }}"
{% endif %}
>
<label class="input-group-prepend input-group-text" for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
{% if field.help_text %}
<label class="input-group-text input-group-append">{{ field.help_text }}</label>
{% if 'drift' in field.id_for_label %}
<label class="input-group-text input-group-append">PPB</label>
{% elif 'low' in field.id_for_label or 'high' in field.id_for_label %}
<label class="input-group-text input-group-append">Hz</label>
{% endif %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}

View File

@ -19,11 +19,30 @@
</div>
{% for field in form %}
<div class="input-group my-1">
{% if 'drift' in field.id_for_label %}
<div class="input-group my-1"
{% if field.help_text %}
data-toggle="tooltip" data-placement="bottom" title="Drifted frequency, when different from the published frequency"
{% endif %}
>
<label class="input-group-prepend input-group-text" for="{{ field.id_for_label }}_hz">{{ field.label }} freq.</label>
<input type="number" name="{{ field.name }}_hz" min="-9223372036854775808" max="9223372036854775807"
placeholder="Drifted Frequency" class="form-control" id="{{ field.id_for_label }}_hz">
<label class="input-group-text input-group-append">Hz</label>
</div>
{% endif %}
<div class="input-group my-1"
{% if field.help_text %}
data-toggle="tooltip" data-placement="bottom" title="{{ field.help_text }}"
{% endif %}
>
<label class="input-group-prepend input-group-text" for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
{% if field.help_text %}
<label class="input-group-text input-group-append">{{ field.help_text }}</label>
{% if 'drift' in field.id_for_label %}
<label class="input-group-text input-group-append">PPB</label>
{% elif 'low' in field.id_for_label or 'high' in field.id_for_label %}
<label class="input-group-text input-group-append">Hz</label>
{% endif %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}