Added Bootstrap and Navigation

pull/68/head
Konstantin Gründger 2019-02-10 14:00:35 +01:00
rodzic 7e9003947e
commit 28395c6426
17 zmienionych plików z 733 dodań i 6 usunięć

Wyświetl plik

@ -1,7 +1,13 @@
from flask import Flask
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from navigation import nav
app = Flask(__name__)
app.config.from_object('config.default')
bootstrap = Bootstrap(app)
db = SQLAlchemy(app)
nav.init_app(app)

14
ogn/navigation.py 100644
Wyświetl plik

@ -0,0 +1,14 @@
from flask_nav import Nav
from flask_nav.elements import *
nav = Nav()
# registers the "top" menubar
nav.register_element('top_menubar', Navbar(
View('Home', 'index'),
View('Devices', 'devices'),
View('Receivers', 'receivers'),
View('Airports', 'airports'),
View('Logbook', 'logbook'),
View('Records', 'records'),
))

Wyświetl plik

@ -1,12 +1,128 @@
from flask import request, render_template
from ogn import app
from ogn import db
from ogn.model import *
@app.route('/')
def index():
return "WTF"
@app.route('/test')
def test():
return db.session.query(Device).first().address
@app.route('/')
@app.route('/index')
def index():
return render_template('base.html')
@app.route('/devices', methods=['GET', 'POST'])
def devices():
device_id = request.args.get('id')
if device_id:
device = db.session.query(Device) \
.filter(Device.id == device_id)
return render_template('device_detail.html', device=device)
else:
devices = db.session.query(Device) \
.limit(100)
return render_template('devices.html', devices=devices)
@app.route('/receivers')
def receivers():
receivers = db.session.query(Receiver) \
.filter(Receiver.country != db.null()) \
.order_by(Receiver.name)
return render_template('receivers.html', receivers=receivers)
@app.route('/airports')
def airports():
page = request.args.get('page', 1, type=int)
pagination = db.session.query(Airport) \
.order_by(Airport.name) \
.paginate(page, 20, False)
return render_template('airports.html', pagination=pagination)
@app.route('/logbook', methods=['GET', 'POST'])
def logbook():
sel_country = request.args.get('country')
sel_airport = request.args.get('airport')
sel_date = request.args.get('date')
sel_device_id = request.args.get('device_id')
airport_ids_in_logbook = db.session.query(db.distinct(Logbook.takeoff_airport_id).label('id')) \
.subquery()
airports_in_logbook = db.session.query(Airport) \
.filter(Airport.id == airport_ids_in_logbook.c.id) \
.subquery()
country_ids_in_logbook = db.session.query(db.distinct(Country.gid).label('id')) \
.filter(Country.iso2 == airports_in_logbook.c.country_code) \
.subquery()
countries_avail = db.session.query(Country) \
.filter(Country.gid == country_ids_in_logbook.c.id) \
.order_by(Country.iso2)
# Get airport selection list
if sel_country:
airports = db.session.query(Airport) \
.filter(Airport.id == airport_ids_in_logbook.c.id) \
.filter(Airport.country_code == sel_country) \
.order_by(Airport.name)
else:
airports = ['']
# Get date selection list
if sel_country and sel_airport:
dates = db.session.query(db.func.date(Logbook.reftime), db.func.count(Logbook.id)) \
.filter(db.or_(Logbook.takeoff_airport_id == sel_airport,
Logbook.landing_airport_id == sel_airport)) \
.group_by(db.func.date(Logbook.reftime)) \
.order_by(db.func.date(Logbook.reftime))
else:
dates = ['']
# Get Logbook
filters = []
if sel_date:
filters.append(db.func.date(Logbook.reftime) == sel_date)
if sel_country and sel_airport:
filters.append(db.or_(Logbook.takeoff_airport_id == sel_airport, Logbook.landing_airport_id == sel_airport))
if sel_device_id:
filters.append(Logbook.device_id == sel_device_id)
if len(filters) > 0:
logbook = db.session.query(Logbook.takeoff_timestamp,
db.func.round(Logbook.takeoff_track/10).label('takeoff_track'),
Logbook.landing_timestamp,
db.func.round(Logbook.landing_track/10).label('landing_track'),
Logbook.max_altitude,
DeviceInfo.aircraft,
DeviceInfo.registration,
DeviceInfo.competition) \
.filter(*filters) \
.filter(db.and_(Logbook.device_id == Device.id, Device.address == DeviceInfo.address)) \
.order_by(Logbook.reftime)
else:
logbook = None
return render_template('logbook.html', sel_country=sel_country, countries=countries_avail, sel_airport=sel_airport, airports=airports, sel_date=sel_date, dates=dates, logbook=logbook)
@app.route('/live')
def live():
return render_template('ogn_live.jinja')
@app.route('/records')
def records():
receiverstats = db.session.query(ReceiverStats) \
.limit(10)
return render_template('records.html', receiverstats=receiverstats)

