Pārlūkot izejas kodu

Track view with gpx.studio integration

Lukas Angerer 3 gadi atpakaļ
vecāks
revīzija
81dd6987f9

+ 6 - 0
src/RunnersMeet.Client/src/app/app-routing.module.ts

@@ -4,6 +4,7 @@ import { AuthGuard } from '@auth0/auth0-angular';
 import { EditTrackPageComponent } from './pages/edit-track-page/edit-track-page.component';
 import { HomePageComponent } from './pages/home-page/home-page.component';
 import { TracksPageComponent } from './pages/tracks-page/tracks-page.component';
+import { ViewTrackPageComponent } from './pages/view-track-page/view-track-page.component';
 
 const routes: Routes = [
 	{
@@ -20,6 +21,11 @@ const routes: Routes = [
 		component: EditTrackPageComponent,
 		canActivate: [AuthGuard],
 	},
+	{
+		path: 'tracks/view/:oid',
+		component: ViewTrackPageComponent,
+		canActivate: [AuthGuard],
+	},
 ];
 
 @NgModule({

+ 2 - 0
src/RunnersMeet.Client/src/app/app.module.ts

@@ -15,6 +15,7 @@ import { TrackCreateComponent } from './tracks/track-create/track-create.compone
 import { TrackListItemComponent } from './tracks/track-list-item/track-list-item.component';
 import { TrackEditComponent } from './tracks/track-edit/track-edit.component';
 import { TrackViewComponent } from './tracks/track-view/track-view.component';
+import { ViewTrackPageComponent } from './pages/view-track-page/view-track-page.component';
 
 @NgModule({
 	declarations: [
@@ -26,6 +27,7 @@ import { TrackViewComponent } from './tracks/track-view/track-view.component';
 		TrackListItemComponent,
 		TrackEditComponent,
 		TrackViewComponent,
+		ViewTrackPageComponent,
 	],
 	imports: [
 		BrowserModule,

+ 1 - 0
src/RunnersMeet.Client/src/app/pages/view-track-page/view-track-page.component.html

@@ -0,0 +1 @@
+<app-track-view [trackId]="trackId"></app-track-view>

+ 0 - 0
src/RunnersMeet.Client/src/app/pages/view-track-page/view-track-page.component.scss


+ 23 - 0
src/RunnersMeet.Client/src/app/pages/view-track-page/view-track-page.component.spec.ts

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

+ 18 - 0
src/RunnersMeet.Client/src/app/pages/view-track-page/view-track-page.component.ts

@@ -0,0 +1,18 @@
+import { Component, Input } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+@Component({
+	selector: 'app-view-track-page',
+	templateUrl: './view-track-page.component.html',
+	styleUrls: ['./view-track-page.component.scss']
+})
+export class ViewTrackPageComponent {
+	public trackId: string = '';
+
+	public constructor(route: ActivatedRoute) {
+		route.params.subscribe(params => {
+			const oid = params['oid'];
+			this.trackId = oid;
+		});
+	}
+}

+ 1 - 0
src/RunnersMeet.Client/src/app/tracks/track-list-item/track-list-item.component.html

@@ -1,4 +1,5 @@
 {{ track?.trackId }} - {{ track?.displayName }} - {{ track?.fileHash }}<br />
 ↔{{ track?.distance }}m ↑{{ track?.elevationUp }}m ↓{{ track?.elevationDown }}m<br />
+<a [routerLink]="['/tracks/view', track?.trackId]">View</a> &mdash;
 <a [routerLink]="['/tracks/edit', track?.trackId]">Edit</a> &mdash;
 <a [href]="downloadUrl" target="_blank">Download</a>

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

@@ -1 +1,24 @@
-<p>track-view works!</p>
+<div>
+	<label>ID:</label> {{ track.trackId }}
+</div>
+<div>
+	<label>Owner:</label> {{ track.owner }}
+</div>
+<div>
+	<label>File Hash:</label> {{ track.fileHash }}
+</div>
+<div>
+	<label>Display Name:</label> {{ track.displayName }}
+</div>
+<div>
+	<label>Distance (m):</label> {{ track.distance }}
+</div>
+<div>
+	<label>Elevation up (m):</label> {{ track.elevationUp }}
+</div>
+<div>
+	<label>Elevation down (m):</label> {{ track.elevationDown }}
+</div>
+<div>
+<iframe [src]="gpxStudioEmbedUrl" width="100%" height="500" frameborder="0" allowfullscreen></iframe>
+</div>

+ 33 - 10
src/RunnersMeet.Client/src/app/tracks/track-view/track-view.component.ts

@@ -1,10 +1,33 @@
-import { Component } from '@angular/core';
-
-@Component({
-  selector: 'app-track-view',
-  templateUrl: './track-view.component.html',
-  styleUrls: ['./track-view.component.scss']
-})
-export class TrackViewComponent {
-
-}
+import { Component, Input } from '@angular/core';
+import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
+import { TracksApiService } from 'src/app/tracks-api.service';
+import { Track } from '../track';
+
+@Component({
+  selector: 'app-track-view',
+  templateUrl: './track-view.component.html',
+  styleUrls: ['./track-view.component.scss']
+})
+export class TrackViewComponent {
+	@Input()
+	public trackId: string = '';
+
+	public track: Track = {} as Track;
+	public gpxStudioEmbedUrl: SafeResourceUrl | null = null;
+
+	public constructor(
+		private readonly tracksApi: TracksApiService,
+		private readonly sanitizer: DomSanitizer
+	) {	}
+
+	public ngOnInit(): void {
+		this.tracksApi.getTrack(this.trackId).then(track => {
+			this.track = track;
+			// See https://gpx.studio/about.html#embed
+			const state = encodeURIComponent(JSON.stringify({
+				urls: [this.tracksApi.getTrackGpxUrl(this.track)]
+			}));
+			this.gpxStudioEmbedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(`https://gpx.studio/?state=${state}&embed&running&distance&direction`);
+		});
+	}
+}

+ 1 - 1
src/RunnersMeet.Server/AppServer.cs

@@ -25,7 +25,7 @@ public class AppServer
 		{
 			options.AddDefaultPolicy(policy  =>
 			{
-				policy.WithOrigins("http://localhost:4200");
+				policy.WithOrigins("http://localhost:4200", "https://gpx.studio");
 				policy.WithHeaders("Authorization", "Content-Type");
 				policy.AllowAnyMethod();
 				policy.WithExposedHeaders("Content-Disposition");