Merge pull request #10 from altf4arnold/webdesign

Webdesign
This commit is contained in:
Arnold Dechamps 2024-03-20 18:16:11 +01:00 committed by GitHub
commit a923d7e798
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 851 additions and 35 deletions

View file

@ -1,16 +1,29 @@
# flight-screen-info # flight-screen-info
Will end up being a little flask site that provides the departure schedule of whatever airport you choose (like they do in real airports) Will end up being a little flask site that provides the departure schedule of whatever airport you choose (like they do in real airports)
![Alt screenshot of the flask app runing](screenshot.png)
# API : ## API :
This program uses the API of Flightaware. This program uses the API of Flightaware.
Said API requires an API key. More info [here](https://www.flightaware.com/commercial/aeroapi) Said API requires an API key. More info [here](https://www.flightaware.com/commercial/aeroapi)
# Config.py : ## config.py :
The example file needs to be copied as config.py. There, you can configure the API key and airport that interests you. The example file needs to be copied as config.py. There, you can configure the API key and airport that interests you.
# datapull.py : ## datapull.py :
This file will pull the data from flightaware's server and print it on the terminal This file will pull the data from flightaware's server and print it on the terminal
# Flask : ## Flask :
This is where the web app runs.
To start flask, ``flask run`` To start flask, ``flask run``
You can then go on ``https://127.0.0.1:5000`` You can then go on ``https://127.0.0.1:5000``
# Developers :
For the CSS, tailwind is used.
To install the CSS bundler :
```
npm install -D tailwindcss
```
to update CSS files :
```
npx tailwindcss -i ./static/input.css -o ./static/style.css
```

27
app.py
View file

@ -4,8 +4,7 @@ This piece of code was written by myself. Supposed to be a frontend for a web-pa
import datapull import datapull
from flask import Flask, render_template from flask import Flask, render_template
from config import AIRPORT as airport from datetime import datetime, timedelta
from datetime import datetime
from dateutil import tz from dateutil import tz
app = Flask(__name__) app = Flask(__name__)
@ -15,7 +14,14 @@ app = Flask(__name__)
def hello_world(): def hello_world():
localformat = "%H:%M" localformat = "%H:%M"
rawdata = datapull.grabber() rawdata = datapull.grabber()
airport = {"name": "", "icao": "", "iata": ""}
for flight in rawdata: for flight in rawdata:
# Source Airport naming
airport["name"] = flight["origin"]["name"]
airport["icao"] = flight["origin"]["code_icao"]
airport["iata"] = flight["origin"]["code_iata"]
# Converting departures time from UTC to local time
origintimezone = flight["origin"]["timezone"] origintimezone = flight["origin"]["timezone"]
from_zone = tz.gettz('UTC') from_zone = tz.gettz('UTC')
to_zone = tz.gettz(origintimezone) to_zone = tz.gettz(origintimezone)
@ -23,7 +29,22 @@ def hello_world():
utctime = utctime.replace(tzinfo=from_zone) utctime = utctime.replace(tzinfo=from_zone)
flight["scheduled_off"] = utctime.astimezone(to_zone).strftime(localformat) flight["scheduled_off"] = utctime.astimezone(to_zone).strftime(localformat)
return render_template('screen.html', airport=airport, data=rawdata) # Calculating Delays in human readable ways
negative = False
delay = flight["departure_delay"]
if delay != 0:
if delay is not None:
# taking advances in account
if delay < 0:
# delay is negative
negative = True
delay = abs(delay)
delay = timedelta(seconds=delay)
delay = datetime.strptime(str(delay), "%H:%M:%S")
flight["departure_delay"] = delay.strftime(localformat)
if negative:
flight["departure_delay"] = ("-" + str(flight["departure_delay"]))
return render_template('screen.html', len=len(rawdata), airport=airport, flight=rawdata)
@app.route("/style.css") @app.route("/style.css")

View file

@ -6,3 +6,6 @@ FLIGHTAWAREKEY = "V3rYs3cr3t"
# ICAO code of the airport you want to see # ICAO code of the airport you want to see
AIRPORT = "EBBR" AIRPORT = "EBBR"
# Amount of pages to pull from the API (default 2)
PAGES = 2

View file

@ -13,7 +13,7 @@ def grabber():
departures = [] departures = []
apiUrl = "https://aeroapi.flightaware.com/aeroapi/" apiUrl = "https://aeroapi.flightaware.com/aeroapi/"
airport = config.AIRPORT airport = config.AIRPORT
payload = {'max_pages': 2} payload = {'max_pages': config.PAGES}
auth_header = {'x-apikey': config.FLIGHTAWAREKEY} auth_header = {'x-apikey': config.FLIGHTAWAREKEY}
response = requests.get(apiUrl + f"airports/{airport}/flights/scheduled_departures", params=payload, response = requests.get(apiUrl + f"airports/{airport}/flights/scheduled_departures", params=payload,
@ -22,6 +22,12 @@ def grabber():
departures = response.json()["scheduled_departures"] departures = response.json()["scheduled_departures"]
else: else:
print("Error executing request") print("Error executing request")
# These are for debug. Should be commented in production
"""
for flight in departures:
print(flight)
"""
return departures return departures

5
package.json Normal file
View file

@ -0,0 +1,5 @@
{
"devDependencies": {
"tailwindcss": "^3.4.1"
}
}

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

3
static/input.css Normal file
View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

BIN
static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View file

@ -0,0 +1,721 @@
/*
! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com
*/
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box;
/* 1 */
border-width: 0;
/* 2 */
border-style: solid;
/* 2 */
border-color: #e5e7eb;
/* 2 */
}
::before,
::after {
--tw-content: '';
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
7. Disable tap highlights on iOS
*/
html,
:host {
line-height: 1.5;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
tab-size: 4;
/* 3 */
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
font-feature-settings: normal;
/* 5 */
font-variation-settings: normal;
/* 6 */
-webkit-tap-highlight-color: transparent;
/* 7 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0;
/* 1 */
line-height: inherit;
/* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0;
/* 1 */
color: inherit;
/* 2 */
border-top-width: 1px;
/* 3 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* 1 */
font-feature-settings: normal;
/* 2 */
font-variation-settings: normal;
/* 3 */
font-size: 1em;
/* 4 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
text-indent: 0;
/* 1 */
border-color: inherit;
/* 2 */
border-collapse: collapse;
/* 3 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-feature-settings: inherit;
/* 1 */
font-variation-settings: inherit;
/* 1 */
font-size: 100%;
/* 1 */
font-weight: inherit;
/* 1 */
line-height: inherit;
/* 1 */
color: inherit;
/* 1 */
margin: 0;
/* 2 */
padding: 0;
/* 3 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button;
/* 1 */
background-color: transparent;
/* 2 */
background-image: none;
/* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
list-style: none;
margin: 0;
padding: 0;
}
/*
Reset default styling for dialogs.
*/
dialog {
padding: 0;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
input::placeholder,
textarea::placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
/* 1 */
vertical-align: middle;
/* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden] {
display: none;
}
*, ::before, ::after {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
::backdrop {
--tw-border-spacing-x: 0;
--tw-border-spacing-y: 0;
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-gradient-from-position: ;
--tw-gradient-via-position: ;
--tw-gradient-to-position: ;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia: ;
}
.relative {
position: relative;
}
.flex {
display: flex;
}
.table {
display: table;
}
.h-14 {
height: 3.5rem;
}
.h-16 {
height: 4rem;
}
.w-14 {
width: 3.5rem;
}
.w-full {
width: 100%;
}
.items-center {
align-items: center;
}
.justify-between {
justify-content: space-between;
}
.overflow-scroll {
overflow: scroll;
}
.overflow-x-auto {
overflow-x: auto;
}
.scroll-smooth {
scroll-behavior: smooth;
}
.whitespace-nowrap {
white-space: nowrap;
}
.border-b {
border-bottom-width: 1px;
}
.bg-gray-100 {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.bg-yellow-400 {
--tw-bg-opacity: 1;
background-color: rgb(250 204 21 / var(--tw-bg-opacity));
}
.fill-current {
fill: currentColor;
}
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.py-3 {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
.py-4 {
padding-top: 1rem;
padding-bottom: 1rem;
}
.pl-8 {
padding-left: 2rem;
}
.text-left {
text-align: left;
}
.text-2xl {
font-size: 1.5rem;
line-height: 2rem;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
.text-xs {
font-size: 0.75rem;
line-height: 1rem;
}
.font-medium {
font-weight: 500;
}
.uppercase {
text-transform: uppercase;
}
.text-amber-400 {
--tw-text-opacity: 1;
color: rgb(251 191 36 / var(--tw-text-opacity));
}
.text-blue-500 {
--tw-text-opacity: 1;
color: rgb(59 130 246 / var(--tw-text-opacity));
}
.text-gray-500 {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity));
}
.text-gray-700 {
--tw-text-opacity: 1;
color: rgb(55 65 81 / var(--tw-text-opacity));
}
.text-gray-900 {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.text-red-600 {
--tw-text-opacity: 1;
color: rgb(220 38 38 / var(--tw-text-opacity));
}
.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
@media (min-width: 1024px) {
.lg\:pl-0 {
padding-left: 0px;
}
}
.rtl\:text-right:where([dir="rtl"], [dir="rtl"] *) {
text-align: right;
}

11
tailwind.config.js Normal file
View file

@ -0,0 +1,11 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./templates/*.html'
],
theme: {
extend: {},
},
plugins: [],
}

View file

@ -3,36 +3,69 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<title>{{ airport }} Departure Schedule</title> <title>{{ airport["icao"] }} Departure Schedule</title>
</head> </head>
<body> <body>
<table> <nav class="px-4 flex justify-between bg-yellow-400 h-16">
<tr> <ul class="flex items-center">
<th>Flight</th> <li>
<th>Time</th> <h1 class="pl-8 lg:pl-0 text-white text-2xl">{{ airport["name"] }} Airport Departures</h1>
<th>Delay</th> </li>
<th>Airline</th> </ul>
<th>Destination</th> <ul class="flex items-center">
<th>Remarks</th> <li class="h-14 w-14">
</tr> <img
{% for flight in data %} class="fill-current h-14 w-14"
src="/static/logo.png"
alt="Skyscreen Logo"/>
</li>
</ul>
</nav>
<div class="relative overflow-x-auto">
<table class="w-full text-sm text-left rtl:text-right text-gray-500">
<thead class="text-xs text-gray-700 uppercase bg-yellow-400">
<tr> <tr>
<td>{{ flight["ident"] }}</td> <th scope="col" class="px-6 py-3">Flight</th>
<td>{{ flight["scheduled_off"] }}</td> <th scope="col" class="px-6 py-3">Time</th>
<td>{% if flight["departure_delay"] %} <th scope="col" class="px-6 py-3">Delay</th>
{{ flight["departure_delay"] }} <th scope="col" class="px-6 py-3">Airline</th>
<th scope="col" class="px-6 py-3">Destination</th>
<th scope="col" class="px-6 py-3">Remarks</th>
</tr>
</thead>
<tbody>
{% for i in range(0,len) %}
{% if i%2 == 0 %}
<tr class="bg-white border-b">
{% else %}
<tr class="bg-gray-100 border-b">
{% endif %}
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">{{ flight[i]["ident"] }}</td>
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">{{ flight[i]["scheduled_off"] }}</td>
<td class="px-6 py-4 font-medium text-red-600 whitespace-nowrap">{% if flight[i]["departure_delay"] %}
{{ flight[i]["departure_delay"] }}
{% else %}
{% endif %}
</td>
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">{{ flight[i]["operator"] }}</td>
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap overflow-scroll scroll-smooth">
{% if flight[i]["destination"]["name"] %}
{{ flight[i]["destination"]["name"] }}
<span class="text-blue-500">{{ flight[i]["destination"]["code_icao"] }}</span> /
<span class="text-green-600">{{ flight[i]["destination"]["code_iata"] }}</span>
{% else %} {% else %}
{% endif %} {% endif %}
</td> </td>
<td>{{ flight["operator"] }}</td> <td class="px-6 py-4 font-medium text-amber-400 whitespace-nowrap">
<td>{{ flight["destination"]["name"] }}</td> {% if flight[i]["status"] != "Scheduled" %}
<td>{% if flight["status"] != "Scheduled" %} {{ flight[i]["status"] }}
{{ flight["status"] }} {% else %}
{% else %} {% endif %}
{% endif %} </td>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </tbody>
</table>
</div>
</body> </body>
</html> </html>