Persists list of rendered user graphs in db, graph is removed list on click
This commit is contained in:
90
app.py
90
app.py
@@ -105,6 +105,17 @@ class HeartRateReading(db.Model):
|
|||||||
bpm = db.Column(db.Integer, nullable=False)
|
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'])
|
@app.route('/', methods=['GET'])
|
||||||
def overview():
|
def overview():
|
||||||
return render_users_and_workouts()
|
return render_users_and_workouts()
|
||||||
@@ -243,9 +254,27 @@ def graph_user_workouts(user_id):
|
|||||||
|
|
||||||
period = request.args.get('period', default='day', type=str)
|
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)
|
return plot_averaged_attributes(workouts, user, start_date, end_date, period, attributes)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/user/<int:user_id>/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)):
|
def daterange(start_date, end_date, delta=timedelta(days=1)):
|
||||||
"""Helper generator to iterate over date ranges."""
|
"""Helper generator to iterate over date ranges."""
|
||||||
curr_date = start_date
|
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')],
|
'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')],
|
'periods': [('day', 'Day'), ('week', 'Week'), ('month', 'Month')],
|
||||||
# (period: str, attributes: [str])
|
# (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,
|
'first_workout_date': workouts[-1]['start_time_date'] if workouts else None,
|
||||||
'last_workout_date': workouts[0]['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)
|
start_date, end_date = get_month_bounds(selected_date)
|
||||||
|
|
||||||
# Build a lookup dictionary for faster access
|
# 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()
|
current_date = datetime.now().date()
|
||||||
days_of_month = [
|
days_of_month = [
|
||||||
@@ -695,6 +726,61 @@ def generate_daily_duration_sparkline(workouts):
|
|||||||
return sparklines.sparklines(daily_durations)[0]
|
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):
|
def toDate(dateString):
|
||||||
return datetime.strptime(dateString, "%Y-%m-%d").date()
|
return datetime.strptime(dateString, "%Y-%m-%d").date()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="flex flex-wrap mb-1">
|
<div class="flex flex-wrap mb-5">
|
||||||
<div class="w-full md:w-1/5 px-3 mb-6 md:mb-0">
|
<div class="w-full md:w-1/5 px-3 mb-6 md:mb-0">
|
||||||
<div class="mb-1 w-full">
|
<div class="mb-1 w-full">
|
||||||
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-city">
|
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-city">
|
||||||
@@ -89,8 +89,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="user-workouts-overview-graphs-{{ user.id }}">
|
<div id="user-workouts-overview-graphs-{{ user.id }}">
|
||||||
{% for period, attributes in user.graphs %}
|
{% for graph in user.graphs %}
|
||||||
<img src="{{ url_for('graph_user_workouts', user_id=user.id, period=period, attributes=attributes) }}"
|
<img src="{{ url_for('graph_user_workouts', user_id=user.id, start_date=graph.start_date, end_date=graph.end_date, period=graph.period, attributes=graph.attributes) }}"
|
||||||
loading="lazy" alt="No image" class="mx-auto" _="on click remove me">
|
loading="lazy" alt="No image" class="mx-auto"
|
||||||
|
hx-delete="{{ url_for('delete_user_graph', user_id=user.id, start_date=graph.start_date, end_date=graph.end_date, period=graph.period, attributes=graph.attributes ) }}"
|
||||||
|
hx-swap="outerHTML">
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
Reference in New Issue
Block a user