Wyświetl plik

@ -0,0 +1,11 @@
License
FamFamFam flag icons are "available for free use for any purpose with no requirement for attribution"
Blogpotato.de flag icons are licensed under Creative Commons
Author and license terms for Maxmind icon set are unknown.
- See more at: https://www.flag-sprites.com/en_US/#sthash.cOJO8GvT.dpuf

Wyświetl plik

@ -0,0 +1,259 @@
.flag {
width: 16px;
height: 11px;
background:url(flags.png) no-repeat
}
.flag.flag-ad {background-position: -16px 0}
.flag.flag-ae {background-position: -32px 0}
.flag.flag-af {background-position: -48px 0}
.flag.flag-ag {background-position: -64px 0}
.flag.flag-ai {background-position: -80px 0}
.flag.flag-al {background-position: -96px 0}
.flag.flag-am {background-position: -112px 0}
.flag.flag-an {background-position: -128px 0}
.flag.flag-ao {background-position: -144px 0}
.flag.flag-ar {background-position: -160px 0}
.flag.flag-as {background-position: -176px 0}
.flag.flag-at {background-position: -192px 0}
.flag.flag-au {background-position: -208px 0}
.flag.flag-aw {background-position: -224px 0}
.flag.flag-az {background-position: -240px 0}
.flag.flag-ba {background-position: 0 -11px}
.flag.flag-bb {background-position: -16px -11px}
.flag.flag-bd {background-position: -32px -11px}
.flag.flag-be {background-position: -48px -11px}
.flag.flag-bf {background-position: -64px -11px}
.flag.flag-bg {background-position: -80px -11px}
.flag.flag-bh {background-position: -96px -11px}
.flag.flag-bi {background-position: -112px -11px}
.flag.flag-bj {background-position: -128px -11px}
.flag.flag-bm {background-position: -144px -11px}
.flag.flag-bn {background-position: -160px -11px}
.flag.flag-bo {background-position: -176px -11px}
.flag.flag-br {background-position: -192px -11px}
.flag.flag-bs {background-position: -208px -11px}
.flag.flag-bt {background-position: -224px -11px}
.flag.flag-bv {background-position: -240px -11px}
.flag.flag-bw {background-position: 0 -22px}
.flag.flag-by {background-position: -16px -22px}
.flag.flag-bz {background-position: -32px -22px}
.flag.flag-ca {background-position: -48px -22px}
.flag.flag-catalonia {background-position: -64px -22px}
.flag.flag-cd {background-position: -80px -22px}
.flag.flag-cf {background-position: -96px -22px}
.flag.flag-cg {background-position: -112px -22px}
.flag.flag-ch {background-position: -128px -22px}
.flag.flag-ci {background-position: -144px -22px}
.flag.flag-ck {background-position: -160px -22px}
.flag.flag-cl {background-position: -176px -22px}
.flag.flag-cm {background-position: -192px -22px}
.flag.flag-cn {background-position: -208px -22px}
.flag.flag-co {background-position: -224px -22px}
.flag.flag-cr {background-position: -240px -22px}
.flag.flag-cu {background-position: 0 -33px}
.flag.flag-cv {background-position: -16px -33px}
.flag.flag-cw {background-position: -32px -33px}
.flag.flag-cy {background-position: -48px -33px}
.flag.flag-cz {background-position: -64px -33px}
.flag.flag-de {background-position: -80px -33px}
.flag.flag-dj {background-position: -96px -33px}
.flag.flag-dk {background-position: -112px -33px}
.flag.flag-dm {background-position: -128px -33px}
.flag.flag-do {background-position: -144px -33px}
.flag.flag-dz {background-position: -160px -33px}
.flag.flag-ec {background-position: -176px -33px}
.flag.flag-ee {background-position: -192px -33px}
.flag.flag-eg {background-position: -208px -33px}
.flag.flag-eh {background-position: -224px -33px}
.flag.flag-england {background-position: -240px -33px}
.flag.flag-er {background-position: 0 -44px}
.flag.flag-es {background-position: -16px -44px}
.flag.flag-et {background-position: -32px -44px}
.flag.flag-eu {background-position: -48px -44px}
.flag.flag-fi {background-position: -64px -44px}
.flag.flag-fj {background-position: -80px -44px}
.flag.flag-fk {background-position: -96px -44px}
.flag.flag-fm {background-position: -112px -44px}
.flag.flag-fo {background-position: -128px -44px}
.flag.flag-fr {background-position: -144px -44px}
.flag.flag-ga {background-position: -160px -44px}
.flag.flag-gb {background-position: -176px -44px}
.flag.flag-gd {background-position: -192px -44px}
.flag.flag-ge {background-position: -208px -44px}
.flag.flag-gf {background-position: -224px -44px}
.flag.flag-gg {background-position: -240px -44px}
.flag.flag-gh {background-position: 0 -55px}
.flag.flag-gi {background-position: -16px -55px}
.flag.flag-gl {background-position: -32px -55px}
.flag.flag-gm {background-position: -48px -55px}
.flag.flag-gn {background-position: -64px -55px}
.flag.flag-gp {background-position: -80px -55px}
.flag.flag-gq {background-position: -96px -55px}
.flag.flag-gr {background-position: -112px -55px}
.flag.flag-gs {background-position: -128px -55px}
.flag.flag-gt {background-position: -144px -55px}
.flag.flag-gu {background-position: -160px -55px}
.flag.flag-gw {background-position: -176px -55px}
.flag.flag-gy {background-position: -192px -55px}
.flag.flag-hk {background-position: -208px -55px}
.flag.flag-hm {background-position: -224px -55px}
.flag.flag-hn {background-position: -240px -55px}
.flag.flag-hr {background-position: 0 -66px}
.flag.flag-ht {background-position: -16px -66px}
.flag.flag-hu {background-position: -32px -66px}
.flag.flag-ic {background-position: -48px -66px}
.flag.flag-id {background-position: -64px -66px}
.flag.flag-ie {background-position: -80px -66px}
.flag.flag-il {background-position: -96px -66px}
.flag.flag-im {background-position: -112px -66px}
.flag.flag-in {background-position: -128px -66px}
.flag.flag-io {background-position: -144px -66px}
.flag.flag-iq {background-position: -160px -66px}
.flag.flag-ir {background-position: -176px -66px}
.flag.flag-is {background-position: -192px -66px}
.flag.flag-it {background-position: -208px -66px}
.flag.flag-je {background-position: -224px -66px}
.flag.flag-jm {background-position: -240px -66px}
.flag.flag-jo {background-position: 0 -77px}
.flag.flag-jp {background-position: -16px -77px}
.flag.flag-ke {background-position: -32px -77px}
.flag.flag-kg {background-position: -48px -77px}
.flag.flag-kh {background-position: -64px -77px}
.flag.flag-ki {background-position: -80px -77px}
.flag.flag-km {background-position: -96px -77px}
.flag.flag-kn {background-position: -112px -77px}
.flag.flag-kp {background-position: -128px -77px}
.flag.flag-kr {background-position: -144px -77px}
.flag.flag-kurdistan {background-position: -160px -77px}
.flag.flag-kw {background-position: -176px -77px}
.flag.flag-ky {background-position: -192px -77px}
.flag.flag-kz {background-position: -208px -77px}
.flag.flag-la {background-position: -224px -77px}
.flag.flag-lb {background-position: -240px -77px}
.flag.flag-lc {background-position: 0 -88px}
.flag.flag-li {background-position: -16px -88px}
.flag.flag-lk {background-position: -32px -88px}
.flag.flag-lr {background-position: -48px -88px}
.flag.flag-ls {background-position: -64px -88px}
.flag.flag-lt {background-position: -80px -88px}
.flag.flag-lu {background-position: -96px -88px}
.flag.flag-lv {background-position: -112px -88px}
.flag.flag-ly {background-position: -128px -88px}
.flag.flag-ma {background-position: -144px -88px}
.flag.flag-mc {background-position: -160px -88px}
.flag.flag-md {background-position: -176px -88px}
.flag.flag-me {background-position: -192px -88px}
.flag.flag-mg {background-position: -208px -88px}
.flag.flag-mh {background-position: -224px -88px}
.flag.flag-mk {background-position: -240px -88px}
.flag.flag-ml {background-position: 0 -99px}
.flag.flag-mm {background-position: -16px -99px}
.flag.flag-mn {background-position: -32px -99px}
.flag.flag-mo {background-position: -48px -99px}
.flag.flag-mp {background-position: -64px -99px}
.flag.flag-mq {background-position: -80px -99px}
.flag.flag-mr {background-position: -96px -99px}
.flag.flag-ms {background-position: -112px -99px}
.flag.flag-mt {background-position: -128px -99px}
.flag.flag-mu {background-position: -144px -99px}
.flag.flag-mv {background-position: -160px -99px}
.flag.flag-mw {background-position: -176px -99px}
.flag.flag-mx {background-position: -192px -99px}
.flag.flag-my {background-position: -208px -99px}
.flag.flag-mz {background-position: -224px -99px}
.flag.flag-na {background-position: -240px -99px}
.flag.flag-nc {background-position: 0 -110px}
.flag.flag-ne {background-position: -16px -110px}
.flag.flag-nf {background-position: -32px -110px}
.flag.flag-ng {background-position: -48px -110px}
.flag.flag-ni {background-position: -64px -110px}
.flag.flag-nl {background-position: -80px -110px}
.flag.flag-no {background-position: -96px -110px}
.flag.flag-np {background-position: -112px -110px}
.flag.flag-nr {background-position: -128px -110px}
.flag.flag-nu {background-position: -144px -110px}
.flag.flag-nz {background-position: -160px -110px}
.flag.flag-om {background-position: -176px -110px}
.flag.flag-pa {background-position: -192px -110px}
.flag.flag-pe {background-position: -208px -110px}
.flag.flag-pf {background-position: -224px -110px}
.flag.flag-pg {background-position: -240px -110px}
.flag.flag-ph {background-position: 0 -121px}
.flag.flag-pk {background-position: -16px -121px}
.flag.flag-pl {background-position: -32px -121px}
.flag.flag-pm {background-position: -48px -121px}
.flag.flag-pn {background-position: -64px -121px}
.flag.flag-pr {background-position: -80px -121px}
.flag.flag-ps {background-position: -96px -121px}
.flag.flag-pt {background-position: -112px -121px}
.flag.flag-pw {background-position: -128px -121px}
.flag.flag-py {background-position: -144px -121px}
.flag.flag-qa {background-position: -160px -121px}
.flag.flag-re {background-position: -176px -121px}
.flag.flag-ro {background-position: -192px -121px}
.flag.flag-rs {background-position: -208px -121px}
.flag.flag-ru {background-position: -224px -121px}
.flag.flag-rw {background-position: -240px -121px}
.flag.flag-sa {background-position: 0 -132px}
.flag.flag-sb {background-position: -16px -132px}
.flag.flag-sc {background-position: -32px -132px}
.flag.flag-scotland {background-position: -48px -132px}
.flag.flag-sd {background-position: -64px -132px}
.flag.flag-se {background-position: -80px -132px}
.flag.flag-sg {background-position: -96px -132px}
.flag.flag-sh {background-position: -112px -132px}
.flag.flag-si {background-position: -128px -132px}
.flag.flag-sk {background-position: -144px -132px}
.flag.flag-sl {background-position: -160px -132px}
.flag.flag-sm {background-position: -176px -132px}
.flag.flag-sn {background-position: -192px -132px}
.flag.flag-so {background-position: -208px -132px}
.flag.flag-somaliland {background-position: -224px -132px}
.flag.flag-sr {background-position: -240px -132px}
.flag.flag-ss {background-position: 0 -143px}
.flag.flag-st {background-position: -16px -143px}
.flag.flag-sv {background-position: -32px -143px}
.flag.flag-sx {background-position: -48px -143px}
.flag.flag-sy {background-position: -64px -143px}
.flag.flag-sz {background-position: -80px -143px}
.flag.flag-tc {background-position: -96px -143px}
.flag.flag-td {background-position: -112px -143px}
.flag.flag-tf {background-position: -128px -143px}
.flag.flag-tg {background-position: -144px -143px}
.flag.flag-th {background-position: -160px -143px}
.flag.flag-tibet {background-position: -176px -143px}
.flag.flag-tj {background-position: -192px -143px}
.flag.flag-tk {background-position: -208px -143px}
.flag.flag-tl {background-position: -224px -143px}
.flag.flag-tm {background-position: -240px -143px}
.flag.flag-tn {background-position: 0 -154px}
.flag.flag-to {background-position: -16px -154px}
.flag.flag-tr {background-position: -32px -154px}
.flag.flag-tt {background-position: -48px -154px}
.flag.flag-tv {background-position: -64px -154px}
.flag.flag-tw {background-position: -80px -154px}
.flag.flag-tz {background-position: -96px -154px}
.flag.flag-ua {background-position: -112px -154px}
.flag.flag-ug {background-position: -128px -154px}
.flag.flag-um {background-position: -144px -154px}
.flag.flag-us {background-position: -160px -154px}
.flag.flag-uy {background-position: -176px -154px}
.flag.flag-uz {background-position: -192px -154px}
.flag.flag-va {background-position: -208px -154px}
.flag.flag-vc {background-position: -224px -154px}
.flag.flag-ve {background-position: -240px -154px}
.flag.flag-vg {background-position: 0 -165px}
.flag.flag-vi {background-position: -16px -165px}
.flag.flag-vn {background-position: -32px -165px}
.flag.flag-vu {background-position: -48px -165px}
.flag.flag-wales {background-position: -64px -165px}
.flag.flag-wf {background-position: -80px -165px}
.flag.flag-ws {background-position: -96px -165px}
.flag.flag-xk {background-position: -112px -165px}
.flag.flag-ye {background-position: -128px -165px}
.flag.flag-yt {background-position: -144px -165px}
.flag.flag-za {background-position: -160px -165px}
.flag.flag-zanzibar {background-position: -176px -165px}
.flag.flag-zm {background-position: -192px -165px}
.flag.flag-zw {background-position: -208px -165px}

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 78 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 43 B

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 42 B

