Support suggestions for creating/editing satellite
Signed-off-by: Alfredos-Panagiotis Damkalis <fredy@fredy.gr>spacecruft
parent
c75b491b9b
commit
418fe5ab3d
|
@ -1,7 +1,7 @@
|
|||
"""SatNOGS DB django base Forms class"""
|
||||
from bootstrap_modal_forms.forms import BSModalModelForm
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import NumberInput, TextInput
|
||||
from django.forms import TextInput
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from db.base.models import SatelliteEntry, Transmitter, TransmitterEntry
|
||||
|
@ -19,7 +19,7 @@ def existing_uuid(value):
|
|||
) from error
|
||||
|
||||
|
||||
class TransmitterModelForm(BSModalModelForm): # pylint: disable=too-many-ancestors
|
||||
class TransmitterCreateForm(BSModalModelForm): # pylint: disable=too-many-ancestors
|
||||
"""Model Form class for TransmitterEntry objects"""
|
||||
class Meta:
|
||||
model = TransmitterEntry
|
||||
|
@ -57,16 +57,18 @@ class TransmitterUpdateForm(BSModalModelForm): # pylint: disable=too-many-ances
|
|||
}
|
||||
|
||||
|
||||
class SatelliteModelForm(BSModalModelForm):
|
||||
class SatelliteCreateForm(BSModalModelForm):
|
||||
"""Form that uses django-bootstrap-modal-forms for satellite editing"""
|
||||
class Meta:
|
||||
model = SatelliteEntry
|
||||
fields = [
|
||||
'norad_cat_id', 'name', 'names', 'operator', 'status', 'description', 'countries',
|
||||
'website', 'dashboard_url', 'launched', 'deployed', 'decayed', 'image'
|
||||
'norad_cat_id', 'norad_follow_id', 'name', 'names', 'description', 'operator',
|
||||
'status', 'countries', 'website', 'dashboard_url', 'launched', 'deployed', 'decayed',
|
||||
'image', 'citation'
|
||||
]
|
||||
labels = {
|
||||
'norad_cat_id': _('Norad ID'),
|
||||
'norad_follow_id': _('Followed Norad ID'),
|
||||
'names': _('Other names'),
|
||||
'countries': _('Countries of Origin'),
|
||||
'launched': _('Launch Date'),
|
||||
|
@ -76,4 +78,28 @@ class SatelliteModelForm(BSModalModelForm):
|
|||
'dashboard_url': _('Dashboard URL'),
|
||||
'operator': _('Owner/Operator'),
|
||||
}
|
||||
widgets = {'norad_cat_id': NumberInput(attrs={'readonly': True}), 'names': TextInput()}
|
||||
widgets = {'names': TextInput()}
|
||||
|
||||
|
||||
class SatelliteUpdateForm(BSModalModelForm):
|
||||
"""Form that uses django-bootstrap-modal-forms for satellite editing"""
|
||||
class Meta:
|
||||
model = SatelliteEntry
|
||||
fields = [
|
||||
'norad_cat_id', 'norad_follow_id', 'name', 'names', 'description', 'operator',
|
||||
'status', 'countries', 'website', 'dashboard_url', 'launched', 'deployed', 'decayed',
|
||||
'image', 'citation'
|
||||
]
|
||||
labels = {
|
||||
'norad_cat_id': _('Norad ID'),
|
||||
'norad_follow_id': _('Followed Norad ID'),
|
||||
'names': _('Other names'),
|
||||
'countries': _('Countries of Origin'),
|
||||
'launched': _('Launch Date'),
|
||||
'deployed': _('Deploy Date'),
|
||||
'decayed': _('Re-entry Date'),
|
||||
'description': _('Description'),
|
||||
'dashboard_url': _('Dashboard URL'),
|
||||
'operator': _('Owner/Operator'),
|
||||
}
|
||||
widgets = {'names': TextInput()}
|
||||
|
|
|
@ -254,10 +254,13 @@ class Satellite(models.Model):
|
|||
last_modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return '{1} ({2}) | {0}'.format(
|
||||
self.satellite_identifier.sat_id, self.satellite_entry.name,
|
||||
self.satellite_entry.norad_cat_id
|
||||
)
|
||||
if self.satellite_entry:
|
||||
name = self.satellite_entry.name
|
||||
norad_cat_id = self.satellite_entry.norad_cat_id
|
||||
else:
|
||||
name = '-'
|
||||
norad_cat_id = '-'
|
||||
return '{1} ({2}) | {0}'.format(self.satellite_identifier.sat_id, name, norad_cat_id)
|
||||
|
||||
@property
|
||||
def transmitters(self):
|
||||
|
|
|
@ -28,6 +28,7 @@ BASE_URLPATTERNS = (
|
|||
path('users/edit/', views.users_edit, name='users_edit'),
|
||||
path(r'robots\.txt', views.robots, name='robots'),
|
||||
path('search/', views.search, name='search_results'),
|
||||
path('create_satellite/', views.SatelliteCreateView.as_view(), name='create_satellite'),
|
||||
path(
|
||||
'update_satellite/<int:pk>/',
|
||||
views.SatelliteUpdateView.as_view(),
|
||||
|
|
|
@ -19,10 +19,11 @@ from django.urls import reverse
|
|||
from django.utils.timezone import now
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
from db.base.forms import SatelliteModelForm, TransmitterModelForm, TransmitterUpdateForm
|
||||
from db.base.forms import SatelliteCreateForm, SatelliteUpdateForm, TransmitterCreateForm, \
|
||||
TransmitterUpdateForm
|
||||
from db.base.helpers import get_apikey
|
||||
from db.base.models import DemodData, Satellite, SatelliteEntry, Transmitter, TransmitterEntry, \
|
||||
TransmitterSuggestion
|
||||
from db.base.models import DemodData, Satellite, SatelliteEntry, SatelliteIdentifier, \
|
||||
Transmitter, TransmitterEntry, TransmitterSuggestion
|
||||
from db.base.tasks import export_frames, notify_suggestion
|
||||
from db.base.utils import cache_statistics, millify, read_influx
|
||||
|
||||
|
@ -353,7 +354,7 @@ class TransmitterCreateView(LoginRequiredMixin, BSModalCreateView):
|
|||
"""A django-bootstrap-modal-forms view for creating transmitter suggestions"""
|
||||
template_name = 'base/modals/transmitter_create.html'
|
||||
model = TransmitterEntry
|
||||
form_class = TransmitterModelForm
|
||||
form_class = TransmitterCreateForm
|
||||
success_message = 'Your transmitter suggestion was stored successfully and will be \
|
||||
reviewed by a moderator. Thanks for contibuting!'
|
||||
|
||||
|
@ -421,11 +422,63 @@ class TransmitterUpdateView(LoginRequiredMixin, BSModalUpdateView):
|
|||
return self.request.META.get('HTTP_REFERER')
|
||||
|
||||
|
||||
class SatelliteCreateView(LoginRequiredMixin, BSModalCreateView):
|
||||
"""A django-bootstrap-modal-forms view for creating satellite suggestions"""
|
||||
template_name = 'base/modals/satellite_create.html'
|
||||
model = SatelliteEntry
|
||||
form_class = SatelliteCreateForm
|
||||
success_message = 'Your satellite suggestion was stored successfully and will be \
|
||||
reviewed by a moderator. Thanks for contributing!'
|
||||
|
||||
user = get_user_model()
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.user = request.user
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
satellite_entry = form.instance
|
||||
satellite_obj = None
|
||||
# Create Satellite Identifier only when POST request is for saving and
|
||||
# NORAD ID is not used by other Satellite.
|
||||
if not self.request.is_ajax():
|
||||
try:
|
||||
satellite_obj = Satellite.objects.get(
|
||||
satellite_entry__norad_cat_id=satellite_entry.norad_cat_id
|
||||
)
|
||||
satellite_entry.satellite_identifier = satellite_obj.satellite_identifier
|
||||
except Satellite.DoesNotExist:
|
||||
satellite_entry.satellite_identifier = SatelliteIdentifier.objects.create()
|
||||
|
||||
satellite_entry.created = now()
|
||||
satellite_entry.created_by = self.user
|
||||
|
||||
# form_valid triggers also save() allowing us to use satellite_entry
|
||||
# for creating Satellite object, see comment bellow.
|
||||
response = super().form_valid(form)
|
||||
|
||||
# Prevents sending notification twice as form_valid is triggered for
|
||||
# validation and saving. Also create and Satellite object only when POST
|
||||
# request is for saving and NORAD ID is not used by other Satellite.
|
||||
if not self.request.is_ajax():
|
||||
if not satellite_obj:
|
||||
satellite_obj = Satellite.objects.create(
|
||||
satellite_identifier=satellite_entry.satellite_identifier,
|
||||
satellite_entry=satellite_entry
|
||||
)
|
||||
notify_suggestion.delay(satellite_obj.satellite_entry.pk, self.user.id, 'satellite')
|
||||
|
||||
return response
|
||||
|
||||
def get_success_url(self):
|
||||
return self.request.META.get('HTTP_REFERER')
|
||||
|
||||
|
||||
class SatelliteUpdateView(LoginRequiredMixin, BSModalUpdateView):
|
||||
"""A django-bootstrap-modal-forms view for updating satellite fields"""
|
||||
"""A django-bootstrap-modal-forms view for updating satellite entries"""
|
||||
template_name = 'base/modals/satellite_update.html'
|
||||
model = SatelliteEntry
|
||||
form_class = SatelliteModelForm
|
||||
form_class = SatelliteUpdateForm
|
||||
success_message = 'Your satellite suggestion was stored successfully and will be \
|
||||
reviewed by a moderator. Thanks for contributing!'
|
||||
|
||||
|
|
|
@ -33,6 +33,14 @@ $(document).ready(function() {
|
|||
pageLength: 50
|
||||
} );
|
||||
|
||||
// Create Satellite
|
||||
$('.create-satellite-link').each(function () {
|
||||
$(this).modalForm({
|
||||
formURL: $(this).data('form-url'),
|
||||
modalID: '#create-satellite-modal'
|
||||
});
|
||||
});
|
||||
|
||||
// Update Satellite
|
||||
$('.update-satellite-link').each(function () {
|
||||
$(this).modalForm({
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
{% load widget_tweaks %}
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
<form action="" method="post" id="satellite_create-form" enctype="multipart/form-data" >
|
||||
{% csrf_token %}
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Create Satellite</h3>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
|
||||
{% for error in form.non_field_errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% for field in form %}
|
||||
<div class="input-group my-1">
|
||||
<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 %}
|
||||
<div class="{% if field.errors %} invalid{% endif %}">
|
||||
{% for error in field.errors %}
|
||||
<p class="help-block">{{ error }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="submit-btn btn btn-satnogs-primary">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<div class="modal-body">
|
||||
<div class="text-danger">You need to login first to add a new transmitter suggestion.</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-outline-secondary" data-dismiss="modal">Close</button>
|
||||
<a href="{% url 'account_login' %}" class="btn btn-satnogs-primary">Log In</a>
|
||||
</div>
|
||||
{% endif %}
|
|
@ -11,7 +11,6 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
|
||||
{% for error in form.non_field_errors %}
|
||||
{{ error }}
|
||||
|
@ -66,4 +65,4 @@
|
|||
<button class="btn btn-outline-secondary" data-dismiss="modal">Close</button>
|
||||
<a href="{% url 'account_login' %}" class="btn btn-satnogs-primary">Log In</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
@ -13,6 +13,27 @@
|
|||
<span class="h4 mb-0 mr-3 text-truncate d-none d-md-block">Satellites</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block top-menu-right %}
|
||||
{% if request.user.is_authenticated %}
|
||||
<ul class="navbar-nav nav nav-pills" data-widget="treeview" role="menu" data-accordion="false" id="tabs" role="tablist">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false" aria-label="Edit Menu">
|
||||
<i class="nav-icon fas fa-edit"></i>
|
||||
<p class="d-none d-lg-inline-block text-sm">Edit</p>
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item d-flex align-items-center create-satellite-link" href="#" id="create-satellite-side"
|
||||
data-form-url="{% url 'create_satellite' %}" aria-label="Submit new satellite">
|
||||
<i class="nav-icon mr-2 fas fa-plus-square"></i>
|
||||
<p class="mb-0">Submit New Satellite</p>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block top %}
|
||||
<span class="h4 mb-0">Satellites</span>
|
||||
{% endblock %}
|
||||
|
@ -66,7 +87,7 @@
|
|||
</td>
|
||||
<td>{{ sat.satellite_entry.names|upper }}</td>
|
||||
<td>{{ sat.approved_transmitters|length }}</td>
|
||||
<td>{{ sat.satellite_entry.norad_follow_id }}</a></td>
|
||||
<td>{{ sat.satellite_entry.norad_follow_id }}</td>
|
||||
<td>{{ sat.satellite_entry.operator }}</td>
|
||||
<td>{{ sat.satellite_entry.launched }}</td>
|
||||
<td>{{ sat.satellite_entry.website }}</td>
|
||||
|
@ -76,6 +97,7 @@
|
|||
<td><button type="button" class="update-satellite-link btn btn-sm btn-satnogs-primary"
|
||||
data-form-url="{% url 'update_satellite' sat.satellite_entry.id %}">
|
||||
<span class="fa fa-edit"></span>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
@ -83,14 +105,21 @@
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Satellite update modal -->
|
||||
<!-- django-bootstrap-modal-forms modals -->
|
||||
{% if request.user.is_authenticated %}
|
||||
<div class="modal fade" id="create-satellite-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="update-satellite-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -108,6 +108,8 @@
|
|||
<i class="fas fa-search"></i> UHF Amateur</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
{% if transmitter.downlink_drift %}
|
||||
<dt class="col-sm-6">Downlink Drifted</dt>
|
||||
<dd class="col-sm-6" data-toggle="tooltip" data-placement="bottom" title="{{ transmitter.downlink_drift }} ppb">
|
||||
<span class="frequency drifted" data-freq_or="{{ transmitter.downlink_low }}" data-drift="{{ transmitter.downlink_drift }}">{{ transmitter.downlink_drift }}</dd>
|
||||
<span class="frequency drifted" data-freq_or="{{ transmitter.downlink_low }}" data-drift="{{ transmitter.downlink_drift }}">{{ transmitter.downlink_drift }}</span></dd>
|
||||
{% endif %}
|
||||
{% if transmitter.baud %}
|
||||
<dt class="col-sm-6">Baud</dt>
|
||||
|
@ -97,22 +97,22 @@
|
|||
{% if transmitter.downlink_high %}
|
||||
<dt class="col-sm-6">Downlink High</dt>
|
||||
<dd class="col-sm-6" data-toggle="tooltip" data-placement="bottom" title="{{ transmitter.downlink_high }}">
|
||||
<span class="frequency">{{ transmitter.downlink_high }}</dd>
|
||||
<span class="frequency">{{ transmitter.downlink_high }}</span></dd>
|
||||
{% endif %}
|
||||
{% if transmitter.uplink_low %}
|
||||
<dt class="col-sm-6">Uplink Frequency</dt>
|
||||
<dd class="col-sm-6" data-toggle="tooltip" data-placement="bottom" title="{{ transmitter.uplink_low }}">
|
||||
<span class="frequency">{{ transmitter.uplink_low }}</dd>
|
||||
<span class="frequency">{{ transmitter.uplink_low }}</span></dd>
|
||||
{% endif %}
|
||||
{% if transmitter.uplink_drift %}
|
||||
<dt class="col-sm-6">Uplink Drift</dt>
|
||||
<dd class="col-sm-6" data-toggle="tooltip" data-placement="bottom" title="{{ transmitter.uplink_drift }} ppb">
|
||||
<span class="frequency drifted" data-freq_or="{{ transmitter.uplink_low }}" data-drift="{{ transmitter.uplink_drift }}">{{ transmitter.uplink_drift }}</dd>
|
||||
<span class="frequency drifted" data-freq_or="{{ transmitter.uplink_low }}" data-drift="{{ transmitter.uplink_drift }}">{{ transmitter.uplink_drift }}</span></dd>
|
||||
{% endif %}
|
||||
{% if transmitter.uplink_high %}
|
||||
<dt class="col-sm-6">Uplink High</dt>
|
||||
<dd class="col-sm-6" data-toggle="tooltip" data-placement="bottom" title="{{ transmitter.uplink_high }}">
|
||||
<span class="frequency">{{ transmitter.uplink_high }}</dd>
|
||||
<span class="frequency">{{ transmitter.uplink_high }}</span></dd>
|
||||
{% endif %}
|
||||
{% if transmitter.invert %}
|
||||
<dt class="col-sm-6">Inverted</dt>
|
||||
|
@ -142,23 +142,23 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Citation Modal -->
|
||||
<div class="modal fade" id="TransmitterCitation-{{ transmitter.id }}" tabindex="-1" role="dialog"
|
||||
aria-labelledby="CitationModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="CitationModalLabel">Citation for {{ transmitter.uuid }}</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ transmitter.citation }}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Close</button>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="CitationModalLabel">Citation for {{ transmitter.uuid }}</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||
aria-hidden="true">×</span></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ transmitter.citation }}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue