a terrible but somewhat functional state
This commit is contained in:
@@ -19,15 +19,12 @@ def create_app(test_config=None):
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
@app.route('/hello')
|
||||
def hello():
|
||||
return "'Ello, Wurld!"
|
||||
|
||||
from . import db
|
||||
db.init_app(app)
|
||||
|
||||
from . import weather
|
||||
app.register_blueprint(weather.bp)
|
||||
app.add_url_rule('/', endpoint='index')
|
||||
app.add_url_rule('/api', endpoint='api')
|
||||
|
||||
return app
|
||||
|
||||
@@ -5,7 +5,6 @@ CREATE TABLE "periods" (
|
||||
"id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"report_id" Integer NOT NULL,
|
||||
"period_number" Integer NOT NULL,
|
||||
"name" Text,
|
||||
"start_time" DateTime NOT NULL,
|
||||
"end_time" DateTime NOT NULL,
|
||||
"is_daytime" Integer NOT NULL,
|
||||
|
||||
BIN
weather/static/images/sunny.jpg
Normal file
BIN
weather/static/images/sunny.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
1
weather/static/images/sunny_license.html
Normal file
1
weather/static/images/sunny_license.html
Normal file
@@ -0,0 +1 @@
|
||||
Image by <a href="https://pixabay.com/users/couleur-1195798/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5459972">Couleur</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5459972">Pixabay</a>
|
||||
@@ -1,20 +1,97 @@
|
||||
@font-face {
|
||||
font-family: "Abel";
|
||||
src: url(Abel-Regular.woff2) format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
#clock {
|
||||
font-size: 2em;
|
||||
padding-top: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.font-abel {
|
||||
font-family: "Abel", sans-serif;
|
||||
.frosted {
|
||||
backdrop-filter: blur(16px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(16px) saturate(180%);
|
||||
background-color: rgba(78, 86, 106, 0.75);
|
||||
border: 1px solid rgba(255, 255, 255, 0.125);
|
||||
}
|
||||
|
||||
.antialiased {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
.page-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1.4fr 0.6fr;
|
||||
gap: 2em 0em;
|
||||
grid-auto-flow: row;
|
||||
grid-template-areas:
|
||||
"currentForecast"
|
||||
"hourlyReport"
|
||||
"weeklyReport";
|
||||
max-width: 72em;
|
||||
margin: 0 auto;
|
||||
padding: 1.5em 0 2.5em;
|
||||
}
|
||||
|
||||
.min-h-screen {
|
||||
min-height: 100vh;
|
||||
.currentForecast {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
gap: 0px 0px;
|
||||
grid-auto-flow: row;
|
||||
grid-template-areas:
|
||||
"forecast secondaryInfo";
|
||||
grid-area: currentForecast;
|
||||
}
|
||||
|
||||
.forecast {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: repeat(3, max-content);
|
||||
gap: 0px 0px;
|
||||
grid-auto-flow: row;
|
||||
grid-template-areas:
|
||||
"shortDescription"
|
||||
"longDescription"
|
||||
"currentTemp"
|
||||
"waterConditions";
|
||||
grid-area: forecast;
|
||||
}
|
||||
|
||||
.shortDescription {
|
||||
font-size: 3em;
|
||||
grid-area: shortDescription;
|
||||
}
|
||||
|
||||
.longDescription {
|
||||
font-size: 1.35em;
|
||||
grid-area: longDescription;
|
||||
}
|
||||
|
||||
.currentTemp { grid-area: currentTemp; }
|
||||
.currentTemp > .temperature { font-size: 6em; }
|
||||
.currentTemp > .unit { font-size: 2em; }
|
||||
|
||||
.waterConditions { grid-area: waterConditions; }
|
||||
|
||||
.secondaryInfo {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
gap: 2em 0;
|
||||
grid-auto-flow: row;
|
||||
grid-template-areas:
|
||||
"windContainer"
|
||||
"solarClock";
|
||||
grid-area: secondaryInfo;
|
||||
}
|
||||
|
||||
.windContainer { grid-area: windContainer; }
|
||||
|
||||
.solarClock { grid-area: solarClock; }
|
||||
|
||||
.hourlyReport { grid-area: hourlyReport; }
|
||||
|
||||
.weeklyReport {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
gap: 0px 0px;
|
||||
grid-auto-flow: row;
|
||||
grid-template-areas:
|
||||
". . . . . .";
|
||||
grid-area: weeklyReport;
|
||||
}
|
||||
|
||||
36
weather/static/tailwind.css
Normal file
36
weather/static/tailwind.css
Normal file
@@ -0,0 +1,36 @@
|
||||
@font-face {
|
||||
font-family: "Abel";
|
||||
src: url(Abel-Regular.woff2) format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
.font-abel { font-family: "Abel", sans-serif; }
|
||||
|
||||
.antialiased {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.min-h-screen { min-height: 100vh; }
|
||||
|
||||
.grid { display: grid; }
|
||||
|
||||
.grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
||||
|
||||
.grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
|
||||
|
||||
.gap-x-4 { column-gap: 0.5rem; }
|
||||
|
||||
.flex { display: flex; }
|
||||
|
||||
.items-center { align-items: center; }
|
||||
|
||||
.justify-between { justify-content: space-between; }
|
||||
|
||||
.justify-center { justify-content: center; }
|
||||
|
||||
.p-4 { padding: 1rem; }
|
||||
|
||||
.my-6 { margin-top: 1.25rem; margin-bottom: 1.25rem; }
|
||||
@@ -11,18 +11,24 @@
|
||||
|
||||
<!-- CSS -->
|
||||
<link href="{{ url_for('static', filename='reset.css') }}" rel="stylesheet" media="screen">
|
||||
<link href="{{ url_for('static', filename='tailwind.css') }}" rel="stylesheet" media="screen">
|
||||
<link href="{{ url_for('static', filename='style.css') }}" rel="stylesheet" media="screen">
|
||||
|
||||
<!-- JS that must be executed before the document is loaded -->
|
||||
|
||||
</head>
|
||||
<body class="font-abel antialiased">
|
||||
<div id="app" class="min-h-screen">
|
||||
{% for message in get_flashed_messages() %}
|
||||
<div class="flash">{{ message }}</div>
|
||||
{% endfor %}
|
||||
<div id="app" class="min-h-screen" style="background-image: url({{ url_for('static', filename=condition_image) }}); background-size: cover; background-position: center;">
|
||||
|
||||
<div id="clock">0:00:00 AM</div>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<script>
|
||||
let clock = document.getElementById('clock');
|
||||
setInterval(() => {
|
||||
clock.innerText = new Date().toLocaleTimeString();
|
||||
}, 1000)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,56 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% for period in periods %}
|
||||
<p>{{ period['start_time'] }} - {{ period['end_time'] }} | {{ period['temperature'] }}{{ period['temperature_unit'] }}</p>
|
||||
{% endfor %}
|
||||
<div class="page-container">
|
||||
<div class="currentForecast">
|
||||
<div class="forecast">
|
||||
<div class="shortDescription">{{ current_conditions['short_forecast'] }}</div>
|
||||
<div class="longDescription">{{ current_conditions['detailed_forecast'] }}</div>
|
||||
<div class="currentTemp">
|
||||
<span class="temperature">{{ current_conditions['temperature'] }}</span><span class="unit">°{{ current_conditions['temperature_unit'] }}</span>
|
||||
</div>
|
||||
<div class="waterConditions">{{ current_conditions['precipitation_probability'] }}% percip | {{ current_conditions['relative_humidity'] }}% humidity (relative)</div>
|
||||
</div>
|
||||
<div class="secondaryInfo">
|
||||
<div class="windContainer frosted">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">Wind Status</div>
|
||||
<div class="flex items-center">{{ current_conditions['wind_speed'] }}</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center">
|
||||
</div>
|
||||
<div class="flex items-center justify-center">
|
||||
Direction: {{ current_conditions['wind_direction'] }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="solarClock frosted">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">Sunrise</div>
|
||||
<div class="flex items-center">Sunset</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-center">
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">Time AM</div>
|
||||
<div class="flex items-center">Time PM</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hourlyForecast frosted my-6">
|
||||
<h3>Hourly Forecast</h3>
|
||||
<div class="grid grid-cols-6 gap-x-4">
|
||||
{{ current_conditions | tojson(2) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="weeklyReport frosted">
|
||||
<h3>Weekly Forecast</h3>
|
||||
<div class="grid grid-cols-7 gap-x-4">
|
||||
{% for period in periods %}
|
||||
<div>{{ period['start_time'] }} - {{ period['end_time'] }} | {{ period['temperature'] }}{{ period['temperature_unit'] }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -10,9 +10,40 @@ bp = Blueprint('weather', __name__)
|
||||
@bp.route('/')
|
||||
def index():
|
||||
db = get_db()
|
||||
latest_period = dict(db.execute(
|
||||
'SELECT `id` FROM `reports` WHERE `type` = "hourly" ORDER BY `reported_at` DESC'
|
||||
).fetchone())
|
||||
|
||||
current_conditions = dict(db.execute(
|
||||
f"SELECT * FROM `periods` WHERE `report_id` = {latest_period['id']} LIMIT 1"
|
||||
).fetchone())
|
||||
|
||||
# TODO: add conditions to check for day/night
|
||||
condition_image = f"images/{current_conditions['short_forecast'].lower()}.jpg"
|
||||
|
||||
periods = db.execute(
|
||||
'SELECT *'
|
||||
' FROM `periods`'
|
||||
' ORDER BY `id` DESC'
|
||||
' LIMIT 7'
|
||||
).fetchall()
|
||||
return render_template('weather/index.html', periods=periods)
|
||||
|
||||
return render_template(
|
||||
'weather/index.html',
|
||||
current_conditions=current_conditions,
|
||||
condition_image=condition_image,
|
||||
periods=periods
|
||||
)
|
||||
|
||||
@bp.route('/api')
|
||||
def api():
|
||||
db = get_db()
|
||||
latest_period = dict(db.execute(
|
||||
'SELECT `id` FROM `reports` WHERE `type` = "hourly" ORDER BY `reported_at` DESC'
|
||||
).fetchone())
|
||||
|
||||
current_conditions = dict(db.execute(
|
||||
f"SELECT * FROM `periods` WHERE `report_id` = {latest_period['id']} LIMIT 1"
|
||||
).fetchone())
|
||||
|
||||
return current_conditions
|
||||
|
||||
Reference in New Issue
Block a user