Wyświetl plik

@ -0,0 +1,27 @@
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="panel panel-success">
<div class="panel-heading"><h3 class="panel-title">Airports</h3></div>
<div class="panel-body">
<table class="datatable table table-striped table-bordered">
<tr>
<th>#</th>
<th>Name</th>
<th>Country</th>
</tr>
{% for airport in pagination.items %}
<tr>
<td>{{ loop.index }}
<td>{{ airport.name }}</td>
<td><img src="{{ url_for('static', filename='img/Transparent.gif') }}" class="flag flag-{{ airport.country_code|lower }}" alt="{{ airport.country_code }}"/></td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}

Wyświetl plik

@ -0,0 +1,24 @@
{% extends 'bootstrap/base.html' %}
{% block title %}
{% if title %}{{ title }}{% else %}No page title{% endif %}
{% endblock %}
{% block navbar %}
{{nav.top_menubar.render()}}
{% endblock %}
{% block content %}
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info" role="alert">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{# application content needs to be provided in the app_content block #}
{% block app_content %}{% endblock %}
</div>
{% endblock %}

Wyświetl plik

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<div class="panel panel-success" id="asdf">
<div class="panel-heading"><h3 class="panel-title">Devices</h3></div>
<div class="panel-body">
{{ device.address }}
<table class="datatable table table-striped table-bordered">
<tr>
<th>Nr.</th>
<th colspan="2">Takeoff</th>
<th colspan="2">Landing</th>
<th>AGL</th>
</tr>
{% for entry in device.logbook %}
<tr>
<td>{{ loop.index }}</td>
<td>{% if entry.takeoff_timestamp is not none %} {{ entry.takeoff_timestamp.strftime('%H:%M') }} {% endif %}</td>
<td>{% if entry.takeoff_track is not none %} {{ '%02d' | format(entry.takeoff_track) }} {% endif %}</td>
<td>{% if entry.landing_timestamp is not none %} {{ entry.landing_timestamp.strftime('%H:%M') }} {% endif %}</td>
<td>{% if entry.landing_track is not none %} {{ '%02d' | format(entry.landing_track) }} {% endif %}</td>
<td>{% if entry.max_altitude is not none %} {{ entry.max_altitude }} {% endif %}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}

