Redesign BP tracker with lightweight views and unobtrusive save confirmations

This commit is contained in:
Peter Stockings
2026-09-08 15:07:57 +10:00
parent 25d1774e53
commit 87b60aac9b
40 changed files with 2693 additions and 2553 deletions
+9
View File
@@ -0,0 +1,9 @@
// Run after compiling. Decimal kB; gzip response-body sizes, without HTTP headers.
const fs = require('node:fs');
const zlib = require('node:zlib');
for (const [file, limit] of [['app/static/css/tailwind.css', 8000], ['app/static/js/diy-turbo.min.js', 5000]]) {
const bytes = fs.readFileSync(file);
const size = zlib.gzipSync(bytes).length;
console.log(`${file}: ${bytes.length} bytes raw, ${size} bytes gzip (budget ${limit})`);
if (size > limit) process.exitCode = 1;
}
+48
View File
@@ -0,0 +1,48 @@
"""Measure compressed page bodies using only an isolated synthetic database."""
import gzip
import json
import os
import sys
from datetime import datetime, timedelta
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
os.environ['FLASK_CONFIG'] = 'TestingConfig'
from app.config import TestingConfig
TestingConfig.SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
from app import create_app, db
from app.models import User, Profile, Reading
app = create_app()
results = {}
with app.app_context():
db.create_all()
db.session.add(User(id=1, username='size-fixture', password_hash='unused', profile=Profile(timezone='Australia/Sydney')))
db.session.commit()
client = app.test_client()
with client.session_transaction() as session:
session['_user_id'] = '1'
session['_fresh'] = True
for filename in ('css/tailwind.css', 'js/diy-turbo.min.js', 'images/favicon.svg'):
payload = (ROOT / 'app/static' / filename).read_bytes()
results[filename] = {'raw_bytes': len(payload), 'gzip_bytes': len(gzip.compress(payload))}
for name, count in [('empty', 0), ('typical', 120), ('large', 10000)]:
db.session.query(Reading).filter_by(user_id=1).delete()
anchor = datetime(2026, 9, 8, 0, 0)
db.session.bulk_save_objects([Reading(user_id=1, timestamp=anchor - timedelta(hours=i * 5),
systolic=110 + i % 40, diastolic=65 + i % 25, heart_rate=60 + i % 30) for i in range(count)])
db.session.commit()
for view in ('overview', 'history', 'trends'):
dates = 'start_date=2020-01-01&end_date=2026-09-08' if name == 'large' and view == 'trends' else 'start_date=2026-09-02&end_date=2026-09-08'
payload = client.get(f'/dashboard?view={view}&{dates}')
assert payload.status_code == 200
size = len(gzip.compress(payload.data))
assert size <= 20000, (name, view, size)
results[f'{name}_{view}'] = {'raw_bytes': len(payload.data), 'gzip_bytes': size}
shared = sum(results[key]['gzip_bytes'] for key in ('css/tailwind.css', 'js/diy-turbo.min.js', 'images/favicon.svg'))
results['typical_cold_overview_bytes'] = shared + results['typical_overview']['gzip_bytes']
assert results['typical_cold_overview_bytes'] <= 40000
db.session.remove()
db.drop_all()
print(json.dumps(results, indent=2))
+32
View File
@@ -0,0 +1,32 @@
"""Run the redesign with disposable, synthetic data: python scripts/preview.py."""
import os
import sys
from datetime import datetime, timedelta
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
os.environ['FLASK_CONFIG'] = 'TestingConfig'
from app.config import TestingConfig
TestingConfig.SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
from app import create_app, db
from app.models import Profile, Reading, User
from werkzeug.security import generate_password_hash
app = create_app()
with app.app_context():
db.create_all()
user = User(username='demo', password_hash=generate_password_hash('preview-only'),
profile=Profile(name='Alex Morgan', timezone='Australia/Sydney'))
db.session.add(user)
db.session.flush()
now = datetime.utcnow().replace(minute=30, second=0, microsecond=0)
db.session.add_all([Reading(user_id=user.id, timestamp=now - timedelta(hours=12 * i),
systolic=122 + ((i * 7) % 19), diastolic=74 + ((i * 3) % 12), heart_rate=62 + i % 14)
for i in range(120)])
db.session.commit()
if __name__ == '__main__':
print('Synthetic preview: http://127.0.0.1:5055 — demo / preview-only', flush=True)
app.run(host='127.0.0.1', port=5055, use_reloader=False, debug=False)