From 6861860b9d973f5bc7a7b4cfae5daf50cbad25e4 Mon Sep 17 00:00:00 2001 From: itskovacs Date: Tue, 28 Oct 2025 18:20:12 +0100 Subject: [PATCH] :lipstick: Dashboard: update settings tabs layout, integrate account tab --- .../dashboard/dashboard.component.html | 179 +++++++++--------- .../dashboard/dashboard.component.ts | 86 ++++++++- 2 files changed, 174 insertions(+), 91 deletions(-) diff --git a/src/src/app/components/dashboard/dashboard.component.html b/src/src/app/components/dashboard/dashboard.component.html index 00166a0..ee00024 100644 --- a/src/src/app/components/dashboard/dashboard.component.html +++ b/src/src/app/components/dashboard/dashboard.component.html @@ -167,10 +167,10 @@ About - Tweaks + Account - Map + Preferences Categories @@ -181,11 +181,12 @@ -
+

About

- +
@@ -221,34 +222,79 @@
Made with ❤️ in BZH
-
-

Low Network Mode

- You can disable Low Network Mode. Default is true. - Display Category - image instead of Place image. -
-
-
Low Network Mode
- +
+

Account

+ +
+ +
-
-

Dark Mode

+
+
+

TOTP

+ Add a second layer of security to your + account +
+ +
-
-
Enable Dark mode
- + + +
+
+
+

Map parameters

+ You can customize the default view on map + loading +
+ + +
+ +
+ + + + + + + + + + + + + + +
+
+ +
+
+
Low Network Mode
+ You can disable Low Network Mode. + Default is true. Display Category image instead of Place image. +
+ +
+ +
-
-

GPX Indication

- If enabled, display a compass in Place bubble when - a - GPX is present. -
-
-
Enable GPX indication
- +
+
+
GPX Indication
+ Display a compass in Place bubble when a + GPX is present. +
+
+ +
@@ -281,42 +327,6 @@
- -
-
-
-

Map parameters

- You can customize the default view on map - loading -
- - -
- -
- - - - - - - - - - - - - - -
- -
- -
-
-
@@ -346,32 +356,31 @@
-
-
-
-

Export data

- Start an export and download it -
- -
- - - - - -
+
+
+

Export data

+ Start an export and download it
-
- +
+ + + + +
+
+
+ +
+ +
@for (backup of backups; track backup.id) { -
-
+
+
{{ backup.filename }}
@if (backup.file_size) {{{ backup.file_size | fileSize }}} @@ -412,7 +421,7 @@

No backup

} -
+
diff --git a/src/src/app/components/dashboard/dashboard.component.ts b/src/src/app/components/dashboard/dashboard.component.ts index bcf75dc..f143195 100644 --- a/src/src/app/components/dashboard/dashboard.component.ts +++ b/src/src/app/components/dashboard/dashboard.component.ts @@ -32,6 +32,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { PlaceGPXComponent } from '../../shared/place-gpx/place-gpx.component'; import { CommonModule } from '@angular/common'; import { FileSizePipe } from '../../shared/filesize.pipe'; +import { TotpVerifyModalComponent } from '../../modals/totp-verify-modal/totp-verify-modal.component'; export interface ContextMenuItem { text: string; @@ -75,7 +76,6 @@ export class DashboardComponent implements OnInit, AfterViewInit { searchInput = new FormControl(''); info?: Info; isLowNet = false; - isDarkMode = false; isGpxInPlaceMode = false; viewSettings = false; @@ -167,9 +167,8 @@ export class DashboardComponent implements OnInit, AfterViewInit { this.activeCategories = new Set(categories.map((c) => c.name)); this.isLowNet = !!settings.mode_low_network; - this.isDarkMode = !!settings.mode_dark; this.isGpxInPlaceMode = !!settings.mode_gpx_in_place; - if (this.isDarkMode) this.utilsService.enableDarkMode(); + if (settings.mode_dark) this.utilsService.enableDarkMode(); this.resetFilters(); this.places = [...places]; @@ -595,9 +594,8 @@ export class DashboardComponent implements OnInit, AfterViewInit { 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.enableDarkMode(); + if (resp.settings.mode_dark) this.utilsService.enableDarkMode(); this.resetFilters(); this.map?.remove(); @@ -866,7 +864,7 @@ export class DashboardComponent implements OnInit, AfterViewInit { toggleDarkMode() { if (!this.settings) return; - let data: Partial = { mode_dark: this.isDarkMode }; + let data: Partial = { mode_dark: !this.settings.mode_dark }; // If user uses default tile, we also update tile_layer to dark/voyager if ( !this.settings.mode_dark && @@ -906,4 +904,80 @@ export class DashboardComponent implements OnInit, AfterViewInit { }, }); } + + toggleTOTP() { + if (this.settings?.totp_enabled) this.disableTOTP(); + else this.enableTOTP(); + } + + enableTOTP() { + this.apiService + .enableTOTP() + .pipe(take(1)) + .subscribe({ + next: (secret) => { + let modal = this.dialogService.open(TotpVerifyModalComponent, { + header: 'Verify TOTP', + modal: true, + closable: true, + breakpoints: { + '640px': '90vw', + }, + data: { + message: + "Add this secret to your authentication app.\nEnter the generated code below to verify it's correct", + token: secret.secret, + }, + })!; + + modal.onClose.subscribe({ + next: (code: string) => { + if (code) + this.apiService.verifyTOTP(code).subscribe({ + next: () => (this.settings!.totp_enabled = true), + }); + }, + error: () => this.utilsService.toast('error', 'Error', 'Error enabling TOTP'), + }); + }, + }); + } + + disableTOTP() { + const modal = this.dialogService.open(TotpVerifyModalComponent, { + header: 'Verify TOTP', + modal: true, + closable: true, + breakpoints: { + '640px': '90vw', + }, + })!; + + modal.onClose.subscribe({ + next: (code: string) => { + if (!code) return; + + const modal = this.dialogService.open(YesNoModalComponent, { + header: 'Confirm', + modal: true, + closable: true, + dismissableMask: true, + breakpoints: { + '640px': '90vw', + }, + data: 'Are you sure you want to disable TOTP?', + })!; + + modal.onClose.subscribe({ + next: (bool: boolean) => { + if (!bool) return; + this.apiService.disableTOTP(code).subscribe({ + next: () => (this.settings!.totp_enabled = false), + error: () => this.utilsService.toast('error', 'Error', 'Error disabling TOTP'), + }); + }, + }); + }, + }); + } }