mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-01-02 03:37:54 +02:00
migrating maps to ngx-leaflet #256
This commit is contained in:
parent
f0f47f96bb
commit
4f2b02b7e0
23
angular.json
23
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": "./"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
29
package-lock.json
generated
29
package-lock.json
generated
@ -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": {
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -66,6 +66,6 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.keywords .oi-person{
|
||||
.keywords .oi-person {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="content">
|
||||
<div class="content d-flex flex-column">
|
||||
<div class="modal-header">
|
||||
<h2 class="modal-title" i18n>Info</h2>
|
||||
<button type="button" class="close" (click)="close()" aria-label="Close">
|
||||
@ -90,19 +90,19 @@
|
||||
<span class="details-icon oi oi-tags"></span>
|
||||
</div>
|
||||
<div class="col-10 keywords">
|
||||
<ng-template ngFor let-keyword [ngForOf]="keywords" let-last="last">
|
||||
<a *ngIf="searchEnabled"
|
||||
[routerLink]="['/search', getTextSearchQuery(keyword.value,keyword.type)]" [ngSwitch]="keyword.type">
|
||||
<ng-template [ngSwitchCase]="SearchQueryTypes.keyword">#</ng-template><!--
|
||||
<ng-template ngFor let-keyword [ngForOf]="keywords" let-last="last">
|
||||
<a *ngIf="searchEnabled"
|
||||
[routerLink]="['/search', getTextSearchQuery(keyword.value,keyword.type)]" [ngSwitch]="keyword.type">
|
||||
<ng-template [ngSwitchCase]="SearchQueryTypes.keyword">#</ng-template><!--
|
||||
-->
|
||||
<ng-template [ngSwitchCase]="SearchQueryTypes.person"><span class="oi oi-person"></span></ng-template><!--
|
||||
<ng-template [ngSwitchCase]="SearchQueryTypes.person"><span class="oi oi-person"></span></ng-template><!--
|
||||
-->{{keyword.value}}</a>
|
||||
<span *ngIf="!searchEnabled" [ngSwitch]="keyword.type">
|
||||
<span *ngIf="!searchEnabled" [ngSwitch]="keyword.type">
|
||||
<ng-template [ngSwitchCase]="SearchQueryTypes.keyword">#</ng-template><!--
|
||||
--><ng-template [ngSwitchCase]="SearchQueryTypes.person"><span class="oi oi-person"></span></ng-template><!--
|
||||
-->{{keyword.value}}</span>
|
||||
<ng-template [ngIf]="!last">, </ng-template>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="!last">, </ng-template>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -123,20 +123,19 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-auto" style="height: 400px">
|
||||
<div
|
||||
*ngIf="hasGPS() && mapEnabled"
|
||||
|
||||
<div id="map" *ngIf="hasGPS() && mapEnabled">
|
||||
<yaga-map [zoom]="10"
|
||||
[lat]="PositionData.GPSData.latitude"
|
||||
[lng]="PositionData.GPSData.longitude">
|
||||
<yaga-marker
|
||||
[lat]="PositionData.GPSData.latitude"
|
||||
[lng]="PositionData.GPSData.longitude">
|
||||
</yaga-marker>
|
||||
<yaga-attribution-control
|
||||
prefix=""
|
||||
[attributions]="mapService.Attributions">
|
||||
</yaga-attribution-control>
|
||||
<yaga-tile-layer [url]="mapService.MapLayer"></yaga-tile-layer>
|
||||
</yaga-map>
|
||||
id="map"
|
||||
leaflet
|
||||
[leafletOptions]="{zoom:10,
|
||||
center:{lat:PositionData.GPSData.latitude,
|
||||
lng:PositionData.GPSData.longitude},
|
||||
layers:[baseLayer],
|
||||
zoomControl: false}"
|
||||
[leafletLayers]="markerLayer">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -6,75 +6,15 @@
|
||||
[style.top.px]="lightboxDimension.top"
|
||||
[style.left.px]="lightboxDimension.left"
|
||||
[style.opacity]="opacity">
|
||||
<div
|
||||
[style.width.px]="mapDimension.width"
|
||||
[style.height.px]="mapDimension.height"
|
||||
|
||||
<yaga-map #yagaMap
|
||||
[style.width.px]="mapDimension.width"
|
||||
[style.height.px]="mapDimension.height">
|
||||
|
||||
<yaga-layers-control
|
||||
position="bottomright">
|
||||
|
||||
<yaga-feature-group
|
||||
[caption]="'path'"
|
||||
*ngIf="paths.length>0"
|
||||
yaga-overlay-layer="'path'">
|
||||
<yaga-polyline
|
||||
*ngFor="let path of paths"
|
||||
[latLngs]="path">
|
||||
</yaga-polyline>
|
||||
<yaga-marker
|
||||
*ngFor="let path of paths"
|
||||
[lat]="path[0].lat"
|
||||
[lng]="path[1].lng">
|
||||
</yaga-marker>
|
||||
</yaga-feature-group>
|
||||
<yaga-feature-group
|
||||
[caption]="'photos'"
|
||||
yaga-overlay-layer="'photos'">
|
||||
<yaga-marker [title]="photo.name"
|
||||
*ngFor="let photo of mapPhotos"
|
||||
[lat]="photo.lat"
|
||||
[lng]="photo.lng">
|
||||
<yaga-icon
|
||||
*ngIf="photo.iconUrl"
|
||||
[iconUrl]="photo.iconUrl"
|
||||
[iconSize]="yagaMap.zoom < 15 ? smallIconSize : iconSize"
|
||||
></yaga-icon>
|
||||
<yaga-popup
|
||||
(open)="loadPreview(photo)"
|
||||
[minWidth]="photo.preview.width">
|
||||
<img *ngIf="photo.preview.thumbnail.Src"
|
||||
[style.width.px]="photo.preview.width"
|
||||
[style.height.px]="photo.preview.height"
|
||||
[src]="photo.preview.thumbnail.Src">
|
||||
<div class="preview-loading"
|
||||
*ngIf="!photo.preview.thumbnail.Src"
|
||||
[style.width.px]="photo.preview.width"
|
||||
[style.height.px]="photo.preview.height">
|
||||
<span class="oi"
|
||||
[ngClass]="photo.preview.thumbnail.Error ? 'oi-warning' : 'oi-picture'"
|
||||
aria-hidden="true">
|
||||
</span>
|
||||
</div>
|
||||
</yaga-popup>
|
||||
</yaga-marker>
|
||||
|
||||
</yaga-feature-group>
|
||||
<ng-container *ngFor="let l of mapService.Layers">
|
||||
<yaga-tile-layer yaga-base-layer
|
||||
[caption]="l.name"
|
||||
[url]="l.url"></yaga-tile-layer>
|
||||
</ng-container>
|
||||
|
||||
</yaga-layers-control>
|
||||
<yaga-zoom-control position="bottomright">
|
||||
|
||||
</yaga-zoom-control>
|
||||
<yaga-attribution-control
|
||||
prefix=""
|
||||
[attributions]="mapService.Attributions">
|
||||
</yaga-attribution-control>
|
||||
</yaga-map>
|
||||
leaflet
|
||||
[leafletOptions]="mapOptions"
|
||||
(leafletMapZoom)="onLeafletZoom()"
|
||||
(leafletMapReady)="onMapReady($event)">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -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<void> {
|
||||
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<void> {
|
||||
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 = `<img style="width: ${width}px; height: ${height}px" ` +
|
||||
`src="${photoTh.Src}" alt="preview">`;
|
||||
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 = `<div class="lightbox-map-gallery-component-preview-loading"
|
||||
style="width: ${width}px; height: ${height}px">
|
||||
<span class="oi ${photoTh.Error ? 'oi-warning' : 'oi-image'}"
|
||||
aria-hidden="true">
|
||||
</span>
|
||||
</div>`;
|
||||
|
||||
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<void> {
|
||||
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 {
|
||||
|
@ -1,4 +1,4 @@
|
||||
.yaga-map{
|
||||
.map{
|
||||
/*z-index: 0;*/
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -1,26 +1,13 @@
|
||||
<ng-template [ngIf]="mapPhotos.length>0">
|
||||
<ng-template [ngIf]="markerLayer.length>0">
|
||||
<app-gallery-map-lightbox [photos]="photos" [gpxFiles]="gpxFiles"></app-gallery-map-lightbox>
|
||||
<div class="clickable" id="map" #map (click)="click()">
|
||||
<span *ngIf="!EnableMapPreview" class="oi-map oi"></span>
|
||||
<yaga-map
|
||||
*ngIf="EnableMapPreview"
|
||||
#yagaMap
|
||||
[draggingEnabled]="false"
|
||||
[keyboardEnabled]="false"
|
||||
[tapEnabled]="false"
|
||||
[boxZoomEnabled]="false"
|
||||
[doubleClickZoomEnabled]="false">
|
||||
<yaga-marker
|
||||
*ngFor="let photo of mapPhotos"
|
||||
[lat]="photo.lat"
|
||||
[lng]="photo.lng">
|
||||
</yaga-marker>
|
||||
<yaga-attribution-control
|
||||
prefix=""
|
||||
[attributions]="mapService.ShortAttributions">
|
||||
</yaga-attribution-control>
|
||||
<yaga-tile-layer [url]="mapService.MapLayer"></yaga-tile-layer>
|
||||
</yaga-map>
|
||||
<div
|
||||
class="map"
|
||||
leaflet
|
||||
[leafletOptions]="options"
|
||||
[leafletLayers]="markerLayer"
|
||||
(leafletMapReady)="onMapReady($event)">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -25,37 +25,33 @@ export class MapService {
|
||||
];
|
||||
}
|
||||
|
||||
public get ShortAttributions(): string[] {
|
||||
const yaga = '<a href="https://yagajs.org" title="YAGA">YAGA</a>';
|
||||
const lf = '<a href="https://leaflet-ng2.yagajs.org" title="Leaflet in Angular2">leaflet-ng2</a>';
|
||||
public get ShortAttributions(): string {
|
||||
const OSM = '<a href="https://www.openstreetmap.org/copyright">OSM</a>';
|
||||
const MB = '<a href="https://www.mapbox.com/">Mapbox</a>';
|
||||
|
||||
|
||||
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 = '<a href="https://yagajs.org" title="YAGA">YAGA</a> | ' +
|
||||
'<a href="https://leaflet-ng2.yagajs.org" title="Leaflet in Angular2">leaflet-ng2</a>';
|
||||
public get Attributions(): string {
|
||||
const OSM = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>';
|
||||
const MB = '© <a href="https://www.mapbox.com/">Mapbox</a>';
|
||||
|
||||
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 {
|
||||
|
@ -14,9 +14,7 @@
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.4/css/bootstrap3/bootstrap-switch.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css"
|
||||
integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
|
||||
crossorigin=""/>
|
||||
|
||||
|
||||
<script>
|
||||
var ServerInject = {user: <%- JSON.stringify(user); %>, ConfigInject: <%- JSON.stringify(Config); %>}
|
||||
|
@ -32,3 +32,4 @@ bs-dropdown-container {
|
||||
transition-delay: 1s;
|
||||
transition-property: opacity;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user