|
|
|
|
|
|
|
|
AfterViewInit, |
|
|
AfterViewInit, |
|
|
Component, |
|
|
Component, |
|
|
OnDestroy, |
|
|
OnDestroy, |
|
|
OnInit |
|
|
|
|
|
|
|
|
OnInit, Renderer2 |
|
|
} from '@angular/core'; |
|
|
} from '@angular/core'; |
|
|
import * as L from 'leaflet'; |
|
|
import * as L from 'leaflet'; |
|
|
import 'leaflet.markercluster'; |
|
|
import 'leaflet.markercluster'; |
|
|
import { Subscription } from 'rxjs'; |
|
|
import { Subscription } from 'rxjs'; |
|
|
import { SocketService } from '../../../shared/services/socket.service'; |
|
|
import { SocketService } from '../../../shared/services/socket.service'; |
|
|
|
|
|
import {MatDialog} from "@angular/material/dialog"; |
|
|
|
|
|
import {CameraDialogComponent} from "../camera-dialog/camera-dialog.component"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const alarmData = [ |
|
|
const alarmData = [ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
]; |
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const alarmDemo = { |
|
|
const alarmDemo = { |
|
|
title: ' Demo Alarm System', // Thêm mới warning |
|
|
title: ' Demo Alarm System', // Thêm mới warning |
|
|
detail: { |
|
|
detail: { |
|
|
|
|
|
|
|
|
time: '06-07-2024' |
|
|
time: '06-07-2024' |
|
|
}, |
|
|
}, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Component({ |
|
|
@Component({ |
|
|
selector: 'app-map', |
|
|
selector: 'app-map', |
|
|
templateUrl: './map.component.html', |
|
|
templateUrl: './map.component.html', |
|
|
|
|
|
|
|
|
state6 = false; |
|
|
state6 = false; |
|
|
isReady = true; |
|
|
isReady = true; |
|
|
|
|
|
|
|
|
constructor(private socketService$: SocketService) { } |
|
|
|
|
|
|
|
|
constructor(private socketService$: SocketService, |
|
|
|
|
|
private dialog: MatDialog, |
|
|
|
|
|
private renderer: Renderer2) { } |
|
|
|
|
|
|
|
|
ngOnInit() { |
|
|
ngOnInit() { |
|
|
this.statusSubscription = this.socketService$.status$.subscribe(isConnected => { |
|
|
this.statusSubscription = this.socketService$.status$.subscribe(isConnected => { |
|
|
|
|
|
|
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
openDialog(): void { |
|
|
|
|
|
this.dialog.open(CameraDialogComponent, { |
|
|
|
|
|
width: '80vw', |
|
|
|
|
|
data: '' |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
ngAfterViewInit(): void { |
|
|
ngAfterViewInit(): void { |
|
|
this.initMap(); |
|
|
this.initMap(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>' |
|
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>' |
|
|
}).addTo(this.map); |
|
|
}).addTo(this.map); |
|
|
|
|
|
|
|
|
this.addIconToMap(); |
|
|
|
|
|
|
|
|
this.addIconsToMap(); |
|
|
} else { |
|
|
} else { |
|
|
console.error('Map container not found'); |
|
|
console.error('Map container not found'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMessage(message: any) { |
|
|
onMessage(message: any) { |
|
|
if (message.id == '0' && message.type === 'get') { |
|
|
if (message.id == '0' && message.type === 'get') { |
|
|
this.state1 = message.state1 === '0';// 1 OFF // alarm 12h |
|
|
|
|
|
|
|
|
this.state1 = message.state1 === '0'; // 1 OFF // alarm 12h |
|
|
this.state2 = message.state2 === '0'; // 1 OFF // alarm 1h |
|
|
this.state2 = message.state2 === '0'; // 1 OFF // alarm 1h |
|
|
this.state5 = message.state5 === '1';// 1 ON, 0 OFF |
|
|
|
|
|
|
|
|
this.state5 = message.state5 === '1'; // 1 ON, 0 OFF |
|
|
this.isReady = message.ready === '1'; |
|
|
this.isReady = message.ready === '1'; |
|
|
this.updateIcons(); |
|
|
this.updateIcons(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
addIconToMap() { |
|
|
|
|
|
|
|
|
addIconsToMap(): void { |
|
|
this.markers = L.markerClusterGroup(); |
|
|
this.markers = L.markerClusterGroup(); |
|
|
this.data.forEach((item: any) => { |
|
|
|
|
|
// create icon |
|
|
|
|
|
const icon = this.createIcon(item.warning); |
|
|
|
|
|
// add icon into map |
|
|
|
|
|
L.marker([item.detail.coordinates.lat, item.detail.coordinates.lng], { icon: icon }) |
|
|
|
|
|
.bindPopup(this.popupDetail(item)) |
|
|
|
|
|
.addTo(this.markers); |
|
|
|
|
|
}); |
|
|
|
|
|
const iconDemo = this.getIcon(this.state5, this.isReady, this.state1, this.state2); |
|
|
|
|
|
L.marker([this.alarmDemo.detail.coordinates.lat,this.alarmDemo.detail.coordinates.lng], { icon: iconDemo }) |
|
|
|
|
|
.bindPopup(this.popupDetail(this.alarmDemo)) |
|
|
|
|
|
.addTo(this.markers); |
|
|
|
|
|
|
|
|
this.data.forEach(item => this.addMarker(item)); |
|
|
|
|
|
this.addMarker(this.alarmDemo, true); |
|
|
|
|
|
this.map.addLayer(this.markers); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
addMarker(item: any, isDemo: boolean = false): void { |
|
|
|
|
|
const icon = isDemo ? this.getIcon(this.state5, this.isReady, this.state1, this.state2) : this.createIcon(item.warning); |
|
|
|
|
|
const marker = L.marker([item.detail.coordinates.lat, item.detail.coordinates.lng], { icon }) |
|
|
|
|
|
.bindPopup(this.popupDetail(item)); |
|
|
|
|
|
|
|
|
|
|
|
marker.on('popupopen', (event) => this.bindPopupEvents(event)); |
|
|
|
|
|
|
|
|
this.markers.addTo(this.map); |
|
|
|
|
|
|
|
|
this.markers.addLayer(marker); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bindPopupEvents(event: any): void { |
|
|
|
|
|
const popupContainer = event.popup.getElement(); |
|
|
|
|
|
const button = popupContainer?.querySelector('.dynamic-button'); |
|
|
|
|
|
if (button) { |
|
|
|
|
|
this.renderer.listen(button, 'click', () => this.openDialog()); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
updateIcons(): void { |
|
|
updateIcons(): void { |
|
|
//clear layer icon mỗi lần update |
|
|
|
|
|
this.markers.clearLayers(); |
|
|
this.markers.clearLayers(); |
|
|
this.addIconToMap(); |
|
|
|
|
|
|
|
|
this.addIconsToMap(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
popupDetail(item: any): string { |
|
|
popupDetail(item: any): string { |
|
|
|
|
|
|
|
|
<div class="tooltip" style="width: 200px"> |
|
|
<div class="tooltip" style="width: 200px"> |
|
|
<div style="display: flex; flex-direction: row; justify-content: space-between; margin-bottom: 5px"> |
|
|
<div style="display: flex; flex-direction: row; justify-content: space-between; margin-bottom: 5px"> |
|
|
<div style="color: #F33152; padding: 5px 13px; background-color: rgba(243, 49, 82, 0.1); border-radius: 20px; text-align: center; max-width: 180px;">${item.title}</div> |
|
|
<div style="color: #F33152; padding: 5px 13px; background-color: rgba(243, 49, 82, 0.1); border-radius: 20px; text-align: center; max-width: 180px;">${item.title}</div> |
|
|
<a href="/overview/camera-stream" target="_blank"> |
|
|
|
|
|
|
|
|
<a class="dynamic-button"> |
|
|
<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none"> |
|
|
<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none"> |
|
|
<g stroke="currentColor" stroke-width="2"> |
|
|
<g stroke="currentColor" stroke-width="2"> |
|
|
<path d="M16 16V8a1 1 0 00-1-1H5a1 1 0 00-1 1v8a1 1 0 001 1h10a1 1 0 001-1z"/> |
|
|
<path d="M16 16V8a1 1 0 00-1-1H5a1 1 0 00-1 1v8a1 1 0 001 1h10a1 1 0 001-1z"/> |
|
|
|
|
|
|
|
|
return L.divIcon({ |
|
|
return L.divIcon({ |
|
|
html: `<div class="icon"> |
|
|
html: `<div class="icon"> |
|
|
<div style="z-index:9999" class="sensor-on"> |
|
|
<div style="z-index:9999" class="sensor-on"> |
|
|
<img alt="icon-alarm" src ="assets/images/sensor-on.png" style="width: 30px; height: 30px"> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div style="background: #F11E1E; color: #FFF; padding: 2px 3px; font-size: 11px; margin-top: 10px; text-align: center"> |
|
|
|
|
|
${htmlContent} |
|
|
|
|
|
</div> |
|
|
|
|
|
</div>`, |
|
|
|
|
|
|
|
|
<img alt="icon-alarm" src="assets/images/sensor-on.png" style="width: 30px; height: 30px"> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div style="background: #F11E1E; color: #FFF; padding: 2px 3px; font-size: 11px; margin-top: 10px; text-align: center"> |
|
|
|
|
|
${htmlContent} |
|
|
|
|
|
</div> |
|
|
|
|
|
</div>`, |
|
|
iconSize: [200, 30], |
|
|
iconSize: [200, 30], |
|
|
className: className |
|
|
className: className |
|
|
}); |
|
|
}); |