From 10ee97794ecc81d55cbbef7d581c0fe6ef9ada01 Mon Sep 17 00:00:00 2001 From: Peter Stockings Date: Tue, 24 Dec 2024 20:32:58 +1100 Subject: [PATCH] Add functionality to import/export readings in csv format --- app/routes.py | 70 ++++++++++++++++++++++++++++++++++++-- app/templates/_layout.html | 2 +- app/templates/data.html | 30 ++++++++++++++++ 3 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 app/templates/data.html diff --git a/app/routes.py b/app/routes.py index 5c562c5..ef26ffd 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,9 +1,12 @@ -from flask import Blueprint, render_template, redirect, request, url_for, flash +import csv +from io import StringIO +from flask import Blueprint, render_template, redirect, request, send_file, url_for, flash from werkzeug.security import generate_password_hash, check_password_hash from app.models import Profile, Reading, db, User from app.forms import DeleteForm, LoginForm, ProfileForm, ReadingForm, SignupForm from flask_login import login_user, login_required, current_user, logout_user import base64 +from datetime import datetime, timedelta main = Blueprint('main', __name__) auth = Blueprint('auth', __name__) @@ -45,8 +48,6 @@ def logout(): @main.route('/', methods=['GET', 'POST']) @login_required def dashboard(): - from datetime import datetime, timedelta - # Default values start_date = None end_date = None @@ -197,3 +198,66 @@ def profile(): return redirect(url_for('user.profile')) return render_template('profile.html', form=form, profile=profile) + +@main.route('/data', methods=['GET', 'POST']) +@login_required +def manage_data(): + if request.method == 'POST': + # Handle CSV file upload + file = request.files.get('file') + if file and file.filename.endswith('.csv'): + try: + csv_data = csv.reader(StringIO(file.read().decode('utf-8'))) + next(csv_data) # Skip the header row + for row in csv_data: + timestamp, systolic, diastolic, heart_rate = row + reading = Reading( + user_id=current_user.id, + timestamp=datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S'), + systolic=int(systolic), + diastolic=int(diastolic), + heart_rate=int(heart_rate), + ) + db.session.add(reading) + db.session.commit() + flash('Data imported successfully!', 'success') + except Exception as e: + flash(f'Error importing data: {str(e)}', 'danger') + else: + flash('Please upload a valid CSV file.', 'danger') + return redirect(url_for('main.manage_data')) + + return render_template('data.html') + +@main.route('/data/export', methods=['GET']) +@login_required +def export_data(): + import io + + output = io.StringIO() + writer = csv.writer(output) + + # Write CSV header + writer.writerow(['Timestamp', 'Systolic', 'Diastolic', 'Heart Rate']) + + # Write user readings to the CSV + readings = Reading.query.filter_by(user_id=current_user.id).all() + for reading in readings: + writer.writerow([ + reading.timestamp.strftime('%Y-%m-%d %H:%M:%S'), + reading.systolic, + reading.diastolic, + reading.heart_rate, + ]) + + # Convert text to bytes for `send_file` + output.seek(0) + response = io.BytesIO(output.getvalue().encode('utf-8')) + output.close() + + return send_file( + response, + mimetype='text/csv', + as_attachment=True, + download_name='readings.csv' + ) \ No newline at end of file diff --git a/app/templates/_layout.html b/app/templates/_layout.html index b0e8d7a..adbca6c 100644 --- a/app/templates/_layout.html +++ b/app/templates/_layout.html @@ -20,7 +20,7 @@
{% if current_user.is_authenticated %} Dashboard - + Data diff --git a/app/templates/data.html b/app/templates/data.html new file mode 100644 index 0000000..7227872 --- /dev/null +++ b/app/templates/data.html @@ -0,0 +1,30 @@ +{% extends "_layout.html" %} + +{% block content %} + +{% endblock %} \ No newline at end of file