diff --git a/angular.json b/angular.json
index 960a8947..22d35c21 100644
--- a/angular.json
+++ b/angular.json
@@ -59,13 +59,19 @@
"tsConfig": "src/frontend/tsconfig.app.json",
"polyfills": "src/frontend/polyfills.ts",
"assets": [
- "src/frontend/assets"
+ "src/frontend/assets",
+ {
+ "glob": "**/*",
+ "input": "node_modules/leaflet/dist/images/",
+ "output": "./"
+ }
],
"styles": [
"bootstrap/dist/css/bootstrap.min.css",
"ngx-bootstrap/datepicker/bs-datepicker.css",
"open-iconic/font/css/open-iconic-bootstrap.css",
"ngx-toastr/toastr.css",
+ "leaflet/dist/leaflet.css",
"src/frontend/styles.css"
],
"scripts": [],
@@ -73,11 +79,8 @@
},
"configurations": {
"dev": {
- "localize": [
- "en",
- "hu"
- ],
- "outputPath": "dist",
+ "outputPath": "dist/en",
+ "localize": false,
"watch": true
},
"production": {
@@ -140,10 +143,16 @@
"bootstrap/dist/css/bootstrap.css",
"open-iconic/font/css/open-iconic-bootstrap.css",
"ngx-bootstrap/datepicker/bs-datepicker.css",
+ "leaflet/dist/leaflet.css",
"src/frontend/styles.css"
],
"assets": [
- "src/frontend/assets"
+ "src/frontend/assets",
+ {
+ "glob": "**/*",
+ "input": "node_modules/leaflet/dist/images/",
+ "output": "./"
+ }
]
}
},
diff --git a/package-lock.json b/package-lock.json
index 47baa963..8779098d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -764,6 +764,12 @@
}
}
},
+ "@asymmetrik/ngx-leaflet": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@asymmetrik/ngx-leaflet/-/ngx-leaflet-8.1.0.tgz",
+ "integrity": "sha512-lq7LduBP/vXcaSEmKnx7mzCR8WsoYqh9pB6BNnq53yeCwsqRbG3GdKye1/i8VvoRzjDsmQBPQsIFZ9uclXrtgg==",
+ "dev": true
+ },
"@babel/code-frame": {
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
@@ -3500,9 +3506,9 @@
"dev": true
},
"@types/leaflet": {
- "version": "1.2.14",
- "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.2.14.tgz",
- "integrity": "sha512-acP2w5DygY0V7bwmjFmaen5I2iBl8RkWx9kon1IJA7k9mNFgBb6702WApjZSrM4AG1ucJVxFcTlS6nr4HvahEw==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.0.tgz",
+ "integrity": "sha512-ltv5jR+VjKSMtoDkxH61Rsbo0zLU7iqyOXpVPkAX4F+79fg2eymC7t0msWsfNaEZO1FGTIQATCCCQe+ijWoicg==",
"dev": true,
"requires": {
"@types/geojson": "*"
@@ -3868,17 +3874,6 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
- "@yaga/leaflet-ng2": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@yaga/leaflet-ng2/-/leaflet-ng2-1.0.0.tgz",
- "integrity": "sha512-8qVI9xophJbMfDeCbHfW91+ksI6snolFV25jw7sg1bpPUVNReWjLGbZEIgshyToppcwKRx0OxHQMb9JvK3bt7w==",
- "dev": true,
- "requires": {
- "@types/geojson": "^7946.0.4",
- "@types/leaflet": "^1.2.8",
- "leaflet": "^1.3.2"
- }
- },
"@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
@@ -12101,9 +12096,9 @@
}
},
"leaflet": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.3.4.tgz",
- "integrity": "sha512-FYL1LGFdj6v+2Ifpw+AcFIuIOqjNggfoLUwuwQv6+3sS21Za7Wvapq+LhbSE4NDXrEj6eYnW3y7LsaBICpyXtw==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz",
+ "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==",
"dev": true
},
"less": {
diff --git a/package.json b/package.json
index 6442e959..960c784b 100644
--- a/package.json
+++ b/package.json
@@ -74,6 +74,7 @@
"@angular/platform-browser": "11.2.9",
"@angular/platform-browser-dynamic": "11.2.9",
"@angular/router": "11.2.9",
+ "@asymmetrik/ngx-leaflet": "^8.1.0",
"@ngx-loading-bar/core": "5.1.1",
"@types/bcrypt": "3.0.1",
"@types/bcryptjs": "2.4.2",
@@ -90,12 +91,12 @@
"@types/image-size": "0.8.0",
"@types/jasmine": "3.6.9",
"@types/jsonwebtoken": "8.5.1",
+ "@types/leaflet": "^1.7.0",
"@types/node": "14.14.37",
"@types/node-geocoder": "3.24.1",
"@types/sharp": "0.23.1",
"@types/winston": "2.4.4",
"@types/xml2js": "0.4.8",
- "@yaga/leaflet-ng2": "1.0.0",
"bootstrap": "4.6.0",
"chai": "4.3.4",
"chai-http": "4.3.0",
@@ -121,6 +122,7 @@
"karma-jasmine-html-reporter": "1.5.4",
"karma-remap-istanbul": "0.6.0",
"karma-systemjs": "0.16.0",
+ "leaflet": "^1.7.1",
"mocha": "8.3.2",
"natural-orderby": "2.0.3",
"ngx-bootstrap": "6.2.0",
diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts
index 2b632f9c..230746e9 100644
--- a/src/frontend/app/app.module.ts
+++ b/src/frontend/app/app.module.ts
@@ -10,7 +10,7 @@ import {FullScreenService} from './ui/gallery/fullscreen.service';
import {AuthenticationService} from './model/network/authentication.service';
import {UserMangerSettingsComponent} from './ui/settings/usermanager/usermanager.settings.component';
import {FrameComponent} from './ui/frame/frame.component';
-import {YagaModule} from '@yaga/leaflet-ng2';
+import { LeafletModule } from '@asymmetrik/ngx-leaflet';
import {LoadingBarModule} from '@ngx-loading-bar/core';
import {GalleryLightboxMediaComponent} from './ui/gallery/lightbox/media/media.lightbox.gallery.component';
import {GalleryPhotoLoadingComponent} from './ui/gallery/grid/photo/loading/loading.photo.grid.gallery.component';
@@ -144,9 +144,9 @@ export class CustomUrlSerializer implements UrlSerializer {
PopoverModule.forRoot(),
BsDropdownModule.forRoot(),
BsDatepickerModule.forRoot(),
- YagaModule,
TimepickerModule.forRoot(),
- LoadingBarModule
+ LoadingBarModule,
+ LeafletModule
],
declarations: [AppComponent,
LoginComponent,
diff --git a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.css b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.css
index d32aa097..54ba5751 100644
--- a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.css
+++ b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.css
@@ -66,6 +66,6 @@
text-decoration: underline;
}
-.keywords .oi-person{
+.keywords .oi-person {
margin-right: 2px;
}
diff --git a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.html b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.html
index 0e476baa..fe647043 100644
--- a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.html
+++ b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.html
@@ -1,4 +1,4 @@
-
+
+
-
-
-
-
-
-
-
+ id="map"
+ leaflet
+ [leafletOptions]="{zoom:10,
+ center:{lat:PositionData.GPSData.latitude,
+ lng:PositionData.GPSData.longitude},
+ layers:[baseLayer],
+ zoomControl: false}"
+ [leafletLayers]="markerLayer">
+
+
diff --git a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts
index c50d5f45..3eb38ed6 100644
--- a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts
+++ b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts
@@ -1,4 +1,4 @@
-import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+import {Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
import {CameraMetadata, PhotoDTO, PhotoMetadata, PositionMetaData} from '../../../../../../common/entities/PhotoDTO';
import {Config} from '../../../../../../common/config/public/Config';
import {MediaDTO, MediaDTOUtils} from '../../../../../../common/entities/MediaDTO';
@@ -8,26 +8,31 @@ import {QueryService} from '../../../../model/query.service';
import {MapService} from '../../map/map.service';
import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes} from '../../../../../../common/entities/SearchQueryDTO';
import {AuthenticationService} from '../../../../model/network/authentication.service';
+import {LatLngLiteral, marker, Marker, TileLayer, tileLayer} from 'leaflet';
@Component({
selector: 'app-info-panel',
styleUrls: ['./info-panel.lightbox.gallery.component.css'],
templateUrl: './info-panel.lightbox.gallery.component.html',
})
-export class InfoPanelLightboxComponent implements OnInit {
+export class InfoPanelLightboxComponent implements OnInit, OnChanges {
@Input() media: MediaDTO;
@Output() closed = new EventEmitter();
public readonly mapEnabled: boolean;
public readonly searchEnabled: boolean;
- keywords: { value: string, type: SearchQueryTypes }[] = null;
- readonly SearchQueryTypes: typeof SearchQueryTypes = SearchQueryTypes;
+ public keywords: { value: string, type: SearchQueryTypes }[] = null;
+ public readonly SearchQueryTypes: typeof SearchQueryTypes = SearchQueryTypes;
+
+ public baseLayer: TileLayer;
+ public markerLayer: Marker[] = [];
constructor(public queryService: QueryService,
public mapService: MapService,
private authService: AuthenticationService) {
this.mapEnabled = Config.Client.Map.enabled;
this.searchEnabled = Config.Client.Search.enabled && this.authService.canSearch();
+ this.baseLayer = tileLayer(mapService.MapLayer, {attribution: mapService.ShortAttributions});
}
get FullPath(): string {
@@ -53,6 +58,15 @@ export class InfoPanelLightboxComponent implements OnInit {
return (this.media as PhotoDTO).metadata.cameraData;
}
+ ngOnChanges(): void {
+ if (this.hasGPS()) {
+ this.markerLayer = [marker({
+ lat: this.PositionData.GPSData.latitude,
+ lng: this.PositionData.GPSData.longitude
+ } as LatLngLiteral)];
+ }
+ }
+
ngOnInit(): void {
const metadata = this.media.metadata as PhotoMetadata;
if ((metadata.keywords && metadata.keywords.length > 0) ||
@@ -101,9 +115,9 @@ export class InfoPanelLightboxComponent implements OnInit {
(this.media as PhotoDTO).metadata.positionData.country);
}
- hasGPS(): number {
- return (this.media as PhotoDTO).metadata.positionData && (this.media as PhotoDTO).metadata.positionData.GPSData &&
- (this.media as PhotoDTO).metadata.positionData.GPSData.latitude && (this.media as PhotoDTO).metadata.positionData.GPSData.longitude;
+ hasGPS(): boolean {
+ return !!((this.media as PhotoDTO).metadata.positionData && (this.media as PhotoDTO).metadata.positionData.GPSData &&
+ (this.media as PhotoDTO).metadata.positionData.GPSData.latitude && (this.media as PhotoDTO).metadata.positionData.GPSData.longitude);
}
getPositionText(): string {
diff --git a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.css b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.css
index 0afd86d5..a813d172 100644
--- a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.css
+++ b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.css
@@ -73,13 +73,13 @@
opacity: 1.0;
}
-.preview-loading {
+::ng-deep .lightbox-map-gallery-component-preview-loading {
background-color: #bbbbbb;
color: #7f7f7f;
font-size: 50px;
}
-.preview-loading span {
+::ng-deep .lightbox-map-gallery-component-preview-loading span {
top: calc(50% - 25px);
left: calc(50% - 25px);
}
diff --git a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html
index 1e9e4e6e..f689a901 100644
--- a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html
+++ b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.html
@@ -6,75 +6,15 @@
[style.top.px]="lightboxDimension.top"
[style.left.px]="lightboxDimension.left"
[style.opacity]="opacity">
+
-
-
-
- 0"
- yaga-overlay-layer="'path'">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ leaflet
+ [leafletOptions]="mapOptions"
+ (leafletMapZoom)="onLeafletZoom()"
+ (leafletMapReady)="onMapReady($event)">
+
diff --git a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts
index 492f3532..ba83588c 100644
--- a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts
+++ b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts
@@ -1,8 +1,8 @@
-import {AfterViewInit, Component, ElementRef, HostListener, Input, OnChanges, ViewChild} from '@angular/core';
+import {Component, ElementRef, HostListener, Input, OnChanges, ViewChild} from '@angular/core';
import {PhotoDTO} from '../../../../../../common/entities/PhotoDTO';
import {Dimension} from '../../../../model/IRenderable';
import {FullScreenService} from '../../fullscreen.service';
-import {IconThumbnail, Thumbnail, ThumbnailManagerService} from '../../thumbnailManager.service';
+import {IconThumbnail, Thumbnail, ThumbnailBase, ThumbnailManagerService} from '../../thumbnailManager.service';
import {MediaIcon} from '../../MediaIcon';
import {Media} from '../../Media';
import {PageHelper} from '../../../../model/page.helper';
@@ -10,15 +10,31 @@ import {FileDTO} from '../../../../../../common/entities/FileDTO';
import {Utils} from '../../../../../../common/Utils';
import {Config} from '../../../../../../common/config/public/Config';
import {MapService} from '../map.service';
-import {LatLng, Point} from 'leaflet';
-import {MapComponent} from '@yaga/leaflet-ng2';
+import {
+ control,
+ Control,
+ icon,
+ LatLng,
+ latLng,
+ latLngBounds,
+ layerGroup,
+ LayerGroup,
+ Map,
+ MapOptions,
+ Marker,
+ marker,
+ Point,
+ polyline,
+ tileLayer
+} from 'leaflet';
+import {LeafletControlLayersConfig} from '@asymmetrik/ngx-leaflet';
@Component({
selector: 'app-gallery-map-lightbox',
styleUrls: ['./lightbox.map.gallery.component.css'],
templateUrl: './lightbox.map.gallery.component.html',
})
-export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
+export class GalleryMapLightboxComponent implements OnChanges {
@Input() photos: PhotoDTO[];
@@ -28,19 +44,46 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
public visible = false;
public controllersVisible = false;
public opacity = 1.0;
- mapPhotos: MapPhoto[] = [];
- paths: LatLng[][] = [];
@ViewChild('root', {static: true}) elementRef: ElementRef;
- @ViewChild('yagaMap', {static: true}) yagaMap: MapComponent;
- public smallIconSize = new Point(Config.Client.Media.Thumbnail.iconSize * 0.75, Config.Client.Media.Thumbnail.iconSize * 0.75);
- public iconSize = new Point(Config.Client.Media.Thumbnail.iconSize, Config.Client.Media.Thumbnail.iconSize);
+ public mapOptions: MapOptions = {
+ zoom: 2,
+ center: latLng(0, 0)
+ };
+ private smallIconSize = new Point(Config.Client.Media.Thumbnail.iconSize * 0.75, Config.Client.Media.Thumbnail.iconSize * 0.75);
+ private iconSize = new Point(Config.Client.Media.Thumbnail.iconSize, Config.Client.Media.Thumbnail.iconSize);
+ private mapLayersControlOption: LeafletControlLayersConfig & { overlays: { Photos: LayerGroup, Paths: LayerGroup } } =
+ {baseLayers: {}, overlays: {Photos: layerGroup([]), Paths: layerGroup([])}};
+
+ private mapLayerControl: Control.Layers;
+ private thumbnailsOnLoad: ThumbnailBase[] = [];
private startPosition: Dimension = null;
+ private leafletMap: Map;
constructor(public fullScreenService: FullScreenService,
private thumbnailService: ThumbnailManagerService,
public mapService: MapService) {
+ this.mapOptions.layers = [this.mapLayersControlOption.overlays.Photos,
+ this.mapLayersControlOption.overlays.Paths];
+ for (let i = 0; i < mapService.Layers.length; ++i) {
+ const l = mapService.Layers[i];
+ const tl = tileLayer(l.url, {attribution: mapService.Attributions});
+ if (i === 0) {
+ this.mapOptions.layers.push(tl);
+ }
+ this.mapLayersControlOption.baseLayers[l.name] = tl;
+ }
+
+ this.mapLayerControl = control.layers(this.mapLayersControlOption.baseLayers,
+ this.mapLayersControlOption.overlays, {position: 'bottomright'});
}
+ private static getScreenWidth(): number {
+ return window.innerWidth;
+ }
+
+ private static getScreenHeight(): number {
+ return window.innerHeight;
+ }
ngOnChanges(): void {
if (this.visible === false) {
@@ -50,37 +93,24 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
}
- ngAfterViewInit(): void {
- // TODO: remove it once yaga/leaflet-ng2 is fixes.
- // See issue: https://github.com/yagajs/leaflet-ng2/issues/440
- let i = 0;
- this.yagaMap.eachLayer((l): void => {
- if (i >= 3 || (this.paths.length === 0 && i >= 2)) {
- this.yagaMap.removeLayer(l);
- }
- ++i;
- });
- }
-
@HostListener('window:resize', ['$event'])
async onResize(): Promise {
this.lightboxDimension = ({
top: 0,
left: 0,
- width: this.getScreenWidth(),
- height: this.getScreenHeight()
+ width: GalleryMapLightboxComponent.getScreenWidth(),
+ height: GalleryMapLightboxComponent.getScreenHeight()
} as Dimension);
this.mapDimension = ({
top: 0,
left: 0,
- width: this.getScreenWidth(),
- height: this.getScreenHeight()
+ width: GalleryMapLightboxComponent.getScreenWidth(),
+ height: GalleryMapLightboxComponent.getScreenHeight()
} as Dimension);
await Utils.wait(0);
- this.yagaMap.invalidateSize();
+ this.leafletMap.invalidateSize();
}
-
public async show(position: Dimension): Promise {
this.hideImages();
this.visible = true;
@@ -91,8 +121,8 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
this.mapDimension = ({
top: 0,
left: 0,
- width: this.getScreenWidth(),
- height: this.getScreenHeight()
+ width: GalleryMapLightboxComponent.getScreenWidth(),
+ height: GalleryMapLightboxComponent.getScreenHeight()
} as Dimension);
this.showImages();
this.centerMap();
@@ -101,11 +131,11 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
this.lightboxDimension = ({
top: 0,
left: 0,
- width: this.getScreenWidth(),
- height: this.getScreenHeight()
+ width: GalleryMapLightboxComponent.getScreenWidth(),
+ height: GalleryMapLightboxComponent.getScreenHeight()
} as Dimension);
await Utils.wait(350);
- this.yagaMap.invalidateSize();
+ this.leafletMap.invalidateSize();
this.centerMap();
this.controllersVisible = true;
}
@@ -116,7 +146,7 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
const to = this.startPosition;
// iff target image out of screen -> scroll to there
- if (PageHelper.ScrollY > to.top || PageHelper.ScrollY + this.getScreenHeight() < to.top) {
+ if (PageHelper.ScrollY > to.top || PageHelper.ScrollY + GalleryMapLightboxComponent.getScreenHeight() < to.top) {
PageHelper.ScrollY = to.top;
}
@@ -127,18 +157,30 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
setTimeout((): void => {
this.visible = false;
this.hideImages();
- this.yagaMap.zoom = 2;
+ this.leafletMap.setZoom(2);
}, 500);
}
showImages(): void {
this.hideImages();
- this.mapPhotos = this.photos.filter((p): number => {
+ this.mapLayersControlOption.overlays.Photos.clearLayers();
+
+ // make sure to enable photos layers when opening map
+ if (this.leafletMap && !this.leafletMap.hasLayer(this.mapLayersControlOption.overlays.Photos)) {
+ this.leafletMap.addLayer(this.mapLayersControlOption.overlays.Photos);
+ }
+ this.thumbnailsOnLoad = [];
+ this.photos.filter((p): number => {
return p.metadata && p.metadata.positionData && p.metadata.positionData.GPSData
&& p.metadata.positionData.GPSData.latitude
&& p.metadata.positionData.GPSData.longitude;
- }).map((p): MapPhoto => {
+ }).forEach((p): void => {
+ const mkr = marker({
+ lat: p.metadata.positionData.GPSData.latitude,
+ lng: p.metadata.positionData.GPSData.longitude
+ });
+ this.mapLayersControlOption.overlays.Photos.addLayer(mkr);
let width = 500;
let height = 500;
const size = p.metadata.size;
@@ -147,30 +189,56 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
} else {
width = height * (size.width / size.height);
}
- const iconTh = this.thumbnailService.getIcon(new MediaIcon(p));
- iconTh.Visible = true;
- const obj: MapPhoto = {
- name: p.name,
- lat: p.metadata.positionData.GPSData.latitude,
- lng: p.metadata.positionData.GPSData.longitude,
- iconThumbnail: iconTh,
- preview: {
- width,
- height,
- thumbnail: this.thumbnailService.getLazyThumbnail(new Media(p, width, height))
- }
+ const photoTh = this.thumbnailService.getLazyThumbnail(new Media(p, width, height));
+ this.thumbnailsOnLoad.push(photoTh);
- };
- if (Config.Client.Map.useImageMarkers === true) {
- if (iconTh.Available === true) {
- obj.iconUrl = iconTh.Src;
+ // Setting popup photo
+ const setPopUpPhoto = () => {
+ const photoPopup = ``;
+ if (!mkr.getPopup()) {
+ mkr.bindPopup(photoPopup, {minWidth: width});
} else {
- iconTh.OnLoad = (): void => {
- obj.iconUrl = iconTh.Src;
- };
+ mkr.setPopupContent(photoPopup);
+ }
+ };
+
+ if (photoTh.Available) {
+ setPopUpPhoto();
+ } else {
+ const noPhotoPopup = `
+
+
+
`;
+
+ mkr.bindPopup(noPhotoPopup, {minWidth: width});
+ mkr.on('popupopen', () => {
+ photoTh.load();
+ photoTh.CurrentlyWaiting = true;
+ });
+ photoTh.OnLoad = setPopUpPhoto;
+ }
+
+ // Setting photo icon
+ if (Config.Client.Map.useImageMarkers === true) {
+ const iconTh = this.thumbnailService.getIcon(new MediaIcon(p));
+ this.thumbnailsOnLoad.push(iconTh);
+ iconTh.Visible = true;
+ const setIcon = () => {
+ mkr.setIcon(icon({
+ iconUrl: iconTh.Src,
+ iconSize: this.iconSize, // size of the icon
+ }));
+ };
+
+ if (iconTh.Available === true) {
+ setIcon();
+ } else {
+ iconTh.OnLoad = setIcon;
}
}
- return obj;
});
if (this.gpxFiles) {
this.loadGPXFiles().catch(console.error);
@@ -184,11 +252,10 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
}
hideImages(): void {
- this.mapPhotos.forEach((mp): void => {
- mp.iconThumbnail.destroy();
- mp.preview.thumbnail.destroy();
+ this.thumbnailsOnLoad.forEach((th): void => {
+ th.destroy();
});
- this.mapPhotos = [];
+ this.thumbnailsOnLoad = [];
}
@HostListener('window:keydown', ['$event'])
@@ -206,20 +273,57 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
this.fullScreenService.showFullScreen(this.elementRef.nativeElement);
}
break;
- case 'Escape': // escape
+ case 'Escape':
this.hide();
break;
}
}
+ onMapReady(map: Map): void {
+ this.leafletMap = map;
+ this.leafletMap.zoomControl.setPosition('bottomright');
+ this.mapLayerControl.addTo(this.leafletMap);
+ }
+
+ onLeafletZoom(): void {
+ (this.mapLayersControlOption.overlays.Photos.getLayers() as Marker[]).forEach(mkr => {
+ if (this.leafletMap.getZoom() < 15) {
+ mkr.getIcon().options.iconSize = this.smallIconSize;
+ mkr.setIcon(mkr.getIcon());
+ } else {
+ mkr.getIcon().options.iconSize = this.iconSize;
+ mkr.setIcon(mkr.getIcon());
+ }
+ });
+ }
+
private centerMap(): void {
- if (this.mapPhotos.length > 0) {
- this.yagaMap.fitBounds(this.mapPhotos as any);
- }
+ this.leafletMap.fitBounds(
+ latLngBounds((this.mapLayersControlOption.overlays.Photos.getLayers() as Marker[])
+ .map(m => m.getLatLng())
+ )
+ );
}
private async loadGPXFiles(): Promise {
- this.paths = [];
+
+ this.mapLayersControlOption.overlays.Paths.clearLayers();
+ if (this.gpxFiles.length === 0) {
+ // remove from controls
+ this.mapLayerControl.removeLayer(this.mapLayersControlOption.overlays.Paths);
+ // remove from map
+ if (this.leafletMap) {
+ this.leafletMap.removeLayer(this.mapLayersControlOption.overlays.Paths);
+ }
+ } else {
+ // make sure it does not appear twice
+ this.mapLayerControl.removeLayer(this.mapLayersControlOption.overlays.Paths);
+ this.mapLayerControl.addOverlay(this.mapLayersControlOption.overlays.Paths, 'Paths');
+ if (this.leafletMap && !this.leafletMap.hasLayer(this.mapLayersControlOption.overlays.Paths)) {
+ this.leafletMap.addLayer(this.mapLayersControlOption.overlays.Paths);
+ }
+ }
+
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < this.gpxFiles.length; i++) {
const file = this.gpxFiles[i];
@@ -230,19 +334,10 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit {
if (path.length === 0) {
continue;
}
- this.paths.push(path as LatLng[]);
+ this.mapLayersControlOption.overlays.Paths.addLayer(marker(path[0] as LatLng));
+ this.mapLayersControlOption.overlays.Paths.addLayer(polyline(path as LatLng[]));
}
}
-
- private getScreenWidth(): number {
- return window.innerWidth;
- }
-
- private getScreenHeight(): number {
- return window.innerHeight;
- }
-
-
}
export interface MapPhoto {
diff --git a/src/frontend/app/ui/gallery/map/map.gallery.component.css b/src/frontend/app/ui/gallery/map/map.gallery.component.css
index 476f4b4f..176cb91e 100644
--- a/src/frontend/app/ui/gallery/map/map.gallery.component.css
+++ b/src/frontend/app/ui/gallery/map/map.gallery.component.css
@@ -1,4 +1,4 @@
-.yaga-map{
+.map{
/*z-index: 0;*/
width: 100%;
height: 100%;
diff --git a/src/frontend/app/ui/gallery/map/map.gallery.component.html b/src/frontend/app/ui/gallery/map/map.gallery.component.html
index 9d12a232..4cf4d29b 100644
--- a/src/frontend/app/ui/gallery/map/map.gallery.component.html
+++ b/src/frontend/app/ui/gallery/map/map.gallery.component.html
@@ -1,26 +1,13 @@
-0">
+0">
diff --git a/src/frontend/app/ui/gallery/map/map.gallery.component.ts b/src/frontend/app/ui/gallery/map/map.gallery.component.ts
index 0d1022f4..96fc560f 100644
--- a/src/frontend/app/ui/gallery/map/map.gallery.component.ts
+++ b/src/frontend/app/ui/gallery/map/map.gallery.component.ts
@@ -1,82 +1,74 @@
-import {AfterViewInit, Component, ElementRef, Input, OnChanges, ViewChild} from '@angular/core';
+import {Component, ElementRef, Input, OnChanges, ViewChild} from '@angular/core';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {Dimension, IRenderable} from '../../../model/IRenderable';
import {GalleryMapLightboxComponent} from './lightbox/lightbox.map.gallery.component';
import {FileDTO} from '../../../../../common/entities/FileDTO';
import {MapService} from './map.service';
-import {MapComponent} from '@yaga/leaflet-ng2';
import {Config} from '../../../../../common/config/public/Config';
+import {LatLngLiteral, Map, MapOptions, Marker, marker, tileLayer} from 'leaflet';
@Component({
selector: 'app-gallery-map',
templateUrl: './map.gallery.component.html',
styleUrls: ['./map.gallery.component.css']
})
-export class GalleryMapComponent implements OnChanges, IRenderable, AfterViewInit {
+export class GalleryMapComponent implements OnChanges, IRenderable {
@Input() photos: PhotoDTO[];
@Input() gpxFiles: FileDTO[];
@ViewChild(GalleryMapLightboxComponent, {static: false}) mapLightbox: GalleryMapLightboxComponent;
-
- mapPhotos: Array<{ lat: number, lng: number }> = [];
@ViewChild('map', {static: false}) mapElement: ElementRef;
- @ViewChild('yagaMap', {static: false}) yagaMap: MapComponent;
-// height: number = null;
+ leafletMap: Map;
+
+
+ options: MapOptions = {
+ zoomControl: false,
+ dragging: false,
+ keyboard: false,
+ tap: false,
+ doubleClickZoom: false,
+ boxZoom: false,
+ zoom: 0,
+ };
+ markerLayer: Marker[] = [];
constructor(public mapService: MapService) {
+ this.options.layers = [
+ tileLayer(mapService.MapLayer, {attribution: mapService.ShortAttributions})
+ ];
}
- get EnableMapPreview(): boolean {
- /**
- * Disabling map preview on IOS as safari has issues handling z-index of leaflet (yaga-maps)
- * Details https://github.com/bpatrik/pigallery2/issues/155
- * TODO: re enable it once yaga-maps is fixed
- */
- const isIOS = [
- 'iPad Simulator',
- 'iPhone Simulator',
- 'iPod Simulator',
- 'iPad',
- 'iPhone',
- 'iPod'
- ].includes(navigator.platform)
- // iPad on iOS 13 detection
- || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
-
- return !isIOS;
+ onMapReady(map: Map): void {
+ this.leafletMap = map;
+ this.leafletMap.setView(this.markerLayer[0].getLatLng(), 99);
+ this.leafletMap.fitBounds(this.markerLayer.map((mp): [number, number] =>
+ [mp.getLatLng().lat, mp.getLatLng().lng] as [number, number]));
+ this.leafletMap.setZoom(0);
}
ngOnChanges(): void {
- this.mapPhotos = this.photos.filter((p): number => {
+ this.markerLayer = this.photos.filter((p): number => {
return p.metadata && p.metadata.positionData && p.metadata.positionData.GPSData &&
p.metadata.positionData.GPSData.latitude && p.metadata.positionData.GPSData.longitude;
- }).slice(0, Config.Client.Map.maxPreviewMarkers).map((p): { lng: number; lat: number } => {
- return {
+ }).slice(0, Config.Client.Map.maxPreviewMarkers).map((p): Marker => {
+ return marker({
lat: p.metadata.positionData.GPSData.latitude,
lng: p.metadata.positionData.GPSData.longitude
- };
+ } as LatLngLiteral);
});
- if (this.yagaMap && this.mapPhotos.length > 0) {
- this.yagaMap.setView(this.mapPhotos[0], 99);
- this.yagaMap.fitBounds(this.mapPhotos.map((mp): [number, number] => [mp.lat, mp.lng] as [number, number]));
- this.yagaMap.zoom = 0;
+ if (this.leafletMap && this.markerLayer.length > 0) {
+ this.options.center = this.markerLayer[0].getLatLng();
+ this.leafletMap.setView(this.markerLayer[0].getLatLng(), 99);
+ this.leafletMap.fitBounds(this.markerLayer.map((mp): [number, number] =>
+ [mp.getLatLng().lat, mp.getLatLng().lng] as [number, number]));
+ this.leafletMap.setZoom(0);
}
}
- ngAfterViewInit(): void {
- setTimeout((): void => {
- // this.height = this.mapElement.nativeElement.clientHeight;
- this.yagaMap.setView(this.mapPhotos[0], 99);
- this.yagaMap.fitBounds(this.mapPhotos.map((mp): [number, number] => [mp.lat, mp.lng] as [number, number]));
- this.yagaMap.zoom = 0;
- }, 0);
- }
-
-
click(): void {
this.mapLightbox.show(this.getDimension());
}
diff --git a/src/frontend/app/ui/gallery/map/map.service.ts b/src/frontend/app/ui/gallery/map/map.service.ts
index 2dc1912e..4e98aba2 100644
--- a/src/frontend/app/ui/gallery/map/map.service.ts
+++ b/src/frontend/app/ui/gallery/map/map.service.ts
@@ -25,37 +25,33 @@ export class MapService {
];
}
- public get ShortAttributions(): string[] {
- const yaga = 'YAGA';
- const lf = 'leaflet-ng2';
+ public get ShortAttributions(): string {
const OSM = 'OSM';
const MB = 'Mapbox';
if (Config.Client.Map.mapProvider === MapProviders.OpenStreetMap) {
- return [yaga + ' | © ' + OSM];
+ return ' © ' + OSM;
}
if (Config.Client.Map.mapProvider === MapProviders.Mapbox) {
- return [yaga + ' | ' + OSM + ' | ' + MB];
+ return OSM + ' | ' + MB;
}
- return [yaga + ' | ' + lf];
+ return '';
}
- public get Attributions(): string[] {
- const yagalf = 'YAGA | ' +
- 'leaflet-ng2';
+ public get Attributions(): string {
const OSM = '© OpenStreetMap';
const MB = '© Mapbox';
if (Config.Client.Map.mapProvider === MapProviders.OpenStreetMap) {
- return [yagalf + ' | ' + OSM];
+ return OSM;
}
if (Config.Client.Map.mapProvider === MapProviders.Mapbox) {
- return [yagalf + ' | ' + OSM + ' | ' + MB];
+ return OSM + ' | ' + MB;
}
- return [yagalf];
+ return '';
}
public get MapLayer(): string {
diff --git a/src/frontend/index.html b/src/frontend/index.html
index 130d77ea..97f52c52 100644
--- a/src/frontend/index.html
+++ b/src/frontend/index.html
@@ -14,9 +14,7 @@
-
+