From 57753fc2fc71ae9429a97987958e94f21292e77c Mon Sep 17 00:00:00 2001 From: Peter Stockings Date: Tue, 24 Oct 2023 21:29:52 +1100 Subject: [PATCH] Persists list of rendered user graphs in db, graph is removed list on click --- app.py | 90 +++++++++++++++++++- templates/partials/user_workouts_graphs.html | 10 ++- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index 277baf7..5e2a898 100644 --- a/app.py +++ b/app.py @@ -105,6 +105,17 @@ class HeartRateReading(db.Model): bpm = db.Column(db.Integer, nullable=False) +class UserGraphs(db.Model): + __tablename__ = 'user_graphs' + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey( + 'users.id', ondelete='CASCADE'), nullable=False) + start_date = db.Column(db.DateTime, nullable=False) + end_date = db.Column(db.DateTime, nullable=False) + period = db.Column(db.String(255), nullable=False) + attributes = db.Column(db.ARRAY(db.String(255))) + + @app.route('/', methods=['GET']) def overview(): return render_users_and_workouts() @@ -243,9 +254,27 @@ def graph_user_workouts(user_id): period = request.args.get('period', default='day', type=str) + # Add record of user graph + insert_usergraph_if_not_exists( + user_id, start_date, end_date, period, attributes) + return plot_averaged_attributes(workouts, user, start_date, end_date, period, attributes) +@app.route('/user//workouts/graph/delete', methods=['DELETE']) +def delete_user_graph(user_id): + attributes = request.args.getlist( + 'attributes', type=str) + start_date = request.args.get( + 'start_date', default=datetime.now().date(), type=toDate) + end_date = request.args.get( + 'end_date', default=datetime.now().date(), type=toDate) + period = request.args.get('period', default='day', type=str) + + remove_usergraph(user_id, start_date, end_date, period, attributes) + return "" + + def daterange(start_date, end_date, delta=timedelta(days=1)): """Helper generator to iterate over date ranges.""" curr_date = start_date @@ -486,7 +515,8 @@ def generate_user_data(user, workouts=[]): 'attributes': [('workout_count', 'Workout count'), ('duration_seconds', 'Duration (sec)'), ('duration_minutes', 'Duration (min)'), ('average_rpm', 'Average RPM'), ('max_rpm', 'Max RPM'), ('average_bpm', 'Average BPM'), ('max_bpm', 'Max BPM'), ('distance', 'Distance'), ('calories', 'Calories')], 'periods': [('day', 'Day'), ('week', 'Week'), ('month', 'Month')], # (period: str, attributes: [str]) - 'graphs': [('month', ['duration_minutes']), ('week', ['average_rpm', 'average_bpm']), ('week', ['workout_count'])], + # 'graphs': [('month', ['duration_minutes']), ('week', ['average_rpm', 'average_bpm']), ('week', ['workout_count'])], + 'graphs': get_user_graphs(user.id), 'first_workout_date': workouts[-1]['start_time_date'] if workouts else None, 'last_workout_date': workouts[0]['start_time_date'] if workouts else None, } @@ -638,7 +668,8 @@ def generate_calendar_monthly_view(workouts, selected_date): start_date, end_date = get_month_bounds(selected_date) # Build a lookup dictionary for faster access - workout_lookup = {w['start_time_date'] : w for w in workouts if start_date <= w['start_time_date'] <= end_date} + workout_lookup = {w['start_time_date'] + : w for w in workouts if start_date <= w['start_time_date'] <= end_date} current_date = datetime.now().date() days_of_month = [ @@ -695,6 +726,61 @@ def generate_daily_duration_sparkline(workouts): return sparklines.sparklines(daily_durations)[0] +def get_user_graphs(user_id): + """Retrieve a list of UserGraphs entries for the given user_id.""" + + user_graphs = UserGraphs.query.filter_by( + user_id=user_id).order_by(UserGraphs.id.desc()).all() + + # change start_date, end_date from datetime to dates + for user_graph in user_graphs: + user_graph.start_date = user_graph.start_date.date() + user_graph.end_date = user_graph.end_date.date() + + return user_graphs + + +def insert_usergraph_if_not_exists(user_id, start_date, end_date, period, attributes): + """Insert a UserGraphs entry if it doesn't already exist based on specified attributes and return its ID.""" + + existing_graph = UserGraphs.query.filter_by( + user_id=user_id, + start_date=start_date, + end_date=end_date, + period=period, + attributes=attributes + ).first() + + if not existing_graph: + new_graph = UserGraphs( + user_id=user_id, + start_date=start_date, + end_date=end_date, + period=period, + attributes=attributes + ) + db.session.add(new_graph) + db.session.commit() + return new_graph.id # Return the ID of the newly added object + return None # Return None if the record already exists + + +def remove_usergraph(user_id, start_date, end_date, period, attributes): + """Remove a UserGraphs entry based on specified attributes.""" + + existing_graph = UserGraphs.query.filter_by( + user_id=user_id, + start_date=start_date, + end_date=end_date, + period=period, + attributes=attributes + ).first() + + if existing_graph: + db.session.delete(existing_graph) + db.session.commit() + + def toDate(dateString): return datetime.strptime(dateString, "%Y-%m-%d").date() diff --git a/templates/partials/user_workouts_graphs.html b/templates/partials/user_workouts_graphs.html index 4d4b1c5..22efbcf 100644 --- a/templates/partials/user_workouts_graphs.html +++ b/templates/partials/user_workouts_graphs.html @@ -1,4 +1,4 @@ -
+
- {% for period, attributes in user.graphs %} - No image + {% for graph in user.graphs %} + No image {% endfor %}
\ No newline at end of file