8000 feat: add import and export buttons/functions by simplicityf · Pull Request #205 · joaovitoriasilva/endurain · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: add import and export buttons/functions #205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# This is an environment variable file for Endurain's docker-compose.yml.example
# These are just the variable you have to set to be up and running.
# There is many more variable you could set. Check them out here: https://docs.endurain.com/getting-started/advanced-started/#supported-environment-variables

DB_PASSWORD=changeme
POSTGRES_PASSWORD=changeme
SECRET_KEY=changeme
FERNET_KEY=changeme
GEOCODES_MAPS_API=changeme
TZ=Europe/Lisbon
ENDURAIN_HOST=https://endurain.example.com
BEHIND_PROXY=true
POSTGRES_DB=endurain
POSTGRES_USER=endurain
17 changes: 10 additions & 7 deletions backend/app/activities/activity/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import core.database as core_database
import core.dependencies as core_dependencies
import core.logger as core_logger
import core.config as core_config
import gears.dependencies as gears_dependencies
import session.security as session_security
import users.user.dependencies as users_dependencies
Expand Down Expand Up @@ -439,11 +440,13 @@ async def read_activities_user_activities_refresh(
)

# Get the garmin activities for the user for the last 24h
garmin_activities = garmin_activity_utils.get_user_garminconnect_activities_by_dates(
start_date=datetime.now(timezone.utc) - timedelta(days=1),
end_date=datetime.now(timezone.utc),
user_id=token_user_id,
db=db,
garmin_activities = (
garmin_activity_utils.get_user_garminconnect_activities_by_dates(
start_date=datetime.now(timezone.utc) - timedelta(days=1),
end_date=datetime.now(timezone.utc),
user_id=token_user_id,
db=db,
)
)

# Extend the activities to the list
Expand Down Expand Up @@ -563,7 +566,7 @@ async def create_activity_with_bulk_import(
):
try:
# Ensure the 'bulk_import' directory exists
bulk_import_dir = "files/bulk_import"
bulk_import_dir = core_config.FILES_BULK_IMPORT_DIR
os.makedirs(bulk_import_dir, exist_ok=True)

# Iterate over each file in the 'bulk_import' directory
Expand Down Expand Up @@ -682,7 +685,7 @@ async def delete_activity(
activities_crud.delete_activity(activity_id, db)

# Define the search pattern using the file ID (e.g., '1.*')
pattern = f"files/processed/{activity_id}.*"
pattern = f"{core_config.FILES_PROCESSED_DIR}/{activity_id}.*"

# Use glob to find files that match the pattern
files_to_delete = glob.glob(pattern)
Expand Down
10 changes: 6 additions & 4 deletions backend/app/activities/activity/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import fit.utils as fit_utils

import core.logger as core_logger
import core.config as core_config

# Global Activity Type Mappings (ID to Name)
ACTIVITY_ID_TO_NAME = {
Expand Down Expand Up @@ -164,6 +165,7 @@
"racquetball": 25,
"pickleball": 26,
"commuting_ride": 27,
"indoor_ride": 28,
}
)

Expand Down Expand Up @@ -343,7 +345,7 @@ def parse_and_store_activity_from_file(
f"File extension not supported: {file_extension}", "error"
)
# Define the directory where the processed files will be stored
processed_dir = "files/processed"
processed_dir = core_config.FILES_PROCESSED_DIR

# Define new file path with activity ID as filename
new_file_name = f"{idsToFileName}{file_extension}"
Expand Down Expand Up @@ -373,7 +375,7 @@ def parse_and_store_activity_from_uploaded_file(

try:
# Ensure the 'files' directory exists
upload_dir = "files"
upload_dir = core_config.FILES_DIR
os.makedirs(upload_dir, exist_ok=True)

10000 # Build the full path where the file will be saved
Expand Down Expand Up @@ -447,7 +449,7 @@ def parse_and_store_activity_from_uploaded_file(
)

# Define the directory where the processed files will be stored
processed_dir = "files/processed"
processed_dir = core_config.FILES_PROCESSED_DIR

# Define new file path with activity ID as filename
new_file_name = f"{idsToFileName}{file_extension}"
Expand Down Expand Up @@ -641,7 +643,7 @@ def calculate_activity_distances(activities: list[activities_schema.Activity]):
for activity in activities:
if activity.activity_type in [1, 2, 3]:
run += activity.distance
elif activity.activity_type in [4, 5, 6, 7, 27]:
elif activity.activity_type in [4, 5, 6, 7, 27, 28]:
bike += activity.distance
elif activity.activity_type in [8, 9]:
swim += activity.distance
Expand Down
79 changes: 70 additions & 9 deletions backend/app/activities/activity_laps/crud.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from fastapi import HTTPException, status
from sqlalchemy.orm import Session

import activities.activity.schema as activities_schema
import activities.activity.models as activity_models
import activities.activity.crud as activity_crud

Expand All @@ -15,9 +16,7 @@

def get_activity_laps(activity_id: int, token_user_id: int, db: Session):
try:
activity = activity_crud.get_activity_by_id(
activity_id, db
)
activity = activity_crud.get_activity_by_id(activity_id, db)

if not activity:
# If the activity does not exist, return None
Expand All @@ -30,7 +29,7 @@ def get_activity_laps(activity_id: int, token_user_id: int, db: Session):
if not user_is_owner and activity.hide_laps:
# If the user is not the owner and laps are hidden, return None
return None

# Get the activity laps from the database
activity_laps = (
db.query(activity_laps_models.ActivityLaps)
Expand Down Expand Up @@ -60,20 +59,82 @@ def get_activity_laps(activity_id: int, token_user_id: int, db: Session):
) from err


def get_public_activity_laps(activity_id: int, db: Session):
def get_activities_laps(
activity_ids: list[int],
token_user_id: int,
db: Session,
activities: list[activities_schema.Activity] = None,
):
try:
activity = activity_crud.get_activity_by_id(
activity_id, db
if not activity_ids:
return []

if not activities:
# Fetch all activities at once
activities = (
db.query(activity_models.Activity)
.filter(activity_models.Activity.id.in_(activity_ids))
.all()
)

if not activities:
return []

# Build a map of activity_id -> activity
activity_map = {activity.id: activity for activity in activities}

# Filter out hidden laps for activities the user doesn't own
allowed_ids = [
activity.id
for activity in activities
if activity.user_id == token_user_id
]

if not allowed_ids:
return []

# Fetch all laps for allowed activities
activity_laps = (
db.query(activity_laps_models.ActivityLaps)
.filter(activity_laps_models.ActivityLaps.activity_id.in_(allowed_ids))
.all()
)

if not activity_laps:
return []

# Serialize each lap
serialized_laps = [
activity_laps_utils.serialize_activity_lap(
activity_map[lap.activity_id], lap
)
for lap in activity_laps
]

return serialized_laps

except Exception as err:
core_logger.print_to_log(
f"Error in get_activities_laps: {err}", "error", exc=err
)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err


def get_public_activity_laps(activity_id: int, db: Session):
try:
activity = activity_crud.get_activity_by_id(activity_id, db)

if not activity:
# If the activity does not exist, return None
return None

if activity.hide_laps:
# If the user is not the owner and laps are hidden, return None
return None

# Check if public sharable links are enabled in server settings
server_settings = server_settings_crud.get_server_settings(db)

Expand Down
5 changes: 3 additions & 2 deletions backend/app/activities/activity_laps/utils.py
57AE
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
from zoneinfo import ZoneInfo

from datetime import datetime
Expand All @@ -7,6 +6,8 @@

import activities.activity.schema as activities_schema

import core.config as core_config

def serialize_activity_lap(activity: activities_schema.Activity, activity_lap: activity_laps_schema.ActivityLaps):
def make_aware_and_format(dt, timezone):
if isinstance(dt, str):
Expand All @@ -18,7 +19,7 @@ def make_aware_and_format(dt, timezone):
timezone = (
ZoneInfo(activity.timezone)
if activity.timezone
else ZoneInfo(os.environ.get("TZ"))
else ZoneInfo(core_config.TZ)
)

activity_lap.start_time = make_aware_and_format(activity_lap.start_time, timezone)
Expand Down
Loading
163F
0