Compare commits
6 Commits
0641b8bf20
...
a1aeb97e41
Author | SHA1 | Date |
---|---|---|
Simon | a1aeb97e41 | |
Simon | b0e21de7ad | |
Simon | 1040e38b22 | |
Simon | 15a1340e15 | |
Simon | 6fa62cb79e | |
Simon | cebb5a3bcd |
|
@ -1,6 +1,7 @@
|
|||
# python stuff
|
||||
__pycache__
|
||||
.vscode
|
||||
.venv
|
||||
|
||||
# protect real config files
|
||||
config.json
|
||||
|
@ -10,8 +11,5 @@ config.h
|
|||
postgres.env
|
||||
umami.env
|
||||
|
||||
# frontend font files
|
||||
*.ttf
|
||||
|
||||
# dynamic files
|
||||
**/dyn/
|
||||
|
|
17
deploy.sh
17
deploy.sh
|
@ -39,27 +39,12 @@ function sync_test {
|
|||
|
||||
}
|
||||
|
||||
# sync prod db to testing
|
||||
function sync_db {
|
||||
|
||||
newest_backup=$(ssh $remote_host 'find backup -type f -name "pg_*.gz" | sort | tail -n 1')
|
||||
rsync --progress -e ssh $remote_host:"$newest_backup" .
|
||||
rsync --progress -e ssh "$(basename "$newest_backup")" $local_host:backup/backup.gz
|
||||
|
||||
ssh $local_host "gzip -d backup/backup.gz"
|
||||
ssh $local_host "docker exec -i postgres psql -U aqi -d aqi < backup/backup"
|
||||
ssh $local_host "docker compose -f docker/docker-compose.yml restart"
|
||||
|
||||
}
|
||||
|
||||
if [[ $1 == "test" ]]; then
|
||||
sync_test "$2"
|
||||
elif [[ $1 == "docker" ]]; then
|
||||
sync_docker
|
||||
elif [[ $1 == "db" ]]; then
|
||||
sync_db
|
||||
else
|
||||
echo "valid options are: test | docker | db"
|
||||
echo "valid options are: test | docker"
|
||||
fi
|
||||
|
||||
##
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
APScheduler==3.10.1
|
||||
Flask==2.3.2
|
||||
APScheduler==3.10.4
|
||||
Flask==3.0.0
|
||||
Flask_HTTPAuth==4.8.0
|
||||
Flask_Table==0.5.0
|
||||
ipython==8.13.2
|
||||
matplotlib==3.7.1
|
||||
numpy==1.24.3
|
||||
pandas==2.0.1
|
||||
psycopg2-binary==2.9.6
|
||||
requests==2.30.0
|
||||
scipy==1.10.1
|
||||
uWSGI==2.0.21
|
||||
ipython==8.19.0
|
||||
matplotlib==3.8.2
|
||||
numpy==1.26.3
|
||||
pandas==2.1.4
|
||||
psycopg2-binary==2.9.9
|
||||
requests==2.31.0
|
||||
scipy==1.11.4
|
||||
uWSGI==2.0.23
|
||||
|
|
|
@ -89,7 +89,7 @@ class CurrentPlot:
|
|||
# calc ticks
|
||||
y_max = np.ceil(y.max()/50)*50 + 50
|
||||
# setup plot
|
||||
plt.style.use('seaborn')
|
||||
plt.style.use('seaborn-v0_8')
|
||||
plt.plot(x, y, color='#313131',)
|
||||
# fill colors
|
||||
plt_fill(plt, x, y)
|
||||
|
|
|
@ -183,7 +183,7 @@ class MonthGenerator():
|
|||
x_dates = [f'{str(i).zfill(2)} {month_short}' for i in x_numbers]
|
||||
x_ticks = x_range, x_dates
|
||||
# plot
|
||||
plt.style.use('seaborn')
|
||||
plt.style.use('seaborn-v0_8')
|
||||
plt.plot(x, y_1, color='#313131', label='this year')
|
||||
plt.plot(
|
||||
x, y_2, color='#666666', linestyle='dashed', label='last year'
|
||||
|
|
|
@ -192,7 +192,7 @@ class LastSevenDays:
|
|||
x_ticks = self.axis['x_ticks']
|
||||
y_max = np.ceil(max(pd.concat([y_1, y_2]))/50)*50 + 50
|
||||
# plot
|
||||
plt.style.use('seaborn')
|
||||
plt.style.use('seaborn-v0_8')
|
||||
plt.plot(x, y_1, color='#313131', label='2hour avg')
|
||||
plt.plot(x, y_2, color='#cc0000', label='daily avg')
|
||||
# fill colors
|
||||
|
@ -284,7 +284,7 @@ class LastThreeDays:
|
|||
x = axis['x']
|
||||
y = axis['y'].replace(0, 1)
|
||||
x_ticks = np.arange(0, 97, step=8)
|
||||
plt.style.use('seaborn')
|
||||
plt.style.use('seaborn-v0_8')
|
||||
plt.plot(x, y, color='#313131',)
|
||||
# fill colors
|
||||
plt_fill(plt, x, y)
|
||||
|
@ -363,7 +363,7 @@ class PmGraphs:
|
|||
else:
|
||||
col.append('#ff4d4d')
|
||||
# plot
|
||||
plt.style.use('seaborn')
|
||||
plt.style.use('seaborn-v0_8')
|
||||
plt.bar(x_dates, y, color=col, width=0.5)
|
||||
plt.axhline(y=thresh, color='#6ecd65', linestyle=':')
|
||||
plt.xticks(ticks=x_range, labels=x_dates)
|
||||
|
@ -426,7 +426,7 @@ class HourBar:
|
|||
# color columns
|
||||
col = NightlyPlots.color_colums(y)
|
||||
# create plot
|
||||
plt.style.use('seaborn')
|
||||
plt.style.use('seaborn-v0_8')
|
||||
plt.bar(x, y, color=col, width=0.5)
|
||||
plt.yticks(np.arange(0, y_max, step=50))
|
||||
plt.xticks(ticks=x_range, labels=x_hours)
|
||||
|
@ -549,7 +549,7 @@ class YearComparison:
|
|||
# build plot
|
||||
plt.title("Daily avg AQI values compared to last year", fontsize=15)
|
||||
chart_fill(plt, y_ticks)
|
||||
plt.style.use("seaborn")
|
||||
plt.style.use("seaborn-v0_8")
|
||||
plt.plot(x, y_1, color="#313131", label="this year")
|
||||
plt.plot(
|
||||
x, y_2, color="#666666", linestyle="dashed", label="last year"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import json
|
||||
|
||||
from flask_table import create_table, Col
|
||||
# from flask_table import create_table, Col
|
||||
|
||||
|
||||
def get_config():
|
||||
|
@ -102,37 +102,9 @@ def chart_fill(plt, y_ticks):
|
|||
)
|
||||
|
||||
|
||||
class Table:
|
||||
""" create html table from filename to pass to template """
|
||||
def get_table(path):
|
||||
"""read json file from path"""
|
||||
with open(path, "r") as f:
|
||||
table_data = json.loads(f.read()).get("data")
|
||||
|
||||
COLUMNS = [' ', 'this year', 'last year', 'change']
|
||||
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.rows = self.get_rows()
|
||||
|
||||
def get_rows(self):
|
||||
""" read filename to build rows dict """
|
||||
|
||||
with open(self.filename, 'r') as json_file:
|
||||
json_raw = json_file.read()
|
||||
|
||||
table_json = json.loads(json_raw)
|
||||
|
||||
rows = []
|
||||
for i in table_json['data']:
|
||||
row = dict(zip(self.COLUMNS, i))
|
||||
rows.append(row)
|
||||
|
||||
return rows
|
||||
|
||||
def create_table(self):
|
||||
""" create the table with rows and columns """
|
||||
|
||||
blank_table = create_table(options={'classes': ['comp-table']})
|
||||
|
||||
for i in self.COLUMNS:
|
||||
blank_table.add_column(i, Col(i))
|
||||
|
||||
table_obj = blank_table(self.rows)
|
||||
return table_obj
|
||||
return table_data
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
Copyright 2015 The Rubik Project Authors (https://github.com/googlefonts/rubik)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -246,7 +246,7 @@ function colorTables() {
|
|||
cell.textContent = '\u25B2';
|
||||
cell.style.backgroundColor = '#ff4d4d';
|
||||
} else if (cellContent == 'same') {
|
||||
cell.textContent = '\u301C';
|
||||
cell.textContent = '\uFF5E';
|
||||
cell.style.backgroundColor = '#bdbdbd';
|
||||
} else if (cellContent == 'nan') {
|
||||
cell.style.backgroundColor = '#eeeeee';
|
||||
|
|
|
@ -91,7 +91,26 @@
|
|||
</div>
|
||||
<div class="content graph">
|
||||
<div class="graph-item">
|
||||
{{ table }}
|
||||
<table class="comp-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>this year</th>
|
||||
<th>last year</th>
|
||||
<th>change</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in table %}
|
||||
<tr>
|
||||
<td>{{ row.0 }}</td>
|
||||
<td>{{ row.1 }}</td>
|
||||
<td>{{ row.2 }}</td>
|
||||
<td>{{ row.3 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="graph-item">
|
||||
<a href="/static/dyn/year-graph.png" data-lightbox="year">
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
{% block content %}{% endblock %}
|
||||
<div class="full-width col_bg">
|
||||
<div class="col-box">
|
||||
<p>© 2023 | <a href="https://github.com/bbilly1/aqi_monitor" target="_blank">Documentation</a></p>
|
||||
<p>© <script type="text/javascript">document.write(new Date().getFullYear());</script> | <a href="https://github.com/bbilly1/aqi_monitor" target="_blank">Documentation</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -16,7 +16,26 @@
|
|||
</a>
|
||||
</div>
|
||||
<div class="graph-item">
|
||||
{{month.table}}
|
||||
<table class="comp-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>this year</th>
|
||||
<th>last year</th>
|
||||
<th>change</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in month.table %}
|
||||
<tr>
|
||||
<td>{{ row.0 }}</td>
|
||||
<td>{{ row.1 }}</td>
|
||||
<td>{{ row.2 }}</td>
|
||||
<td>{{ row.3 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
|
|
@ -9,7 +9,7 @@ from flask_httpauth import HTTPBasicAuth
|
|||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
|
||||
|
||||
from src.helper import Table, get_config
|
||||
from src.helper import get_config, get_table
|
||||
from src.db import get_current, insert_data
|
||||
from src.graph_current import main as current_graph
|
||||
from src.graph_nightly import main as nightly_graph
|
||||
|
@ -92,7 +92,7 @@ def about():
|
|||
@app.route("/graphs")
|
||||
def graphs():
|
||||
""" graphs page """
|
||||
table = Table('static/dyn/year-table.json').create_table()
|
||||
table = get_table("static/dyn/year-table.json")
|
||||
return render_template('graphs.html', title='Graphs', table=table)
|
||||
|
||||
|
||||
|
@ -108,7 +108,7 @@ def monthly():
|
|||
month_graph = os.path.join('static/dyn/monthly', month_clean + '.png')
|
||||
month_name = datetime.strptime(month_clean, "%Y-%m").strftime('%B %Y')
|
||||
month_json = os.path.join('static/dyn/monthly', month)
|
||||
table = Table(month_json).create_table()
|
||||
table = get_table(month_json)
|
||||
month_dict = {
|
||||
'month_graph': month_graph,
|
||||
'month_name': month_name,
|
||||
|
|
Loading…
Reference in New Issue