Wyświetl plik

@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="panel panel-success">
<div class="panel-heading"><h3 class="panel-title">Devices</h3></div>
<div class="panel-body">
<table class="datatable table table-striped table-bordered">
<tr>
<th>Address</th>
<th>Airport</th>
<th>Last takeoff/landing</th>
<th>Logbook</th>
<th>Software version</th>
</tr>
{% for device in devices %}
<tr>
<td><a href="?id={{ device.id }}">{{ device.address }}</a></td>
<td>{% if device.takeoff_landings %}{% set last_action = device.takeoff_landings|last %}{{ last_action.airport.name }}{% endif %}
<td>{% if device.takeoff_landings %}{% set last_action = device.takeoff_landings|last %}{% if last_action.is_takeoff == True %}↗{% else %}↘{% endif %} @ {{ last_action.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}{% endif %}
<td>{% if device.infos %}{% set info = device.infos|first %}{{ info.registration }} {% else %} - {% endif %}</td>
<td>{% if device.software_version is not none %}{% if device.software_version < 6.6 %}<p class="text-danger">{{ device.software_version }}</p>{% else %}{{ device.software_version }}{% endif %}{% else %} - {% endif %}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}

Wyświetl plik

@ -0,0 +1,61 @@
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="panel panel-success">
<div class="panel-heading"><h3 class="panel-title">Logbook</h3></div>
<div class="panel-body">
<form>
<div class="well">
<select name="country" onchange="this.form.submit();">
<option value="">(none)</option>
{% for country in countries %}
<option value="{{ country.iso2 }}"{% if sel_country == country.iso2 %} SELECTED{% endif %}>{{ country.iso2 }}</option>
{% endfor %}
</select>
<select name="airport" onchange="this.form.submit();">
<option value="">(none)</option>
{% for airport in airports %}
<option value="{{ airport.id }}"{% if sel_airport == airport.id|string() %} SELECTED{% endif %}>{{ airport.name }}</option>
{% endfor %}
</select>
<select name="date" onchange="this.form.submit();">
<option value="">(none)</option>
{% for date in dates %}
<option value="{{ date[0] }}"{% if sel_date|string() == date[0]|string() %} SELECTED{% endif %}>{{ date[0] }} ({{ date[1] }})</option>
{% endfor %}
</select>
</div>
</form>
{% if logbook is not none %}
<table class="datatable table table-striped table-bordered">
<tr>
<th>Nr.</th>
<th>Aircraft</th>
<th>Type</th>
<th colspan="2">Takeoff</th>
<th colspan="2">Landing</th>
<th>AGL</th>
</tr>
{% for entry in logbook %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ entry.registration }}</td>
<td>{{ entry.aircraft }}</td>
<td>{% if entry.takeoff_timestamp is not none %} {{ entry.takeoff_timestamp.strftime('%H:%M') }} {% endif %}</td>
<td>{% if entry.takeoff_track is not none %} {{ '%02d' | format(entry.takeoff_track) }} {% endif %}</td>
<td>{% if entry.landing_timestamp is not none %} {{ entry.landing_timestamp.strftime('%H:%M') }} {% endif %}</td>
<td>{% if entry.landing_track is not none %} {{ '%02d' | format(entry.landing_track) }} {% endif %}</td>
<td>{% if entry.max_altitude is not none %} {{ entry.max_altitude }} {% endif %}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
</div>
{% endblock %}

