A hole bunch of cleanup
This commit is contained in:
@ -20,6 +20,7 @@ export enum WeatherLayers {
|
||||
}
|
||||
|
||||
const ARROW = L.icon({iconUrl: '/assets/images/arrow.png', iconSize: [40, 45], iconAnchor: [20, 23]});
|
||||
const DOT = L.icon({iconUrl: '/assets/images/dot.png', iconSize: [25, 25], iconAnchor: [13, 13]});
|
||||
const MARKER = L.icon({iconUrl: '/assets/images/marker.png', iconSize: [40, 55], iconAnchor: [20, 55]});
|
||||
const MEASURE = L.icon({iconUrl: '/assets/images/measure.png', iconSize: [75, 50], iconAnchor: [25, 25]});
|
||||
|
||||
@ -51,6 +52,8 @@ export class MapService {
|
||||
switch(name) {
|
||||
case 'arrow':
|
||||
return ARROW;
|
||||
case 'dot':
|
||||
return DOT;
|
||||
case 'measure':
|
||||
return MEASURE;
|
||||
default:
|
||||
@ -98,7 +101,7 @@ export class MapService {
|
||||
}
|
||||
|
||||
newCircle(c: Circle) {
|
||||
let circle = L.circle(c.latlng, Object.assign({}, c)).addTo(this.map);
|
||||
let circle = L.circle(c.latlng, Object.assign({color: '#ff4141'}, c)).addTo(this.map);
|
||||
if(c.label) circle.bindTooltip(c.label, {permanent: true, direction: 'center'});
|
||||
circle.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: c, item: circle}));
|
||||
if(!c.noDelete) this.circles.push(circle);
|
||||
@ -106,7 +109,7 @@ export class MapService {
|
||||
}
|
||||
|
||||
newMarker(m: Marker) {
|
||||
let marker = L.marker(m.latlng, Object.assign({}, m, {icon: m.icon ? this.getIcon(m.icon) : MARKER})).addTo(this.map);
|
||||
let marker = L.marker(m.latlng, Object.assign({color: '#ff4141'}, m, {icon: m.icon ? this.getIcon(m.icon) : MARKER})).addTo(this.map);
|
||||
if(m.label) marker.bindTooltip(m.label, {permanent: true, direction: 'bottom'});
|
||||
marker.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: m, item: marker}));
|
||||
if(!m.noDelete) this.markers.push(marker);
|
||||
@ -114,10 +117,10 @@ export class MapService {
|
||||
}
|
||||
|
||||
newMeasurement(m: Measurement) {
|
||||
let line = L.polyline([m.latlng, m.latlng2], Object.assign({}, m));
|
||||
let line = L.polyline([m.latlng, m.latlng2], Object.assign({color: '#ff4141', weight: 8}, m));
|
||||
let decoration = L.polylineDecorator(line, {patterns: [
|
||||
{offset: '100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: m})},
|
||||
{offset: '-100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: m})}
|
||||
{offset: '100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: Object.assign({color: '#ff4141', weight: 8}, m)})},
|
||||
{offset: '-100%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 10, polygon: false, headAngle: 180, pathOptions: Object.assign({color: '#ff4141', weight: 8}, m)})}
|
||||
]});
|
||||
let group = new L.LayerGroup([line, decoration]).addTo(this.map);
|
||||
if(!m.noDelete) this.measurements.push(group);
|
||||
@ -129,21 +132,21 @@ export class MapService {
|
||||
}
|
||||
|
||||
newPolygon(p: Polygon) {
|
||||
let polygon = new L.Polygon(p.latlng, Object.assign({}, p)).addTo(this.map);
|
||||
let polygon = new L.Polygon(p.latlng, Object.assign({color: '#ff4141'}, p)).addTo(this.map);
|
||||
polygon.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: p, item: polygon}));
|
||||
if(!p.noDelete) this.polygons.push(polygon);
|
||||
return polygon;
|
||||
}
|
||||
|
||||
newPolyline(p: Polyline) {
|
||||
let polyline = new L.Polyline(p.latlng, Object.assign({}, p)).addTo(this.map);
|
||||
let polyline = new L.Polyline(p.latlng, Object.assign({color: '#ff4141', weight: 10}, p)).addTo(this.map);
|
||||
polyline.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: p, item: polyline}));
|
||||
if(!p.noDelete) this.polylines.push(polyline);
|
||||
return polyline;
|
||||
}
|
||||
|
||||
newRectangle(r: Rectangle) {
|
||||
let rect = new L.Rectangle([r.latlng, r.latlng2], Object.assign({}, r)).addTo(this.map);
|
||||
let rect = new L.Rectangle([r.latlng, r.latlng2], Object.assign({color: '#ff4141'}, r)).addTo(this.map);
|
||||
if(r.label) rect.bindTooltip(r.label, {permanent: true, direction: 'center'});
|
||||
rect.on('click', e => this.click.next({latlng: {lat: e.latlng.lat, lng: e.latlng.lng}, symbol: r, item: rect}));
|
||||
if(!r.noDelete) this.rectangles.push(rect);
|
||||
|
@ -3,7 +3,7 @@ import {AngularFirestore, AngularFirestoreDocument} from "@angular/fire/firestor
|
||||
import {BehaviorSubject, combineLatest, Subscription} from "rxjs";
|
||||
import {Circle, MapData, MapSymbol, Marker, Measurement, Polygon, Polyline, Position, Rectangle} from "../models/mapSymbol";
|
||||
import * as _ from 'lodash';
|
||||
import {map} from "rxjs/operators";
|
||||
import {filter, map} from "rxjs/operators";
|
||||
|
||||
export const LOCATION_COLLECTION = 'Users';
|
||||
export const MAP_COLLECTION = 'Maps';
|
||||
@ -23,9 +23,19 @@ export class SyncService {
|
||||
private username: string;
|
||||
|
||||
mapData = new BehaviorSubject<MapData>({});
|
||||
status = new BehaviorSubject<string>(null);
|
||||
|
||||
constructor(private db: AngularFirestore) {
|
||||
window.addEventListener('beforeunload', () => this.unload());
|
||||
// Handle prompting the user before exit if there are changes
|
||||
this.status.pipe(filter(s => !s)).subscribe(() => window.onbeforeunload = () => this.unload());
|
||||
this.status.pipe(filter(s => !!s)).subscribe(() => {
|
||||
window.onbeforeunload = e => {
|
||||
this.removeLocation();
|
||||
let ignore = this.save();
|
||||
e.returnValue = 'Please wait for us to finish saving!';
|
||||
return e.returnValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private addMapSymbol(s: MapSymbol, key: string) {
|
||||
@ -35,6 +45,7 @@ export class SyncService {
|
||||
map[key].push(s);
|
||||
this.mapData.next(map);
|
||||
this.mapChanged = true;
|
||||
this.status.next('modified');
|
||||
}
|
||||
|
||||
async exists(mapCode: string) {
|
||||
@ -58,7 +69,7 @@ export class SyncService {
|
||||
let markForSave = this.location == null;
|
||||
if(!this.locationChanged) this.locationChanged = !_.isEqual(this.location, location);
|
||||
if(this.locationChanged) this.location = location;
|
||||
if(markForSave) this.save(true);
|
||||
if(markForSave) return this.save(false, true);
|
||||
}
|
||||
|
||||
addPolygon(polygon: Polygon) {
|
||||
@ -80,6 +91,7 @@ export class SyncService {
|
||||
});
|
||||
this.mapData.next(map);
|
||||
this.mapChanged = true;
|
||||
this.status.next('modified');
|
||||
}
|
||||
|
||||
load(mapCode: string, username: string) {
|
||||
@ -88,7 +100,12 @@ export class SyncService {
|
||||
this.mapDoc = this.db.collection(MAP_COLLECTION).doc(mapCode);
|
||||
this.locationDoc = this.mapDoc.collection(LOCATION_COLLECTION).doc(username);
|
||||
|
||||
this.mapSub = combineLatest(this.mapDoc.valueChanges(), this.mapDoc.collection(LOCATION_COLLECTION).snapshotChanges())
|
||||
|
||||
this.mapSub = combineLatest(this.mapDoc.valueChanges(), this.mapDoc.collection(LOCATION_COLLECTION, ref => {
|
||||
let aMinuteAgo = new Date();
|
||||
aMinuteAgo.setMinutes(aMinuteAgo.getMinutes() - 1);
|
||||
return ref.where('timestamp', '>=', aMinuteAgo);
|
||||
}).snapshotChanges())
|
||||
.pipe(map(data => {
|
||||
let newMap = data[0];
|
||||
let oldMap = this.mapData.value;
|
||||
@ -103,8 +120,9 @@ export class SyncService {
|
||||
return mergedMap;
|
||||
})).subscribe((mapData: MapData) => {
|
||||
this.mapData.next(mapData);
|
||||
this.status.next(null);
|
||||
if(this.saveInterval) clearInterval(this.saveInterval);
|
||||
this.saveInterval = setInterval(() => this.save(), (mapData.locations && Object.keys(mapData.locations).length > 0) ? 5_000 : 30_000)
|
||||
this.saveInterval = setInterval(() => this.save(), (mapData.locations && Object.keys(mapData.locations).length > 0) ? 5_000 : 30_000);
|
||||
});
|
||||
}
|
||||
|
||||
@ -120,26 +138,35 @@ export class SyncService {
|
||||
return map;
|
||||
}
|
||||
|
||||
save(locationOnly?) {
|
||||
if(this.locationDoc && this.locationChanged) {
|
||||
let ignore = this.locationDoc.set(this.location);
|
||||
removeLocation() {
|
||||
// Hack to delete doc even if page is closed
|
||||
navigator.sendBeacon(`https://us-central1-mapalliance-ab38a.cloudfunctions.net/closeSession/?mapCode=${this.mapCode}&username=${this.username}`);
|
||||
}
|
||||
|
||||
save(map=true, location=true) {
|
||||
this.status.next('saving');
|
||||
let promises = [];
|
||||
|
||||
if(location && this.locationDoc && this.locationChanged) {
|
||||
promises.push(this.locationDoc.set(this.location));
|
||||
}
|
||||
|
||||
if(!locationOnly && this.mapDoc && this.mapChanged) {
|
||||
if(map && this.mapDoc && this.mapChanged) {
|
||||
let map = this.mapData.value;
|
||||
Object.values(map).filter(val => Array.isArray(val)).forEach(val => val.filter(s => s.new).forEach(s => delete s.new));
|
||||
delete map.locations;
|
||||
let ignore = this.mapDoc.set(map);
|
||||
promises.push(this.mapDoc.set(map));
|
||||
this.mapChanged = false;
|
||||
}
|
||||
|
||||
return Promise.all(promises)
|
||||
}
|
||||
|
||||
async unload() {
|
||||
// Hack to delete doc on page close
|
||||
navigator.sendBeacon(`https://us-central1-mapalliance-ab38a.cloudfunctions.net/closeSession/?mapCode=${this.mapCode}&username=${this.username}`);
|
||||
unload() {
|
||||
this.removeLocation();
|
||||
|
||||
this.save();
|
||||
if(this.saveInterval) clearInterval(this.saveInterval);
|
||||
let saving = this.save(true, false);
|
||||
|
||||
if(this.mapSub) {
|
||||
this.mapSub.unsubscribe();
|
||||
@ -160,5 +187,6 @@ export class SyncService {
|
||||
this.mapCode = null;
|
||||
this.username = null;
|
||||
this.mapData.next({});
|
||||
return saving;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user