✨ Map: handle GPX click
This commit is contained in:
parent
0abb938393
commit
9eae8f9b53
@ -6,6 +6,11 @@
|
|||||||
(closeEmitter)="closePlaceBox()"></app-place-box>
|
(closeEmitter)="closePlaceBox()"></app-place-box>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (selectedGPX) {
|
||||||
|
<app-place-gpx [selectedPlace]="selectedGPX" (downloadEmitter)="downloadGPX()" (removeEmitter)="removeGPX()"
|
||||||
|
(closeEmitter)="closePlaceGPX()"></app-place-gpx>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="absolute z-30 top-2 right-2 p-2 bg-white shadow rounded dark:bg-surface-900">
|
<div class="absolute z-30 top-2 right-2 p-2 bg-white shadow rounded dark:bg-surface-900">
|
||||||
<p-button (click)="toggleMarkersList()" text severity="secondary" icon="pi pi-map-marker" />
|
<p-button (click)="toggleMarkersList()" text severity="secondary" icon="pi pi-map-marker" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import { YesNoModalComponent } from "../../modals/yes-no-modal/yes-no-modal.comp
|
|||||||
import { CategoryCreateModalComponent } from "../../modals/category-create-modal/category-create-modal.component";
|
import { CategoryCreateModalComponent } from "../../modals/category-create-modal/category-create-modal.component";
|
||||||
import { AuthService } from "../../services/auth.service";
|
import { AuthService } from "../../services/auth.service";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
|
import { PlaceGPXComponent } from "../../shared/place-gpx/place-gpx.component";
|
||||||
|
|
||||||
export interface ContextMenuItem {
|
export interface ContextMenuItem {
|
||||||
text: string;
|
text: string;
|
||||||
@ -62,6 +63,7 @@ export interface MarkerOptions extends L.MarkerOptions {
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
PlaceBoxComponent,
|
PlaceBoxComponent,
|
||||||
|
PlaceGPXComponent,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
SkeletonModule,
|
SkeletonModule,
|
||||||
ToggleSwitchModule,
|
ToggleSwitchModule,
|
||||||
@ -102,6 +104,7 @@ export class DashboardComponent implements OnInit, AfterViewInit {
|
|||||||
visiblePlaces: Place[] = [];
|
visiblePlaces: Place[] = [];
|
||||||
selectedPlace?: Place;
|
selectedPlace?: Place;
|
||||||
categories: Category[] = [];
|
categories: Category[] = [];
|
||||||
|
selectedGPX?: Place;
|
||||||
|
|
||||||
filter_display_visited = false;
|
filter_display_visited = false;
|
||||||
filter_display_favorite_only = false;
|
filter_display_favorite_only = false;
|
||||||
@ -531,21 +534,24 @@ export class DashboardComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
displayGPXOnMap(gpx: string) {
|
displayGPXOnMap(gpx: string) {
|
||||||
if (!this.map) return;
|
if (!this.map || !this.selectedPlace) return;
|
||||||
if (!this.gpxLayerGroup)
|
if (!this.gpxLayerGroup)
|
||||||
this.gpxLayerGroup = L.layerGroup().addTo(this.map);
|
this.gpxLayerGroup = L.layerGroup().addTo(this.map);
|
||||||
this.gpxLayerGroup.clearLayers();
|
this.gpxLayerGroup.clearLayers();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const gpxPolyline = gpxToPolyline(gpx);
|
const gpxPolyline = gpxToPolyline(gpx);
|
||||||
|
const selectedPlaceWithGPX = { ...this.selectedPlace, gpx };
|
||||||
|
|
||||||
gpxPolyline.on("click", () => {
|
gpxPolyline.on("click", () => {
|
||||||
this.gpxLayerGroup?.removeLayer(gpxPolyline);
|
this.selectedGPX = selectedPlaceWithGPX;
|
||||||
});
|
});
|
||||||
this.gpxLayerGroup?.addLayer(gpxPolyline);
|
this.gpxLayerGroup?.addLayer(gpxPolyline);
|
||||||
this.map.fitBounds(gpxPolyline.getBounds(), { padding: [20, 20] });
|
this.map.fitBounds(gpxPolyline.getBounds(), { padding: [20, 20] });
|
||||||
} catch {
|
} catch {
|
||||||
this.utilsService.toast("error", "Error", "Couldn't parse GPX data");
|
this.utilsService.toast("error", "Error", "Couldn't parse GPX data");
|
||||||
}
|
}
|
||||||
|
this.closePlaceBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlaceGPX() {
|
getPlaceGPX() {
|
||||||
@ -816,6 +822,28 @@ export class DashboardComponent implements OnInit, AfterViewInit {
|
|||||||
this.selectedPlace = undefined;
|
this.selectedPlace = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closePlaceGPX() {
|
||||||
|
this.selectedGPX = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadGPX() {
|
||||||
|
if (!this.selectedGPX?.gpx) return;
|
||||||
|
const dataBlob = new Blob([this.selectedGPX.gpx]);
|
||||||
|
const downloadURL = URL.createObjectURL(dataBlob);
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = downloadURL;
|
||||||
|
link.download = `TRIP_${this.selectedGPX.name}.gpx`;
|
||||||
|
link.click();
|
||||||
|
link.remove();
|
||||||
|
URL.revokeObjectURL(downloadURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeGPX() {
|
||||||
|
if (!this.gpxLayerGroup) return;
|
||||||
|
this.gpxLayerGroup.clearLayers();
|
||||||
|
this.closePlaceGPX();
|
||||||
|
}
|
||||||
|
|
||||||
toGithub() {
|
toGithub() {
|
||||||
this.utilsService.toGithubTRIP();
|
this.utilsService.toGithubTRIP();
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/src/app/shared/place-gpx/place-gpx.component.html
Normal file
22
src/src/app/shared/place-gpx/place-gpx.component.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@if (selectedPlace) {
|
||||||
|
<div class="place-box-dialog">
|
||||||
|
<div class="place-box-dialog-content">
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<div class="flex items-center gap-4 w-full max-w-full">
|
||||||
|
<img [src]="selectedPlace.image || selectedPlace.category.image"
|
||||||
|
class="object-cover rounded-full size-16">
|
||||||
|
<div class="flex grow min-w-0">
|
||||||
|
<h1 class="text-gray-800 font-bold mb-0 truncate">Trace of {{ selectedPlace.name }}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end gap-2">
|
||||||
|
<p-button (click)="downloadTrace()" text icon="pi pi-download" />
|
||||||
|
<p-button (click)="removeTrace()" text icon="pi pi-eraser" />
|
||||||
|
<div class="border-l border-solid border-gray-700 h-4"></div>
|
||||||
|
<p-button (click)="close()" text icon="pi pi-times" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
25
src/src/app/shared/place-gpx/place-gpx.component.scss
Normal file
25
src/src/app/shared/place-gpx/place-gpx.component.scss
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
.place-box-dialog {
|
||||||
|
animation: slideYcenteredX 0.3s both;
|
||||||
|
z-index: 999;
|
||||||
|
min-height: 100px;
|
||||||
|
max-height: 800px;
|
||||||
|
width: 95%;
|
||||||
|
max-width: 1200px;
|
||||||
|
background-color: #fff;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
transition: none;
|
||||||
|
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
position: relative;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/src/app/shared/place-gpx/place-gpx.component.ts
Normal file
38
src/src/app/shared/place-gpx/place-gpx.component.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
} from "@angular/core";
|
||||||
|
import { ButtonModule } from "primeng/button";
|
||||||
|
import { Place } from "../../types/poi";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "app-place-gpx",
|
||||||
|
standalone: true,
|
||||||
|
imports: [ButtonModule],
|
||||||
|
templateUrl: "./place-gpx.component.html",
|
||||||
|
styleUrls: ["./place-gpx.component.scss"],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class PlaceGPXComponent {
|
||||||
|
@Input() selectedPlace: Place | undefined = undefined;
|
||||||
|
@Output() closeEmitter = new EventEmitter<void>();
|
||||||
|
@Output() removeEmitter = new EventEmitter<void>();
|
||||||
|
@Output() downloadEmitter = new EventEmitter<void>();
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.closeEmitter.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeTrace() {
|
||||||
|
this.removeEmitter.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadTrace() {
|
||||||
|
this.downloadEmitter.emit()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user