From c4a7f1aad71070ef1ca872f17e2aa342da4fd1e5 Mon Sep 17 00:00:00 2001 From: August Andersen Date: Wed, 3 Apr 2024 11:04:38 +0200 Subject: [PATCH 1/3] now possible to maximize maps. --- package-lock.json | 70 +++- package.json | 7 +- .../shared/components/map/map.component.html | 2 +- .../shared/components/map/map.component.ts | 316 ++++++++++-------- 4 files changed, 243 insertions(+), 152 deletions(-) diff --git a/package-lock.json b/package-lock.json index aa858add9..608d772f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@angular/router": "^14.2.3", "@auth0/angular-jwt": "^5.0.1", "@fortawesome/angular-fontawesome": "^0.11.1", - "@fortawesome/fontawesome-free": "^5.13.1", + "@fortawesome/fontawesome-free": "^5.15.4", "@fortawesome/fontawesome-svg-core": "^1.2.28", "@fortawesome/free-solid-svg-icons": "^5.13.0", "@ng-bootstrap/ng-bootstrap": "^13.0.0", @@ -36,7 +36,8 @@ "file-saver": "^2.0.2", "guid-typescript": "^1.0.9", "jwt-decode": "^3.1.2", - "leaflet": "^1.7.1", + "leaflet": "^1.9.4", + "leaflet.fullscreen": "^3.0.1", "moment": "^2.29.4", "monaco-editor": "^0.33.0", "ng": "0.0.0", @@ -59,6 +60,8 @@ "@types/jasmine": "~3.6.0", "@types/jasminewd2": "~2.0.3", "@types/jwt-decode": "^3.1.0", + "@types/leaflet": "^1.9.8", + "@types/leaflet.fullscreen": "^3.0.2", "@types/node": "^12.11.1", "codelyzer": "^6.0.2", "eslint": "^7.3.1", @@ -3383,6 +3386,12 @@ "@types/send": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", + "dev": true + }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -3429,6 +3438,24 @@ "jwt-decode": "*" } }, + "node_modules/@types/leaflet": { + "version": "1.9.8", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.8.tgz", + "integrity": "sha512-EXdsL4EhoUtGm2GC2ZYtXn+Fzc6pluVgagvo2VC1RHWToLGlTRwVYoDpqS/7QXa01rmDyBjJk3Catpf60VMkwg==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/leaflet.fullscreen": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/leaflet.fullscreen/-/leaflet.fullscreen-3.0.2.tgz", + "integrity": "sha512-0em5r68INZtQbZn1RzPX6o6Qnd1dxClHRW/iNNXRtqGHBQB1dEQj0lGEhJ373ZFs65hX+/A4xUvX1brK71sE+g==", + "dev": true, + "dependencies": { + "@types/leaflet": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -9178,6 +9205,11 @@ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" }, + "node_modules/leaflet.fullscreen": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/leaflet.fullscreen/-/leaflet.fullscreen-3.0.1.tgz", + "integrity": "sha512-Lsg49e4AYSjHOhmy+VOm4+O6Urim2UvthydKJI3KzfwC3InYkfvJtv1mWuOb9K7qG4H2MtEut09Dz6noQyJARQ==" + }, "node_modules/less": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", @@ -17417,6 +17449,12 @@ "@types/send": "*" } }, + "@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", + "dev": true + }, "@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -17462,6 +17500,24 @@ "jwt-decode": "*" } }, + "@types/leaflet": { + "version": "1.9.8", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.8.tgz", + "integrity": "sha512-EXdsL4EhoUtGm2GC2ZYtXn+Fzc6pluVgagvo2VC1RHWToLGlTRwVYoDpqS/7QXa01rmDyBjJk3Catpf60VMkwg==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, + "@types/leaflet.fullscreen": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/leaflet.fullscreen/-/leaflet.fullscreen-3.0.2.tgz", + "integrity": "sha512-0em5r68INZtQbZn1RzPX6o6Qnd1dxClHRW/iNNXRtqGHBQB1dEQj0lGEhJ373ZFs65hX+/A4xUvX1brK71sE+g==", + "dev": true, + "requires": { + "@types/leaflet": "*" + } + }, "@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -21822,6 +21878,11 @@ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" }, + "leaflet.fullscreen": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/leaflet.fullscreen/-/leaflet.fullscreen-3.0.1.tgz", + "integrity": "sha512-Lsg49e4AYSjHOhmy+VOm4+O6Urim2UvthydKJI3KzfwC3InYkfvJtv1mWuOb9K7qG4H2MtEut09Dz6noQyJARQ==" + }, "less": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", @@ -24062,7 +24123,7 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", + "tough-cookie": "^4.1.3", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, @@ -25335,7 +25396,8 @@ "dev": true }, "tough-cookie": { - "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, "requires": { diff --git a/package.json b/package.json index 65d24e348..d55fd18d9 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@angular/router": "^14.2.3", "@auth0/angular-jwt": "^5.0.1", "@fortawesome/angular-fontawesome": "^0.11.1", - "@fortawesome/fontawesome-free": "^5.13.1", + "@fortawesome/fontawesome-free": "^5.15.4", "@fortawesome/fontawesome-svg-core": "^1.2.28", "@fortawesome/free-solid-svg-icons": "^5.13.0", "@ng-bootstrap/ng-bootstrap": "^13.0.0", @@ -39,7 +39,8 @@ "file-saver": "^2.0.2", "guid-typescript": "^1.0.9", "jwt-decode": "^3.1.2", - "leaflet": "^1.7.1", + "leaflet": "^1.9.4", + "leaflet.fullscreen": "^3.0.1", "moment": "^2.29.4", "monaco-editor": "^0.33.0", "ng": "0.0.0", @@ -62,6 +63,8 @@ "@types/jasmine": "~3.6.0", "@types/jasminewd2": "~2.0.3", "@types/jwt-decode": "^3.1.0", + "@types/leaflet": "^1.9.8", + "@types/leaflet.fullscreen": "^3.0.2", "@types/node": "^12.11.1", "codelyzer": "^6.0.2", "eslint": "^7.3.1", diff --git a/src/app/shared/components/map/map.component.html b/src/app/shared/components/map/map.component.html index d08db03c5..078e1330d 100644 --- a/src/app/shared/components/map/map.component.html +++ b/src/app/shared/components/map/map.component.html @@ -1 +1 @@ -
+
diff --git a/src/app/shared/components/map/map.component.ts b/src/app/shared/components/map/map.component.ts index fa1ce7b8f..a7f2d85ee 100644 --- a/src/app/shared/components/map/map.component.ts +++ b/src/app/shared/components/map/map.component.ts @@ -1,162 +1,188 @@ -import { AfterViewInit, Component, Input, OnChanges, OnInit, Output, EventEmitter, SimpleChanges, OnDestroy, AfterViewChecked, DoCheck } from '@angular/core'; -import * as L from 'leaflet'; -import { Subscription } from 'rxjs'; -import { MapCoordinates, MarkerInfo } from './map-coordinates.model'; +import { + AfterViewInit, + Component, + Input, + OnChanges, + OnInit, + Output, + EventEmitter, + SimpleChanges, + OnDestroy, +} from "@angular/core"; +import * as L from "leaflet"; +import "leaflet.fullscreen"; +import { Subscription } from "rxjs"; +import { MapCoordinates, MarkerInfo } from "./map-coordinates.model"; @Component({ - selector: 'app-map', - templateUrl: './map.component.html', - styleUrls: ['./map.component.scss'] + selector: "app-map", + templateUrl: "./map.component.html", + styleUrls: ["./map.component.scss"], }) export class MapComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy { - private map; - public mapId; - private marker; - private markers: any; - @Input() coordinates?: MapCoordinates; - @Input() coordinateList: [MapCoordinates]; - @Output() updateCoordinates = new EventEmitter(); - private zoomLevel = 15; - private redMarker = '/assets/images/red-marker.png'; - private grenMarker = '/assets/images/green-marker.png'; - subscription: Subscription; - - constructor() { - } - - ngOnInit(): void { - this.mapId = Math.random().toString(); - if (this.coordinates?.useGeolocation) { - this.setGeolocation(); + private map; + public mapId; + private marker; + private markers: any; + @Input() coordinates?: MapCoordinates; + @Input() coordinateList: [MapCoordinates]; + @Output() updateCoordinates = new EventEmitter(); + private zoomLevel = 15; + private redMarker = "/assets/images/red-marker.png"; + private grenMarker = "/assets/images/green-marker.png"; + subscription: Subscription; + + constructor() {} + + ngOnInit(): void { + this.mapId = Math.random().toString(); + if (this.coordinates?.useGeolocation) { + this.setGeolocation(); + } } - } - ngOnChanges(changes: SimpleChanges) { - if (changes?.coordinates?.currentValue?.latitude !== changes?.coordinates?.previousValue?.latitude || - changes?.coordinates?.currentValue?.longitude !== changes?.coordinates?.previousValue?.longitude) { - this.updateMarker(); + ngOnChanges(changes: SimpleChanges) { + if ( + changes?.coordinates?.currentValue?.latitude !== changes?.coordinates?.previousValue?.latitude || + changes?.coordinates?.currentValue?.longitude !== changes?.coordinates?.previousValue?.longitude + ) { + this.updateMarker(); + } + if (changes?.coordinateList?.currentValue !== changes?.coordinateList?.previousValue) { + this.changeMarkers(); + } } - if (changes?.coordinateList?.currentValue !== changes?.coordinateList?.previousValue) { - this.changeMarkers(); + + changeMarkers() { + if (this.markers) { + this.markers.clearLayers(); + } + this.placeMarkers(); + } + + ngAfterViewInit(): void { + this.initMap(); + this.placeMarkers(); + } + + ngOnDestroy(): void { + if (this.map) { + this.map.off(); + this.map.remove(); + } + } + + setGeolocation() { + if (window.navigator.geolocation) { + window.navigator.geolocation.getCurrentPosition(res => { + this.coordinates.longitude = res.coords.longitude; + this.coordinates.latitude = res.coords.latitude; + this.updateMarker(); + this.setCoordinatesOutput(); + }); + } + } + + updateMarker() { + this.marker?.setLatLng([this.coordinates.latitude, this.coordinates.longitude]); + this.map?.setView(this.marker._latlng, this.zoomLevel); + } + + private placeMarkers() { + if (this.coordinateList) { + const markerLayerGroup = []; + this.coordinateList.forEach(coord => { + markerLayerGroup.push( + this.addMarker(coord.latitude, coord.longitude, coord.draggable, coord.markerInfo) + ); + this.markers = L.layerGroup(markerLayerGroup).addTo(this.map); + }); + this.fitToBounds(markerLayerGroup); + } else { + this.marker = this.addMarker( + this.coordinates.latitude, + this.coordinates.longitude, + this.coordinates.draggable, + this.coordinates.markerInfo + ); + this.map.addLayer(this.marker); + } } - } - changeMarkers() { - if (this.markers) { - this.markers.clearLayers(); + private fitToBounds(markers: any[]) { + const group = L.featureGroup(markers); + this.map.fitBounds(group.getBounds(), { padding: [50, 50] }); } - this.placeMarkers(); - } - - ngAfterViewInit(): void { - this.initMap(); - this.placeMarkers(); - } - - ngOnDestroy(): void { - if (this.map) { - this.map.off(); - this.map.remove(); + + private addMarker(latitude: number, longitude: number, draggable = true, markerInfo: MarkerInfo = null) { + const markerIcon = this.getMarkerIcon(markerInfo?.active); + const marker = L.marker([latitude, longitude], { draggable, icon: markerIcon }); + marker.on("dragend", event => this.dragend(event)); + if (markerInfo) { + const isActive = markerInfo.active ? "Aktiv" : "Inaktiv"; + marker.bindPopup( + // TODO: should be standardised when more components use this feature. + '' + + markerInfo.name + + "" + + "

" + + isActive + + "

" + + "

" + + "Organisation: " + + markerInfo.internalOrganizationName + + "

" + ); + } + return marker; } - } - - setGeolocation() { - if (window.navigator.geolocation) { - window.navigator.geolocation.getCurrentPosition( - (res) => { - this.coordinates.longitude = res.coords.longitude; - this.coordinates.latitude = res.coords.latitude; - this.updateMarker(); - this.setCoordinatesOutput(); + + private getMarkerIcon(active = true): any { + return L.icon({ + iconUrl: active ? this.grenMarker : this.redMarker, + iconSize: [38, 38], + iconAnchor: [19, 38], + popupAnchor: [0, -38], }); } - } - - updateMarker() { - this.marker?.setLatLng([this.coordinates.latitude, this.coordinates.longitude]); - this.map?.setView(this.marker._latlng, this.zoomLevel); - } - - private placeMarkers() { - if (this.coordinateList) { - const markerLayerGroup = []; - this.coordinateList.forEach(coord => { - markerLayerGroup.push(this.addMarker(coord.latitude, coord.longitude, coord.draggable, coord.markerInfo)); - this.markers = L.layerGroup(markerLayerGroup).addTo(this.map); - }); - this.fitToBounds(markerLayerGroup) - } else { - this.marker = this.addMarker(this.coordinates.latitude, this.coordinates.longitude, this.coordinates.draggable, this.coordinates.markerInfo); - this.map.addLayer(this.marker); + + private dragend(event: any) { + this.coordinates.latitude = event.target._latlng.lat; + this.coordinates.longitude = event.target._latlng.lng; + this.setCoordinatesOutput(); } - } - - private fitToBounds(markers: any[]) { - const group = new L.featureGroup(markers); - this.map.fitBounds(group.getBounds(), {padding: [50,50]}); - } - - private addMarker(latitude: number, longitude: number, draggable = true, markerInfo: MarkerInfo = null) { - const markerIcon = this.getMarkerIcon(markerInfo?.active); - const marker = L.marker([latitude, longitude], { draggable, icon: markerIcon }); - marker.on('dragend', event => this.dragend(event)); - if (markerInfo) { - const isActive = markerInfo.active ? 'Aktiv' : 'Inaktiv'; - marker.bindPopup( - // TODO: should be standardised when more components use this feature. - '' + markerInfo.name + '' - + - '

' + - isActive + - '

' - + - '

' + - 'Organisation: ' + markerInfo.internalOrganizationName + - '

' - ); + + setCoordinatesOutput() { + this.updateCoordinates.emit({ latitude: this.coordinates.latitude, longitude: this.coordinates.longitude }); } - return marker; - } - - private getMarkerIcon(active = true): any { - return L.icon({ - iconUrl: active ? this.grenMarker : this.redMarker, - iconSize: [38, 38], - iconAnchor: [19, 38], - popupAnchor: [0, -38] - }) - ; - } - - private dragend(event: any) { - this.coordinates.latitude = event.target._latlng.lat; - this.coordinates.longitude = event.target._latlng.lng; - this.setCoordinatesOutput(); - } - - setCoordinatesOutput() { - this.updateCoordinates.emit({ latitude: this.coordinates.latitude, longitude: this.coordinates.longitude }); - } - - private initMap(): void { - const container = document.getElementById(this.mapId); - if (container) { - this.map = L.map(this.mapId, { - center: [ - this.coordinateList ? this.coordinateList[0]?.latitude : this.coordinates?.latitude, - this.coordinateList ? this.coordinateList[0]?.longitude : this.coordinates?.longitude - ], - zoom: this.zoomLevel - }); - const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - maxZoom: 19, - attribution: '© OpenStreetMap' - }); - tiles.addTo(this.map); + + private initMap(): void { + const container = document.getElementById(this.mapId); + if (container) { + this.map = L.map(this.mapId, { + center: [ + this.coordinateList ? this.coordinateList[0]?.latitude : this.coordinates?.latitude, + this.coordinateList ? this.coordinateList[0]?.longitude : this.coordinates?.longitude, + ], + zoom: this.zoomLevel, + fullscreenControl: true, + fullscreenControlOptions: { + position: "topleft", + content: '
' + }, + }); + const tiles = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { + maxZoom: 19, + attribution: '© OpenStreetMap', + }); + tiles.addTo(this.map); + } } - } } From f94325768d017841f1062278111ce018cc60db70 Mon Sep 17 00:00:00 2001 From: August Andersen Date: Wed, 3 Apr 2024 11:12:04 +0200 Subject: [PATCH 2/3] changed latitude and longitude --- .../iot-device-detail-generic.component.html | 4 ++-- .../iot-device-edit.component.html | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html index d7f8f5ec6..4064bee28 100644 --- a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html @@ -70,10 +70,10 @@

{{ 'IOTDEVICE.LOCATION' | translate }}

-

{{ 'IOTDEVICE.LONGITUDE' | translate }}{{longitude | number:'2.1-6'}}

+

{{ 'IOTDEVICE.LATITUDE' | translate }}{{latitude | number:'2.1-6'}}

-

{{ 'IOTDEVICE.LATITUDE' | translate }}{{latitude | number:'2.1-6'}}

+

{{ 'IOTDEVICE.LONGITUDE' | translate }}{{longitude | number:'2.1-6'}}

diff --git a/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html b/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html index 8ae4507e9..49c42882c 100644 --- a/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html +++ b/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html @@ -77,7 +77,13 @@
- +
+ + +
-
- - -
Date: Wed, 3 Apr 2024 11:28:36 +0200 Subject: [PATCH 3/3] changed default center on maps when create --- src/app/applications/iot-devices/iot-device.model.ts | 4 ++-- src/app/shared/models/common-location.model.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/applications/iot-devices/iot-device.model.ts b/src/app/applications/iot-devices/iot-device.model.ts index c385a2d21..5e1097f1f 100644 --- a/src/app/applications/iot-devices/iot-device.model.ts +++ b/src/app/applications/iot-devices/iot-device.model.ts @@ -27,8 +27,8 @@ export class IotDevice { createdByName: string; updatedByName: string; applicationId: number; - longitude = 0; - latitude = 0; + longitude = 11.764445; + latitude = 55.959443; deviceModelId?: number; latestReceivedMessage: LatestReceivedMessage; lorawanSettings = new LorawanSettings(); diff --git a/src/app/shared/models/common-location.model.ts b/src/app/shared/models/common-location.model.ts index 13619ae8a..22b42dfcb 100644 --- a/src/app/shared/models/common-location.model.ts +++ b/src/app/shared/models/common-location.model.ts @@ -1,6 +1,6 @@ export class CommonLocation { - longitude = 0; - latitude = 0; + longitude = 11.764445; + latitude = 55.959443; altitude = 0; source?: | 'UNKNOWN'