diff --git a/src/app/map-location/map-location-list/map-location-list.component.ts b/src/app/map-location/map-location-list/map-location-list.component.ts
index 14e0a57..353d957 100644
--- a/src/app/map-location/map-location-list/map-location-list.component.ts
+++ b/src/app/map-location/map-location-list/map-location-list.component.ts
@@ -1,4 +1,4 @@
-import {Component, ElementRef, HostListener, Input, OnInit, Renderer2, ViewChild} from '@angular/core';
+import {Component, ElementRef, Input, OnInit, Renderer2, ViewChild} from '@angular/core';
import {MapLocationService} from "../map-location.service";
import {maxPageSize} from "../../shared/http.config";
import {Route} from "../../route/route.model";
@@ -12,6 +12,8 @@ import {AudioService} from "../../audio/audio.service";
import {Audio} from "../../audio/audio.model";
import {DomSanitizer, SafeUrl} from "@angular/platform-browser";
import {ScreenSizeService} from "../../shared/screen-size.service";
+import { forkJoin } from 'rxjs';
+import { map } from 'rxjs/operators';
@Component({
selector: 'app-map-location-list',
@@ -30,64 +32,92 @@ export class MapLocationListComponent implements OnInit {
@Input() route: Route;
mapLocations: MapLocation[];
+ mapLocationsAndImages: { mapLocation: MapLocation, url: SafeUrl }[] = [];
activeMapLocationId: string;
audiosEntities: Audio[] = [];
- audiosUrls: SafeUrl[] = [];
audioData: { audio: Audio, url: SafeUrl }[] = [];
-
mobileVersion: boolean;
+ @ViewChild('info') infoWrapper: ElementRef;
+
constructor(private mapService: MapService,
private sidePanelService: SidePanelService,
private mapLocationService: MapLocationService,
private audioService: AudioService,
private sanitizer: DomSanitizer,
private renderer: Renderer2,
- private screenSizeService: ScreenSizeService) {
- }
-
-
- @ViewChild('info') infoWrapper: ElementRef;
+ private screenSizeService: ScreenSizeService) { }
ngOnInit(): void {
-
this.screenSizeService.isMobileVersion$.subscribe(isMobileVersion => {
this.mobileVersion = isMobileVersion;
});
+ //subscribe to event emitted by map location in map info window
this.mapService.mapLocationDetailsEventEmitter.subscribe(mapLocation => {
this.onMapLocationSelected(mapLocation);
-
-
this.sidePanelService.togglePanelEventEmitter.emit(true);
+ this.scrollToInfoWrapper();
+ });
+ this.fetchMapLocations();
+ }
-
-
+ //scroll to map location info and animate it
+ private scrollToInfoWrapper() {
+ if (this.infoWrapper?.nativeElement) {
this.infoWrapper.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ this.renderer.addClass(this.infoWrapper.nativeElement, 'animation');
+ this.infoWrapper.nativeElement.addEventListener('animationend', () => {
+ this.renderer.removeClass(this.infoWrapper.nativeElement, 'animation');
+ }, { once: true });
+ }
+ }
- if (this.infoWrapper.nativeElement) {
- this.renderer.addClass(this.infoWrapper.nativeElement, 'animation');
- this.infoWrapper.nativeElement.addEventListener('animationend', () => {
- this.renderer.removeClass(this.infoWrapper.nativeElement, 'animation');
- }, { once: true });
- }
- })
-
-
+ //fetch map locations and their images
+ private fetchMapLocations() {
this.mapLocationService.getMapLocationsByRoute(0, maxPageSize, this.route.id)
.subscribe(response => {
this.mapLocations = response.content;
+ this.loadImagesForMapLocations();
this.mapService.routeSelectedEventEmitter.emit(this.mapLocations);
});
+ }
+ //fetch images for map locations
+ private loadImagesForMapLocations() {
+ const imageRequests = this.mapLocations.map(ml => {
+ return this.mapLocationService.getMapLocationImageById(ml.id).pipe(
+ map(response => {
+ if (response) {
+ const objectURL = URL.createObjectURL(response);
+ const imageUrl = this.sanitizer.bypassSecurityTrustUrl(objectURL);
+ return { mapLocation: ml, url: imageUrl };
+ } else {
+ return { mapLocation: ml, url: null };
+ }
+ })
+ );
+ });
+ //execute all requests concurrently and wait for their execution
+ forkJoin(imageRequests).subscribe({
+ next: (results) => {
+ this.mapLocationsAndImages = results;
+ },
+ error: (error) => {
+ console.error('Error loading images:', error);
+ }
+ });
}
onMapLocationSelected(mapLocation: MapLocation) {
this.mapService.centerOnMapLocation.emit(mapLocation);
- if(this.activeMapLocationId != mapLocation.id) {
+ if(this.activeMapLocationId == mapLocation.id) {
+ this.activeMapLocationId = null;
+ }
+ else {
this.activeMapLocationId = mapLocation.id;
if (this.mobileVersion) {
this.sidePanelService.togglePanelEventEmitter.emit(false);
@@ -120,10 +150,8 @@ export class MapLocationListComponent implements OnInit {
});
Promise.all(audioPromises).then(() => {
- //All audio files fetched and URLs are set
+ // All audio files fetched and URLs are set
});
});
}
-
-
}
diff --git a/src/app/map-location/map-location.service.ts b/src/app/map-location/map-location.service.ts
index 002a0e0..b3b94ef 100644
--- a/src/app/map-location/map-location.service.ts
+++ b/src/app/map-location/map-location.service.ts
@@ -1,8 +1,9 @@
-import { HttpClient, HttpParams } from "@angular/common/http";
+import {HttpClient, HttpErrorResponse, HttpParams} from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Page } from "../shared/page.model";
import { MapLocation } from "./map-location.model";
import { backendUrl } from "../shared/http.config";
+import {catchError, of} from "rxjs";
@Injectable({ providedIn: 'root' })
export class MapLocationService {
@@ -30,6 +31,17 @@ export class MapLocationService {
return this.http.put(url, formData);
}
+ getMapLocationImageById(mapLocationId: string) {
+ const url = `${backendUrl}/mapLocations/${mapLocationId}/image`;
+ return this.http.get(url, {responseType: 'blob'}).pipe(
+ catchError((error: HttpErrorResponse) => {
+ console.error('Error fetching image:', error);
+ return of(null);
+ })
+ );
+
+ }
+
}
diff --git a/src/app/route/route-info/route-info.component.css b/src/app/route/route-info/route-info.component.css
index b1711ba..db91755 100644
--- a/src/app/route/route-info/route-info.component.css
+++ b/src/app/route/route-info/route-info.component.css
@@ -1,21 +1,57 @@
+.flex-item {
+ text-align: center;
+}
+
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
- justify-content: center;
+ justify-content: space-around;
width: 100%;
}
-.flex-item {
- flex: 1 1 auto;
- text-align: center;
+
+.route-button {
+ height: 30px;
+ width: 30px;
+ background-color: white;
+ color: #10898d;
+ margin-left: 10px;
+ font-size: 2.5rem;
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
+.background-animation {
+ animation: background-change 1s infinite;
+ animation-duration: 1s;
+}
+
+@keyframes background-change {
+ 0% {
+ background-color: #10898d;
+
+ }
+ 50% {
+ background-color: #046169;
+
+ }
+ 100% {
+ background-color: #10898d;
+
+ }
+}
@media (max-width: 900px) {
* {
font-size: 1rem;
}
+
+ .route-button {
+ height: 20px;
+ width: 20px;
+ }
}
diff --git a/src/app/route/route-info/route-info.component.html b/src/app/route/route-info/route-info.component.html
index 4e51668..1ecf34a 100644
--- a/src/app/route/route-info/route-info.component.html
+++ b/src/app/route/route-info/route-info.component.html
@@ -1,15 +1,22 @@
-
+
diff --git a/src/app/route/route-list/route-list.component.css b/src/app/route/route-list/route-list.component.css
index 37fe65d..9d40ddb 100644
--- a/src/app/route/route-list/route-list.component.css
+++ b/src/app/route/route-list/route-list.component.css
@@ -57,7 +57,17 @@
color: azure;
}
-
+.route-button {
+ height: 30px;
+ width: 30px;
+ background-color: white;
+ color: #10898d;
+ margin-left: 10px;
+ font-size: 2.5rem;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
@media (max-width: 900px) {
* {
@@ -67,6 +77,11 @@
.list-group-item {
height: 6dvh;
}
+
+ .route-button {
+ height: 20px;
+ width: 20px;
+ }
}
@media (max-width: 320px) {
@@ -76,4 +91,11 @@
.flex-item:nth-child(3) {
order: 2;
}
+
+ .route-button {
+ height: 20px;
+ width: 20px;
+ }
}
+
+
diff --git a/src/app/route/route-list/route-list.component.html b/src/app/route/route-list/route-list.component.html
index 202973c..cdb13cb 100644
--- a/src/app/route/route-list/route-list.component.html
+++ b/src/app/route/route-list/route-list.component.html
@@ -1,8 +1,8 @@
-
@@ -31,8 +31,15 @@
[routerLink]="[routeIt.id]"
[queryParams]="{ page: currentPageNumber }"
class="list-group-item"
- routerLinkActive="active">
+ routerLinkActive="active"
+ #rla="routerLinkActive">
+
+
+
+
+
diff --git a/src/app/route/route-list/route-list.component.ts b/src/app/route/route-list/route-list.component.ts
index db1ef2e..7d0d173 100644
--- a/src/app/route/route-list/route-list.component.ts
+++ b/src/app/route/route-list/route-list.component.ts
@@ -1,7 +1,7 @@
import {Component} from '@angular/core';
import {Route} from "../route.model";
import {RouteService} from "../route.service";
-import {NgForOf} from "@angular/common";
+import {NgForOf, NgIf} from "@angular/common";
import {RouteItemComponent} from "./route-item/route-item.component";
import {ActivatedRoute, Router, RouterLink, RouterLinkActive, RouterOutlet} from "@angular/router";
import {MapLocationService} from "../../map-location/map-location.service";
@@ -19,7 +19,8 @@ import {FormsModule} from "@angular/forms";
RouterLinkActive,
RouterLink,
RouterOutlet,
- FormsModule
+ FormsModule,
+ NgIf
],
templateUrl: './route-list.component.html',
styleUrl: './route-list.component.css'