Merge branch 'async-load-predictions' into 'dev'
Load satellite predictions asynchronously See merge request librespacefoundation/satnogs/satnogs-network!450environments/stage/deployments/60
commit
ecb38787e0
|
@ -22,6 +22,8 @@ base_urlpatterns = ([
|
|||
url(r'^prediction_windows/(?P<sat_id>[\w.@+-]+)/(?P<transmitter>[\w.@+-]+)/'
|
||||
'(?P<start_date>.+)/(?P<end_date>.+)/$',
|
||||
views.prediction_windows, name='prediction_windows'),
|
||||
url(r'^pass_predictions/(?P<id>[\w.@+-]+)/$',
|
||||
views.pass_predictions, name='pass_predictions'),
|
||||
url(r'^observation_vet_good/(?P<id>[0-9]+)/$', views.observation_vet_good,
|
||||
name='observation_vet_good'),
|
||||
url(r'^observation_vet_bad/(?P<id>[0-9]+)/$', views.observation_vet_bad,
|
||||
|
|
|
@ -540,6 +540,22 @@ def station_view(request, id):
|
|||
rigs = Rig.objects.all()
|
||||
unsupported_frequencies = request.GET.get('unsupported_frequencies', '0')
|
||||
|
||||
can_schedule = schedule_perms(request.user)
|
||||
|
||||
return render(request, 'base/station_view.html',
|
||||
{'station': station, 'form': form, 'antennas': antennas,
|
||||
'mapbox_id': settings.MAPBOX_MAP_ID,
|
||||
'mapbox_token': settings.MAPBOX_TOKEN,
|
||||
'rigs': rigs, 'can_schedule': can_schedule,
|
||||
'unsupported_frequencies': unsupported_frequencies})
|
||||
|
||||
|
||||
@ajax_required
|
||||
def pass_predictions(request, id):
|
||||
"""Endpoint for pass predictions"""
|
||||
station = get_object_or_404(Station, id=id)
|
||||
unsupported_frequencies = request.GET.get('unsupported_frequencies', '0')
|
||||
|
||||
try:
|
||||
satellites = Satellite.objects.filter(transmitters__alive=True) \
|
||||
.filter(status='alive').distinct()
|
||||
|
@ -622,7 +638,6 @@ def station_view(request, id):
|
|||
ts.datetime(), 10)
|
||||
sat_pass = {'passid': passid,
|
||||
'mytime': str(observer.date),
|
||||
'debug': observer.next_pass(sat_ephem),
|
||||
'name': str(satellite.name),
|
||||
'id': str(satellite.id),
|
||||
'success_rate': str(satellite.success_rate),
|
||||
|
@ -635,7 +650,7 @@ def station_view(request, id):
|
|||
'norad_cat_id': str(satellite.norad_cat_id),
|
||||
'tr': tr.datetime(), # Rise time
|
||||
'azr': azimuth_r, # Rise Azimuth
|
||||
'tt': tt, # Max altitude time
|
||||
'tt': tt.datetime(), # Max altitude time
|
||||
'altt': elevation, # Max altitude
|
||||
'ts': ts.datetime(), # Set time
|
||||
'azs': azimuth_s, # Set azimuth
|
||||
|
@ -646,15 +661,12 @@ def station_view(request, id):
|
|||
else:
|
||||
keep_digging = False
|
||||
|
||||
can_schedule = schedule_perms(request.user)
|
||||
data = {
|
||||
'id': id,
|
||||
'nextpasses': sorted(nextpasses, key=itemgetter('tr'))
|
||||
}
|
||||
|
||||
return render(request, 'base/station_view.html',
|
||||
{'station': station, 'form': form, 'antennas': antennas,
|
||||
'mapbox_id': settings.MAPBOX_MAP_ID,
|
||||
'mapbox_token': settings.MAPBOX_TOKEN,
|
||||
'nextpasses': sorted(nextpasses, key=itemgetter('tr')),
|
||||
'rigs': rigs, 'can_schedule': can_schedule,
|
||||
'unsupported_frequencies': unsupported_frequencies})
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
|
||||
@require_POST
|
||||
|
|
|
@ -351,6 +351,49 @@ span.datetime-time {
|
|||
background-color: #072;
|
||||
}
|
||||
|
||||
/* Station
|
||||
==================== */
|
||||
|
||||
#loading-image {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
margin: 50px auto 0;
|
||||
width: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.spinner > div {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-color: #666;
|
||||
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
|
||||
}
|
||||
|
||||
.spinner .bounce1 {
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.spinner .bounce2 {
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
@keyframes sk-bouncedelay {
|
||||
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Observations
|
||||
==================== */
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
$(document).ready(function() {
|
||||
/* exported polarplot */
|
||||
|
||||
function polarplot() {
|
||||
'use strict';
|
||||
|
||||
function drawPolarPlot(canvas, data) {
|
||||
|
@ -89,4 +91,4 @@ $(document).ready(function() {
|
|||
var $this = $(this);
|
||||
drawPolarPlot($this.get(0), $this.data().points);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* global mapboxgl */
|
||||
/* global mapboxgl, polarplot, moment */
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
$(document).ready(function() {
|
||||
'use strict';
|
||||
|
@ -25,9 +26,7 @@ $(document).ready(function() {
|
|||
|
||||
// Init the map
|
||||
var mapboxtoken = $('div#map-station').data('mapboxtoken');
|
||||
|
||||
mapboxgl.accessToken = mapboxtoken;
|
||||
|
||||
var map = new mapboxgl.Map({
|
||||
container: 'map-station',
|
||||
style: 'mapbox://styles/pierros/cj8kftshl4zll2slbelhkndwo',
|
||||
|
@ -35,15 +34,11 @@ $(document).ready(function() {
|
|||
minZoom: 2,
|
||||
center: [parseFloat(station_info.lng),parseFloat(station_info.lat)]
|
||||
});
|
||||
|
||||
map.addControl(new mapboxgl.NavigationControl());
|
||||
|
||||
map.on('load', function () {
|
||||
|
||||
map.loadImage('/static/img/pin.png', function(error, image) {
|
||||
map.addImage('pin', image);
|
||||
});
|
||||
|
||||
var map_points = {
|
||||
'id': 'points',
|
||||
'type': 'symbol',
|
||||
|
@ -72,7 +67,6 @@ $(document).ready(function() {
|
|||
'icon-allow-overlap': true
|
||||
}
|
||||
};
|
||||
|
||||
map.addLayer(map_points);
|
||||
map.repaint = true;
|
||||
});
|
||||
|
@ -97,4 +91,88 @@ $(document).ready(function() {
|
|||
$('#antenna-filter input[type=checkbox]').change(function() {
|
||||
$('#antenna-filter').submit();
|
||||
});
|
||||
|
||||
// Pass predictions loading
|
||||
$('#loading-image').show();
|
||||
$.ajax({
|
||||
url: '/pass_predictions/' + $('#station-info').attr('data-id'),
|
||||
cache: false,
|
||||
success: function(data){
|
||||
var len = data.nextpasses.length - 1;
|
||||
var new_obs = $('#station-info').attr('data-new-obs');
|
||||
var station = $('#station-info').attr('data-id');
|
||||
var station_online = $('#station-info').data('online');
|
||||
var station_active = $('#station-info').data('active');
|
||||
var can_schedule = $('#station-info').data('schedule');
|
||||
for (var i = 0; i <= len; i++) {
|
||||
var schedulable = data.nextpasses[i].valid && station_online && station_active && can_schedule;
|
||||
var json_polar_data = JSON.stringify(data.nextpasses[i].polar_data);
|
||||
var tr = moment(data.nextpasses[i].tr).format('YYYY/MM/DD HH:mm');
|
||||
var ts = moment(data.nextpasses[i].ts).format('YYYY/MM/DD HH:mm');
|
||||
var tr_display_date = moment(data.nextpasses[i].tr).format('YYYY-MM-DD');
|
||||
var tr_display_time = moment(data.nextpasses[i].tr).format('HH:mm');
|
||||
var ts_display_date = moment(data.nextpasses[i].ts).format('YYYY-MM-DD');
|
||||
var ts_display_time = moment(data.nextpasses[i].ts).format('HH:mm');
|
||||
$('#pass_predictions').append(`
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#" data-toggle="modal" data-target="#SatelliteModal" data-id="${data.nextpasses[i].norad_cat_id}">
|
||||
${data.nextpasses[i].norad_cat_id} - ${data.nextpasses[i].name}
|
||||
</a>
|
||||
<div class="progress satellite-success">
|
||||
<div class="progress-bar progress-bar-success" style="width: ${data.nextpasses[i].success_rate}%"
|
||||
data-toggle="tooltip" data-placement="bottom" title="${data.nextpasses[i].success_rate}% (${data.nextpasses[i].verified_count}) Verified">
|
||||
<span class="sr-only">${data.nextpasses[i].success_rate}% Verified</span>
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-warning" style="width: ${data.nextpasses[i].unknown_rate}%"
|
||||
data-toggle="tooltip" data-placement="bottom" title="${data.nextpasses[i].unknown_rate}% (${data.nextpasses[i].unknown_count}) Unknown">
|
||||
<span class="sr-only">${data.nextpasses[i].unknown_rate}% Unknown</span>
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-danger" style="width: ${data.nextpasses[i].empty_rate}%"
|
||||
data-toggle="tooltip" data-placement="bottom" title="${data.nextpasses[i].empty_rate}% (${data.nextpasses[i].empty_count}) Empty">
|
||||
<span class="sr-only">${data.nextpasses[i].empty_rate}% Empty</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="datetime-date">${tr_display_date}</span>
|
||||
<span class="datetime-time">${tr_display_time}</span><br>
|
||||
<span class="datetime-date">${ts_display_date}</span>
|
||||
<span class="datetime-time">${ts_display_time}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="lightgreen">⤉</span>${data.nextpasses[i].azr}°
|
||||
</td>
|
||||
<td>
|
||||
⇴${data.nextpasses[i].altt}°
|
||||
</td>
|
||||
<td>
|
||||
<span class="red">⤈</span>${data.nextpasses[i].azs}°
|
||||
</td>
|
||||
<td>
|
||||
<canvas class="polar-plot" width="100" height="100" data-points="${json_polar_data}"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
${schedulable ? `<a href="${new_obs}?norad=${data.nextpasses[i].norad_cat_id}&ground_station=${station}&start_date=${tr}&end_date=${ts}"
|
||||
class="btn btn-default"
|
||||
target="_blank">
|
||||
schedule
|
||||
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
|
||||
</a>
|
||||
` : `
|
||||
<a class="btn btn-default" disabled>
|
||||
schedule
|
||||
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
|
||||
</a>
|
||||
`}
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
}
|
||||
polarplot();
|
||||
},
|
||||
complete: function(){
|
||||
$('#loading-image').hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,7 +16,11 @@
|
|||
data-name="{{ station.name }}"
|
||||
data-id="{{ station.id }}"
|
||||
data-lng="{{ station.lng }}"
|
||||
data-lat="{{ station.lat }}">
|
||||
data-lat="{{ station.lat }}"
|
||||
data-online="{{ station.online|yesno:"true,false" }}"
|
||||
data-active="{{ station.active|yesno:"true,false" }}"
|
||||
data-schedule="{{ can_schedule|yesno:"true,false" }}"
|
||||
data-new-obs="{% url 'base:observation_new' %}">
|
||||
{{ station.id }} - {{ station.name }}
|
||||
</h2>
|
||||
</div>
|
||||
|
@ -198,63 +202,17 @@
|
|||
<th>Polar</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for nextpass in nextpasses %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#" data-toggle="modal" data-target="#SatelliteModal" data-id="{{ nextpass.norad_cat_id }}">
|
||||
{{ nextpass.norad_cat_id }} - {{ nextpass.name }}
|
||||
</a>
|
||||
<div class="progress satellite-success">
|
||||
<div class="progress-bar progress-bar-success" style="width: {{ nextpass.success_rate }}%"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ nextpass.success_rate }}% ({{ nextpass.verified_count }}) Verified">
|
||||
<span class="sr-only">{{ nextpass.success_rate }}% Verified</span>
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-warning" style="width: {{ nextpass.unknown_rate }}%"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ nextpass.unknown_rate }}% ({{ nextpass.unknown_count }}) Unknown">
|
||||
<span class="sr-only">{{ nextpass.unknown_rate }}% Unknown</span>
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-danger" style="width: {{ nextpass.empty_rate }}%"
|
||||
data-toggle="tooltip" data-placement="bottom" title="{{ nextpass.empty_rate }}% ({{ nextpass.empty_count }}) Empty">
|
||||
<span class="sr-only">{{ nextpass.empty_rate }}% Empty</span>
|
||||
</div>
|
||||
<tbody id="pass_predictions" station-online="{{ station.online }}" station-active="{{ station.active }}" can_schedule="{{ can_schedule }}">
|
||||
<tr id="loading-image">
|
||||
<td colspan=7>
|
||||
<div class="spinner">
|
||||
<div class="bounce1"></div>
|
||||
<div class="bounce2"></div>
|
||||
<div class="bounce3"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="datetime-date">{{ nextpass.tr|date:"Y-m-d" }}</span>
|
||||
<span class="datetime-time">{{ nextpass.tr|date:"H:i:s" }}</span><br>
|
||||
<span class="datetime-date">{{ nextpass.ts|date:"Y-m-d" }}</span>
|
||||
<span class="datetime-time">{{ nextpass.ts|date:"H:i:s" }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="lightgreen">⤉</span>{{ nextpass.azr }}°
|
||||
</td>
|
||||
<td>
|
||||
⇴{{ nextpass.altt }}°
|
||||
</td>
|
||||
<td>
|
||||
<span class="red">⤈</span>{{ nextpass.azs }}°
|
||||
</td>
|
||||
<td>
|
||||
<canvas class="polar-plot" width="100" height="100" data-points="{{ nextpass.polar_data }}"></canvas>
|
||||
</td>
|
||||
<td>
|
||||
{% if nextpass.valid and station.online and station.active and can_schedule %}
|
||||
<a href="{% url 'base:observation_new' %}?norad={{ nextpass.norad_cat_id }}&ground_station={{ station.id }}&start_date={{ nextpass.tr|date:"Y/m/d H:i" }}&end_date={{ nextpass.ts|date:"Y/m/d H:i" }}"
|
||||
class="btn btn-default"
|
||||
target="_blank">
|
||||
schedule
|
||||
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="btn btn-default" disabled>
|
||||
schedule
|
||||
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
Loading Pass Predictions
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -271,8 +229,9 @@
|
|||
{% block javascript %}
|
||||
<script src="{% static 'lib/urijs/src/URI.min.js' %}"></script>
|
||||
<script src="{% static 'lib/mapbox-gl/dist/mapbox-gl.js' %}"></script>
|
||||
<script src="{% static 'lib/moment/min/moment.min.js' %}"></script>
|
||||
<script src="{% static 'js/polar.js' %}"></script>
|
||||
<script src="{% static 'js/station_view.js' %}"></script>
|
||||
<script src="{% static 'js/gridsquare.js' %}"></script>
|
||||
<script src="{% static 'js/satellite.js' %}"></script>
|
||||
<script src="{% static 'js/polar.js' %}"></script>
|
||||
{% endblock javascript %}
|
||||
|
|
Loading…
Reference in New Issue