WIP: Add graphs to workouts list view that show reps/weight, still need to refactor logic and dont display unless plot button(Need to add) is checked
This commit is contained in:
28
app.py
28
app.py
@@ -5,7 +5,7 @@ from flask import Flask, render_template, redirect, request, url_for
|
|||||||
import jinja_partials
|
import jinja_partials
|
||||||
from decorators import validate_person, validate_topset, validate_workout
|
from decorators import validate_person, validate_topset, validate_workout
|
||||||
from db import DataBase
|
from db import DataBase
|
||||||
from utils import get_people_and_exercise_rep_maxes, convert_str_to_date, get_earliest_and_latest_workout_date, filter_workout_topsets, get_exercise_ids_from_workouts, first_and_last_visible_days_in_month
|
from utils import flatten, get_people_and_exercise_rep_maxes, convert_str_to_date, get_earliest_and_latest_workout_date, filter_workout_topsets, get_exercise_ids_from_workouts, first_and_last_visible_days_in_month
|
||||||
from flask_htmx import HTMX
|
from flask_htmx import HTMX
|
||||||
import minify_html
|
import minify_html
|
||||||
from urllib.parse import urlparse, unquote, quote
|
from urllib.parse import urlparse, unquote, quote
|
||||||
@@ -100,6 +100,32 @@ def get_person(person_id):
|
|||||||
filtered_exercises = filter(
|
filtered_exercises = filter(
|
||||||
lambda e: e['ExerciseId'] in active_exercise_ids, person['Exercises'])
|
lambda e: e['ExerciseId'] in active_exercise_ids, person['Exercises'])
|
||||||
person['FilteredExercises'] = list(filtered_exercises)
|
person['FilteredExercises'] = list(filtered_exercises)
|
||||||
|
|
||||||
|
# New feature to plot reps and weights over time
|
||||||
|
topsets_with_start_date = flatten([(p['StartDate'], p['TopSets'])
|
||||||
|
for p in person['Workouts']])
|
||||||
|
topsets = flatten([[{**t, 'StartDate': start_date} for t in topsets]
|
||||||
|
for (start_date, topsets) in topsets_with_start_date])
|
||||||
|
|
||||||
|
exercise_graph_view_models = []
|
||||||
|
for exercise_id in active_exercise_ids:
|
||||||
|
topsets_for_exercise = [
|
||||||
|
t for t in topsets if t['ExerciseId'] == exercise_id]
|
||||||
|
if topsets_for_exercise:
|
||||||
|
repitions = [t['Repetitions'] for t in topsets_for_exercise]
|
||||||
|
weights = [t['Weight'] for t in topsets_for_exercise]
|
||||||
|
start_dates = [t['StartDate'].strftime(
|
||||||
|
"%Y-%m-%d") for t in topsets_for_exercise]
|
||||||
|
exercise_view_model = {
|
||||||
|
'ExerciseId': exercise_id,
|
||||||
|
'ExerciseName': topsets_for_exercise[0]['ExerciseName'],
|
||||||
|
'Repititions': repitions[::-1],
|
||||||
|
'Weights': weights[::-1],
|
||||||
|
'StartDates': start_dates[::-1]
|
||||||
|
}
|
||||||
|
exercise_graph_view_models.append(exercise_view_model)
|
||||||
|
person['ExerciseGraphs'] = exercise_graph_view_models
|
||||||
|
|
||||||
if htmx:
|
if htmx:
|
||||||
return render_template('partials/page/person.html',
|
return render_template('partials/page/person.html',
|
||||||
person=person, selected_exercise_ids=active_exercise_ids, max_date=max_date, min_date=min_date, tags=tags), 200, {"HX-Trigger": "updatedPeople"}
|
person=person, selected_exercise_ids=active_exercise_ids, max_date=max_date, min_date=min_date, tags=tags), 200, {"HX-Trigger": "updatedPeople"}
|
||||||
|
|||||||
@@ -162,9 +162,52 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 mb-4 w-full grid grid-cols-1 2xl:grid-cols-2 gap-4">
|
||||||
|
{% for exercise_graph in person['ExerciseGraphs'] %}
|
||||||
|
<div class="bg-white shadow rounded-lg p-4 sm:p-6 xl:p-8 ">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<span class="text-2xl sm:text-3xl leading-none font-bold text-gray-900">{{
|
||||||
|
exercise_graph['ExerciseName'] }}</span>
|
||||||
|
</div>
|
||||||
|
<div id="e-{{ exercise_graph['ExerciseId'] }}"></div>
|
||||||
|
<script>
|
||||||
|
Plotly.newPlot("e-{{ exercise_graph['ExerciseId'] }}", [
|
||||||
|
{
|
||||||
|
x: {{ exercise_graph['StartDates'] | replace('"', "'") | safe }},
|
||||||
|
y: {{ exercise_graph['Repititions'] | replace('"', "'") | safe }},
|
||||||
|
name: 'Reps',
|
||||||
|
type: 'scatter'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: {{ exercise_graph['StartDates'] | replace('"', "'") | safe }},
|
||||||
|
y: {{ exercise_graph['Weights'] | replace('"', "'") | safe }},
|
||||||
|
name: 'Weight',
|
||||||
|
yaxis: 'y2',
|
||||||
|
type: 'scatter'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
{
|
||||||
|
title: '{{ exercise_graph['ExerciseName'] }}}',
|
||||||
|
margin: { t: 0 },
|
||||||
|
xaxis: { type: 'date', showgrid: false },
|
||||||
|
yaxis: { title: 'Reps', showgrid: false },
|
||||||
|
yaxis2: {
|
||||||
|
title: 'Weight',
|
||||||
|
overlaying: 'y',
|
||||||
|
side: 'right', showgrid: false
|
||||||
|
}
|
||||||
|
}, config);
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{ render_partial('partials/stats.html', stats=person['Stats']) }}
|
{{ render_partial('partials/stats.html', stats=person['Stats']) }}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
|||||||
13
utils.py
13
utils.py
@@ -170,3 +170,16 @@ def first_and_last_visible_days_in_month(first_day_of_month, last_day_of_month):
|
|||||||
end_date = last_day_of_month + \
|
end_date = last_day_of_month + \
|
||||||
timedelta(days=end[last_day_of_month.weekday()])
|
timedelta(days=end[last_day_of_month.weekday()])
|
||||||
return (start_date, end_date)
|
return (start_date, end_date)
|
||||||
|
|
||||||
|
|
||||||
|
def flatten(lst):
|
||||||
|
"""
|
||||||
|
Flatten a list of lists.
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
for item in lst:
|
||||||
|
if isinstance(item, list):
|
||||||
|
result.extend(flatten(item))
|
||||||
|
else:
|
||||||
|
result.append(item)
|
||||||
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user