Wyświetl plik

@ -0,0 +1,81 @@
<!DOCTYPE html>
<!--
ogn-live - Display glider traffic from OpenGliderNetwork
Copyright (C) 2015 Sebastien Chaumontet and others
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
____ _____ _ _ _ _ _ _ _
/ __ \ / ____| (_) | | | \ | | | | | |
| | | |_ __ ___ _ __ | | __| |_ __| | ___ _ __ | \| | ___| |___ _____ _ __| | __
| | | | '_ \ / _ \ '_ \ | | |_ | | |/ _` |/ _ \ '__| | . ` |/ _ \ __\ \ /\ / / _ \| '__| |/ /
| |__| | |_) | __/ | | | | |__| | | | (_| | __/ | | |\ | __/ |_ \ V V / (_) | | | <
\____/| .__/ \___|_| |_| \_____|_|_|\__,_|\___|_| |_| \_|\___|\__| \_/\_/ \___/|_| |_|\_\
| |
|_|
-->
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Spot the gliders!</title>
<link href="cunimb.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3&amp;libraries=geometry&amp;sensor=false"></script>
<script type="text/javascript" src="util.js"></script>
<script type="text/javascript">
var cxml = "lxml.php";
var cxml1 = "livexml1.php";
var dxml = "dataxml.php";
var rxml = "rec.php";
var tld = "http://{{ ip_address }}:{{ port }}";
var vlon = 11.0;
var vlat = 48.0;
var vlatmin = 40.0;
var vlonmin = 10.0;
var vlatmax = 60.0;
var vlonmax = 20.0;
var bound = false;
var boundc = '';
var amax = 85;
var amin = -85;
var omax = 180;
var omin = -180;
var recc = "";
var parc = "";
var tz;
try {
tz = new Date().getTimezoneOffset();
} catch (e) {
tz = 0;
}
</script>
<script type="text/javascript" src="cunimb.js"></script>
</head>
<body onload="initialize()">
<div id="popup" onclick="cp('popup');"></div>
<div id="map_canvas"></div>
<div id="ac" class="acright" onclick="this.style.display='none';"></div>
<div id="dlist" class="lright">
<DIV id="ett1"></DIV>
<DIV id="ett2"></DIV>
<DIV id="dtable"></DIV>
</div>
</body>
</html>

Wyświetl plik

@ -0,0 +1,29 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/flags/flags.css') }}"/>
<div class="container">
<div class="panel panel-success" id="asdf">
<div class="panel-heading"><h3 class="panel-title">Receivers</h3></div>
<div class="panel-body">
<table class="datatable table table-striped table-bordered">
<tr>
<th>Name</th>
<th>Country</th>
<th>Altitude</th>
</tr>
{% for receiver in receivers %}
<tr>
<td>{{ receiver.name }}</td>
<td><img src="{{ url_for('static', filename='img/Transparent.gif') }}" class="flag flag-{{ receiver.country.iso2|lower }}" alt="{{ receiver.country.iso2 }}"/></td>
<td>{{ receiver.altitude }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}

Wyświetl plik

@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block content %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/flags/flags.css') }}"/>
<div class="container-fluid">
<div class="panel panel-success" id="asdf">
<div class="panel-heading"><h3 class="panel-title">Devices</h3></div>
<div class="panel-body">
<table class="datatable table table-striped table-bordered">
<tr>
<th>Receiver</th>
<th>Country</th>
<th>Aircrafts</th>
<th>Beacons</th>
</tr>
{% for receiverstat in receiverstats %}
<tr>
<td>{{ receiverstat.receiver.name }}</td>
<td><img src="{{ url_for('static', filename='img/Transparent.gif') }}" class="flag flag-{{ receiverstat.receiver.country.iso2|lower }}" alt="{{ receiverstat.receiver.country.iso2 }}"/></td>
<td>{{ receiverstat.aircraft_count }}</td>
<td>{{ receiverstat.beacon_count }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}

Wyświetl plik

@ -32,7 +32,10 @@ setup(
keywords='gliding ogn',
packages=find_packages(exclude=['tests', 'tests.*']),
install_requires=[
'Flask==1.0.2',
'flask-bootstrap==3.3.7.1',
'flask-sqlalchemy==2.3.2',
'flask-nav==0.6',
'geopy==1.17.0',
'manage.py==0.2.10',
'celery[redis]==4.2.1',