diff --git a/rowers/templates/workouts_export_email.html b/rowers/templates/workouts_export_email.html
new file mode 100644
index 00000000..42ced93d
--- /dev/null
+++ b/rowers/templates/workouts_export_email.html
@@ -0,0 +1,11 @@
+{% extends "emailbase.html" %}
+{% block body %}
+
+ You can download the file {{ filename }} from the following link: {{ download_url }}. The file will be deleted after downloading, so please make sure to download it as soon as possible.
+
+
+
+
+ Best Regards, the Rowsandall Team
+
+{% endblock %}
diff --git a/rowers/urls.py b/rowers/urls.py
index b92ea953..19d499f9 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -434,6 +434,10 @@ urlpatterns = [
name='create_marker_workouts_view'),
re_path(r'^createmarkerworkouts/$', views.create_marker_workouts_view,
name='create_marker_workouts_view'),
+ re_path(r'^workouts/alluserworkouts/$', views.export_all_workouts_zip_view,
+ name='workout_export_all_workouts_zip_view'),
+ re_path(r'^workouts/download/$', views.download_zip_file_view,
+ name='download_zip_file_view'),
re_path(r'^goldmedalscores/$', views.goldmedalscores_view,
name='goldmedalscores_view'),
re_path(r'^goldmedalscores/user/(?P\d+)/$',
diff --git a/rowers/views/exportviews.py b/rowers/views/exportviews.py
index 3504e59f..0b62bdc2 100644
--- a/rowers/views/exportviews.py
+++ b/rowers/views/exportviews.py
@@ -273,6 +273,53 @@ def workout_csvemail_view(request, id=0):
return response
+import io
+
+# Export all workouts as ZIP file with individual CSV files
+@login_required()
+def export_all_workouts_zip_view(request):
+ from datetime import datetime
+ r = getrower(request.user)
+
+ if request.method == 'GET':
+ form = DateRangeForm()
+ elif request.method == 'POST':
+ form = DateRangeForm(request.POST)
+ if not form.is_valid():
+ messages.error(request, "Invalid date range. Please try again.")
+ return render(request, "export_workouts_daterange.html", {'form': form})
+
+ startdate = form.cleaned_data['startdate']
+ enddate = form.cleaned_data['enddate']
+
+ myqueue(queuehigh, email_all_user_workouts_zip, r, startdate, enddate)
+
+ successmessage = "A download link will be sent to you per email"
+ messages.info(request, successmessage)
+
+ # return to export settings view
+ return render(request, "export_workouts_daterange.html", {'form': form})
+
+def download_zip_file_view(request):
+ # This view would be called when the user clicks the download link in the email
+ zip_file_path = request.GET.get('file')
+ print("Requested ZIP file path:", zip_file_path) # Debugging statement
+ # add media folder
+ zip_file_path = os.path.join(settings.MEDIA_ROOT, zip_file_path)
+
+ if not zip_file_path or not os.path.exists(zip_file_path):
+ messages.error(request, "The requested file does not exist.")
+ return HttpResponseRedirect(reverse('workouts_view'))
+
+ with open(zip_file_path, 'rb') as f:
+ response = HttpResponse(f.read(), content_type='application/zip')
+ response['Content-Disposition'] = f'attachment; filename="{os.path.basename(zip_file_path)}"'
+
+ # remove the file after sending
+ os.remove(zip_file_path)
+
+ return response
+
# Get Workout CSV file and send it to user's email address
@login_required()
@@ -297,3 +344,5 @@ def workout_csvtoadmin_view(request, id=0): # pragma: no cover
response = HttpResponseRedirect(url)
return response
+
+
diff --git a/rowers/views/statements.py b/rowers/views/statements.py
index 84a62fdb..55988dae 100644
--- a/rowers/views/statements.py
+++ b/rowers/views/statements.py
@@ -254,6 +254,7 @@ from rowers.rows import handle_uploaded_file, handle_uploaded_image
from rowers.plannedsessions import *
from rowers.tasks import handle_makeplot, handle_otwsetpower, handle_sendemailtcx, handle_sendemailcsv
from rowers.tasks import (
+ email_all_user_workouts_zip,
handle_intervals_updateworkout,
handle_post_workout_api,
handle_sendemail_newftp,