From d3292f14301c4ffc29e8024758b3a6be34e23fe2 Mon Sep 17 00:00:00 2001 From: itskovacs Date: Wed, 6 Aug 2025 23:46:37 +0200 Subject: [PATCH] :bug: Fix import not updating categories, Fix import not updating user settings --- backend/trip/routers/settings.py | 39 +++++++++++++++---- .../dashboard/dashboard.component.ts | 21 +++++++--- src/src/app/services/api.service.ts | 23 +++++++---- src/src/app/types/settings.ts | 8 ++++ 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/backend/trip/routers/settings.py b/backend/trip/routers/settings.py index 6bb628b..05a3803 100644 --- a/backend/trip/routers/settings.py +++ b/backend/trip/routers/settings.py @@ -80,12 +80,12 @@ def export_data(session: SessionDep, current_user: Annotated[str, Depends(get_cu return data -@router.post("/import", response_model=list[PlaceRead]) +@router.post("/import") async def import_data( session: SessionDep, current_user: Annotated[str, Depends(get_current_username)], file: UploadFile = File(...), -) -> list[PlaceRead]: +): if file.content_type != "application/json": raise HTTPException(status_code=415, detail="File must be a JSON file") @@ -107,7 +107,7 @@ async def import_data( # Handle image update if category.get("image_id"): - b64_image = category.get("images", {}).get(str(category.get("image_id"))) + b64_image = data.get("images", {}).get(str(category.get("image_id"))) if b64_image: image_bytes = b64img_decode(b64_image) filename = save_image_to_file(image_bytes, settings.PLACE_IMAGE_SIZE) @@ -144,7 +144,7 @@ async def import_data( category_data["user"] = current_user if category.get("image_id"): - b64_image = category.get("images", {}).get(str(category.get("image_id"))) + b64_image = data.get("images", {}).get(str(category.get("image_id"))) if b64_image is None: continue @@ -205,16 +205,32 @@ async def import_data( db_user = session.get(User, current_user) if data.get("settings"): settings_data = data["settings"] - if settings_data.get("map_lat"): + if "map_lat" in settings_data: db_user.map_lat = settings_data["map_lat"] - if settings_data.get("map_lng"): + if "map_lng" in settings_data: db_user.map_lng = settings_data["map_lng"] - if settings_data.get("currency"): + if "currency" in settings_data: db_user.currency = settings_data["currency"] + if "tile_layer" in settings_data: + db_user.tile_layer = settings_data["tile_layer"] + + if "do_not_display" in settings_data: + db_user.do_not_display = ",".join(settings_data["do_not_display"]) + + if "mode_low_network" in settings_data: + db_user.mode_low_network = settings_data["mode_low_network"] + + if "mode_dark" in settings_data: + db_user.mode_dark = settings_data["mode_dark"] + + if "mode_gpx_in_place" in settings_data: + db_user.mode_gpx_in_place = settings_data["mode_gpx_in_place"] + session.add(db_user) + session.flush() session.refresh(db_user) trip_place_id_map = {p["id"]: new_p.id for p, new_p in zip(data.get("places", []), places)} @@ -271,4 +287,11 @@ async def import_data( session.add(trip_item) session.commit() - return [PlaceRead.serialize(p) for p in places] + return { + "places": [PlaceRead.serialize(p) for p in places], + "categories": [ + CategoryRead.serialize(c) + for c in session.exec(select(Category).filter(Category.user == current_user)) + ], + "settings": UserRead.serialize(session.get(User, current_user)), + } diff --git a/src/src/app/components/dashboard/dashboard.component.ts b/src/src/app/components/dashboard/dashboard.component.ts index 92c18ac..ef1b8c5 100644 --- a/src/src/app/components/dashboard/dashboard.component.ts +++ b/src/src/app/components/dashboard/dashboard.component.ts @@ -617,13 +617,24 @@ export class DashboardComponent implements OnInit, AfterViewInit { .settingsUserImport(formdata) .pipe(take(1)) .subscribe({ - next: (places) => { - this.places = [...this.places, ...places].sort((a, b) => + next: (resp) => { + this.places = [...this.places, ...resp.places].sort((a, b) => a.name.localeCompare(b.name), ); - setTimeout(() => { - this.updateMarkersAndClusters(); - }, 10); + + this.categories = resp.categories; + this.activeCategories = new Set(resp.categories.map((c) => c.name)); + + this.settings = resp.settings; + this.isLowNet = !!resp.settings.mode_low_network; + this.isDarkMode = !!resp.settings.mode_dark; + this.isGpxInPlaceMode = !!resp.settings.mode_gpx_in_place; + if (this.isDarkMode) this.utilsService.toggleDarkMode(); + this.resetFilters(); + + this.map?.remove(); + this.initMap(); + this.updateMarkersAndClusters(); this.viewSettings = false; }, }); diff --git a/src/src/app/services/api.service.ts b/src/src/app/services/api.service.ts index 6d2471b..49998e6 100644 --- a/src/src/app/services/api.service.ts +++ b/src/src/app/services/api.service.ts @@ -3,7 +3,7 @@ import { HttpClient } from "@angular/common/http"; import { Category, Place } from "../types/poi"; import { BehaviorSubject, Observable, tap } from "rxjs"; import { Info } from "../types/info"; -import { Settings } from "../types/settings"; +import { ImportResponse, Settings } from "../types/settings"; import { Trip, TripBase, TripDay, TripItem } from "../types/trip"; @Injectable({ @@ -220,12 +220,21 @@ export class ApiService { return this.httpClient.get(`${this.apiBaseUrl}/settings/export`); } - settingsUserImport(formdata: FormData): Observable { + settingsUserImport(formdata: FormData): Observable { const headers = { enctype: "multipart/form-data" }; - return this.httpClient.post( - `${this.apiBaseUrl}/settings/import`, - formdata, - { headers: headers }, - ); + return this.httpClient + .post(`${this.apiBaseUrl}/settings/import`, formdata, { + headers: headers, + }) + .pipe( + tap((resp) => { + if (resp.categories) { + this._categoriesSubjectNext(resp.categories); + } + if (resp.settings) { + this.settingsSubject.next(resp.settings); + } + }), + ); } } diff --git a/src/src/app/types/settings.ts b/src/src/app/types/settings.ts index 42444ba..d082d3f 100644 --- a/src/src/app/types/settings.ts +++ b/src/src/app/types/settings.ts @@ -1,3 +1,5 @@ +import { Category, Place } from "./poi"; + export interface Settings { username: string; map_lat: number; @@ -9,3 +11,9 @@ export interface Settings { mode_dark?: boolean; mode_gpx_in_place?: boolean; } + +export interface ImportResponse { + places: Place[]; + categories: Category[]; + settings: Settings; +}