Selaa lähdekoodia

Map display in event detail view

Lukas Angerer 2 vuotta sitten
vanhempi
sitoutus
edb7da47cb

+ 3 - 1
src/RunnersMeet.Client/src/app/app.module.ts

@@ -38,7 +38,8 @@ import { DistancePipe } from './tracks/distance.pipe';
 import { ElevationPipe } from './tracks/elevation.pipe';
 import { RegistrationStatePipe } from './events/registration-state.pipe';
 import { EventListItemComponent } from './events/event-list-item/event-list-item.component';
-import { IsOwnerPipe } from './users/is-owner.pipe';
+import { IsOwnerPipe } from './users/is-owner.pipe';
+import { MapComponent } from './tracks/map/map.component';
 
 @NgModule({
 	declarations: [
@@ -65,6 +66,7 @@ import { IsOwnerPipe } from './users/is-owner.pipe';
 		RegistrationStatePipe,
 		EventListItemComponent,
 		IsOwnerPipe,
+  MapComponent,
 	],
 	imports: [
 		BrowserModule,

+ 5 - 0
src/RunnersMeet.Client/src/app/events/event-view/event-view.component.html

@@ -30,3 +30,8 @@
 		</tr>
 	</ng-template>
 </p-table>
+
+<ng-container *ngIf="event?.track">
+	<h1>Map</h1>
+	<app-map [track]="event!.track!"></app-map>
+</ng-container>

+ 1 - 1
src/RunnersMeet.Client/src/app/pages/events-page/events-page.component.html

@@ -1,4 +1,4 @@
-<p-panel header="Search Tracks">
+<p-panel header="Search Events">
 	<form class="vertical-form" (ngSubmit)="search($event)">
 		<div class="form-field form-field--full-width">
 			<span class="p-float-label p-input-icon-left">

+ 11 - 1
src/RunnersMeet.Client/src/app/tracks-api.service.ts

@@ -5,6 +5,7 @@ import { ConfigService } from './config.service';
 import { ResultPage } from './result-page';
 import { Track } from './tracks/track';
 import { TrackSearchParams } from './tracks/track-search-params';
+import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
 
 @Injectable({
 	providedIn: 'root'
@@ -13,7 +14,8 @@ export class TracksApiService {
 
 	public constructor(
 		private readonly config: ConfigService,
-		private readonly http: HttpClient
+		private readonly http: HttpClient,
+		private readonly sanitizer: DomSanitizer
 	) { }
 
 	public getTracks(searchParams: TrackSearchParams): Promise<ResultPage<Track>> {
@@ -44,6 +46,14 @@ export class TracksApiService {
 		return this.config.apiUri(`/api/tracks/download/${track.fileHash}`);
 	}
 
+	public getTrackGpxStudioEmbedUrl(track: Track): SafeResourceUrl | null {
+		// See https://gpx.studio/about.html#embed
+		const state = encodeURIComponent(JSON.stringify({
+			urls: [this.getTrackGpxUrl(track)]
+		}));
+		return this.sanitizer.bypassSecurityTrustResourceUrl(`https://gpx.studio/?state=${state}&embed&running&distance&direction`);
+	}
+
 	public downloadTrack(track: Track): Promise<{ blob: Blob | null, filename?: string }> {
 		return lastValueFrom(this.http.get(this.config.apiUri(`/api/tracks/download/${track.fileHash}`), {
 			responseType: 'blob',

+ 3 - 0
src/RunnersMeet.Client/src/app/tracks/map/map.component.html

@@ -0,0 +1,3 @@
+<div class="map-container">
+	<iframe *ngIf="gpxStudioEmbedUrl" [src]="gpxStudioEmbedUrl" width="100%" height="100%" frameborder="0" allowfullscreen></iframe>
+</div>

+ 0 - 0
src/RunnersMeet.Client/src/app/tracks/map/map.component.scss


+ 23 - 0
src/RunnersMeet.Client/src/app/tracks/map/map.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MapComponent } from './map.component';
+
+describe('MapComponent', () => {
+  let component: MapComponent;
+  let fixture: ComponentFixture<MapComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ MapComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(MapComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 27 - 0
src/RunnersMeet.Client/src/app/tracks/map/map.component.ts

@@ -0,0 +1,27 @@
+import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { Track } from '../track';
+import { SafeResourceUrl } from '@angular/platform-browser';
+import { TracksApiService } from 'src/app/tracks-api.service';
+
+@Component({
+  selector: 'app-map',
+  templateUrl: './map.component.html',
+  styleUrls: ['./map.component.scss']
+})
+export class MapComponent implements OnChanges {
+	@Input()
+	public track: Track | null = null;
+	public gpxStudioEmbedUrl: SafeResourceUrl | null = null;
+
+	public constructor(
+		private readonly tracksApi: TracksApiService
+	) {	}
+
+	public ngOnChanges(changes: SimpleChanges): void {
+		if (this.track) {
+			this.gpxStudioEmbedUrl = this.tracksApi.getTrackGpxStudioEmbedUrl(this.track);
+		} else {
+			this.gpxStudioEmbedUrl = null;
+		}
+	}
+}

+ 1 - 3
src/RunnersMeet.Client/src/app/tracks/track-view/track-view.component.html

@@ -20,6 +20,4 @@
 </dl>
 
 <h1>Map</h1>
-<div class="map-container">
-	<iframe *ngIf="gpxStudioEmbedUrl" [src]="gpxStudioEmbedUrl" width="100%" height="100%" frameborder="0" allowfullscreen></iframe>
-</div>
+<app-map [track]="track"></app-map>