A hole bunch of cleanup
This commit is contained in:
		@@ -1,14 +1,14 @@
 | 
				
			|||||||
import { Component } from '@angular/core';
 | 
					import {Component} from '@angular/core';
 | 
				
			||||||
import {MatSnackBar} from "@angular/material/snack-bar";
 | 
					import {MatSnackBar} from "@angular/material/snack-bar";
 | 
				
			||||||
import {SwUpdate} from "@angular/service-worker";
 | 
					import {SwUpdate} from "@angular/service-worker";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-root',
 | 
					    selector: 'app-root',
 | 
				
			||||||
  templateUrl: 'app.component.html'
 | 
					    templateUrl: 'app.component.html'
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class AppComponent {
 | 
					export class AppComponent {
 | 
				
			||||||
  constructor(private snackbar: MatSnackBar, private update: SwUpdate) {
 | 
					    constructor(private snackbar: MatSnackBar, private update: SwUpdate) {
 | 
				
			||||||
    update.available.subscribe(() => snackbar.open('Update Available!! 🚀', 'Reload').onAction().subscribe(async () => update.activateUpdate()))
 | 
					        update.available.subscribe(() => snackbar.open('Update Available!! 🚀', 'Reload').onAction().subscribe(async () => update.activateUpdate()))
 | 
				
			||||||
    update.activated.subscribe(() => window.location.reload());
 | 
					        update.activated.subscribe(() => window.location.reload());
 | 
				
			||||||
  }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,8 @@
 | 
				
			|||||||
        <img src="/assets/images/logo.png" height="35px" width="auto">
 | 
					        <img src="/assets/images/logo.png" height="35px" width="auto">
 | 
				
			||||||
    </button>
 | 
					    </button>
 | 
				
			||||||
    <small class="ml-1">{{version}}</small>
 | 
					    <small class="ml-1">{{version}}</small>
 | 
				
			||||||
 | 
					    <mat-progress-spinner *ngIf="(status | async) == 'staving'" color="primary" class="text-muted pl-2"></mat-progress-spinner>
 | 
				
			||||||
 | 
					    <button mat-icon-button *ngIf="(status | async) == 'modified'" class="ml-2" (click)="save.emit()"><mat-icon class="text-muted">autorenew</mat-icon></button>
 | 
				
			||||||
    <div class="ml-auto">
 | 
					    <div class="ml-auto">
 | 
				
			||||||
        <ng-container *ngFor="let item of displayMenuItems; let i = index">
 | 
					        <ng-container *ngFor="let item of displayMenuItems; let i = index">
 | 
				
			||||||
            <ng-container *ngIf="i < maxMenuItems">
 | 
					            <ng-container *ngIf="i < maxMenuItems">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import {AfterViewInit, Component, EventEmitter, HostListener, Input, OnInit, Output,} from "@angular/core";
 | 
					import {AfterViewInit, Component, EventEmitter, HostListener, Input, OnInit, Output,} from "@angular/core";
 | 
				
			||||||
import {ToolbarItem} from "../../models/toolbarItem";
 | 
					import {ToolbarItem} from "../../models/toolbarItem";
 | 
				
			||||||
import {version} from '../../../../package.json';
 | 
					import {version} from '../../../../package.json';
 | 
				
			||||||
 | 
					import {Observable} from "rxjs";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
    selector: 'toolbar',
 | 
					    selector: 'toolbar',
 | 
				
			||||||
@@ -9,8 +10,10 @@ import {version} from '../../../../package.json';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class ToolbarComponent implements OnInit, AfterViewInit {
 | 
					export class ToolbarComponent implements OnInit, AfterViewInit {
 | 
				
			||||||
    @Input() menuItems: ToolbarItem[];
 | 
					    @Input() menuItems: ToolbarItem[];
 | 
				
			||||||
 | 
					    @Input() status: Observable<string>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Output() menuItemsChange = new EventEmitter<ToolbarItem[]>();
 | 
					    @Output() menuItemsChange = new EventEmitter<ToolbarItem[]>();
 | 
				
			||||||
 | 
					    @Output() save = new EventEmitter<void>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    readonly version = version;
 | 
					    readonly version = version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ import {
 | 
				
			|||||||
} from "@angular/material";
 | 
					} from "@angular/material";
 | 
				
			||||||
import {NgModule} from "@angular/core";
 | 
					import {NgModule} from "@angular/core";
 | 
				
			||||||
import {MatTooltipModule} from "@angular/material/tooltip";
 | 
					import {MatTooltipModule} from "@angular/material/tooltip";
 | 
				
			||||||
 | 
					import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const materialModules = [
 | 
					export const materialModules = [
 | 
				
			||||||
    MatBottomSheetModule,
 | 
					    MatBottomSheetModule,
 | 
				
			||||||
@@ -17,6 +18,7 @@ export const materialModules = [
 | 
				
			|||||||
    MatIconModule,
 | 
					    MatIconModule,
 | 
				
			||||||
    MatInputModule,
 | 
					    MatInputModule,
 | 
				
			||||||
    MatMenuModule,
 | 
					    MatMenuModule,
 | 
				
			||||||
 | 
					    MatProgressSpinnerModule,
 | 
				
			||||||
    MatSliderModule,
 | 
					    MatSliderModule,
 | 
				
			||||||
    MatSnackBarModule,
 | 
					    MatSnackBarModule,
 | 
				
			||||||
    MatToolbarModule,
 | 
					    MatToolbarModule,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ export enum WeatherLayers {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ARROW = L.icon({iconUrl: '/assets/images/arrow.png', iconSize: [40, 45], iconAnchor: [20, 23]});
 | 
					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 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]});
 | 
					const MEASURE = L.icon({iconUrl: '/assets/images/measure.png', iconSize: [75, 50], iconAnchor: [25, 25]});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,6 +52,8 @@ export class MapService {
 | 
				
			|||||||
        switch(name) {
 | 
					        switch(name) {
 | 
				
			||||||
            case 'arrow':
 | 
					            case 'arrow':
 | 
				
			||||||
                return ARROW;
 | 
					                return ARROW;
 | 
				
			||||||
 | 
					            case 'dot':
 | 
				
			||||||
 | 
					                return DOT;
 | 
				
			||||||
            case 'measure':
 | 
					            case 'measure':
 | 
				
			||||||
                return MEASURE;
 | 
					                return MEASURE;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
@@ -98,7 +101,7 @@ export class MapService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    newCircle(c: Circle) {
 | 
					    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'});
 | 
					        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}));
 | 
					        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);
 | 
					        if(!c.noDelete) this.circles.push(circle);
 | 
				
			||||||
@@ -106,7 +109,7 @@ export class MapService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    newMarker(m: Marker) {
 | 
					    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'});
 | 
					        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}));
 | 
					        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);
 | 
					        if(!m.noDelete) this.markers.push(marker);
 | 
				
			||||||
@@ -114,10 +117,10 @@ export class MapService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    newMeasurement(m: Measurement) {
 | 
					    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: [
 | 
					        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: Object.assign({color: '#ff4141', weight: 8}, 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)})}
 | 
				
			||||||
        ]});
 | 
					        ]});
 | 
				
			||||||
        let group = new L.LayerGroup([line, decoration]).addTo(this.map);
 | 
					        let group = new L.LayerGroup([line, decoration]).addTo(this.map);
 | 
				
			||||||
        if(!m.noDelete) this.measurements.push(group);
 | 
					        if(!m.noDelete) this.measurements.push(group);
 | 
				
			||||||
@@ -129,21 +132,21 @@ export class MapService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    newPolygon(p: Polygon) {
 | 
					    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}));
 | 
					        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);
 | 
					        if(!p.noDelete) this.polygons.push(polygon);
 | 
				
			||||||
        return polygon;
 | 
					        return polygon;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    newPolyline(p: Polyline) {
 | 
					    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}));
 | 
					        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);
 | 
					        if(!p.noDelete) this.polylines.push(polyline);
 | 
				
			||||||
        return polyline;
 | 
					        return polyline;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    newRectangle(r: Rectangle) {
 | 
					    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'});
 | 
					        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}));
 | 
					        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);
 | 
					        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 {BehaviorSubject, combineLatest, Subscription} from "rxjs";
 | 
				
			||||||
import {Circle, MapData, MapSymbol, Marker, Measurement, Polygon, Polyline, Position, Rectangle} from "../models/mapSymbol";
 | 
					import {Circle, MapData, MapSymbol, Marker, Measurement, Polygon, Polyline, Position, Rectangle} from "../models/mapSymbol";
 | 
				
			||||||
import * as _ from 'lodash';
 | 
					import * as _ from 'lodash';
 | 
				
			||||||
import {map} from "rxjs/operators";
 | 
					import {filter, map} from "rxjs/operators";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const LOCATION_COLLECTION = 'Users';
 | 
					export const LOCATION_COLLECTION = 'Users';
 | 
				
			||||||
export const MAP_COLLECTION = 'Maps';
 | 
					export const MAP_COLLECTION = 'Maps';
 | 
				
			||||||
@@ -23,9 +23,19 @@ export class SyncService {
 | 
				
			|||||||
    private username: string;
 | 
					    private username: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mapData = new BehaviorSubject<MapData>({});
 | 
					    mapData = new BehaviorSubject<MapData>({});
 | 
				
			||||||
 | 
					    status = new BehaviorSubject<string>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(private db: AngularFirestore) {
 | 
					    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) {
 | 
					    private addMapSymbol(s: MapSymbol, key: string) {
 | 
				
			||||||
@@ -35,6 +45,7 @@ export class SyncService {
 | 
				
			|||||||
        map[key].push(s);
 | 
					        map[key].push(s);
 | 
				
			||||||
        this.mapData.next(map);
 | 
					        this.mapData.next(map);
 | 
				
			||||||
        this.mapChanged = true;
 | 
					        this.mapChanged = true;
 | 
				
			||||||
 | 
					        this.status.next('modified');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async exists(mapCode: string) {
 | 
					    async exists(mapCode: string) {
 | 
				
			||||||
@@ -58,7 +69,7 @@ export class SyncService {
 | 
				
			|||||||
        let markForSave = this.location == null;
 | 
					        let markForSave = this.location == null;
 | 
				
			||||||
        if(!this.locationChanged) this.locationChanged = !_.isEqual(this.location, location);
 | 
					        if(!this.locationChanged) this.locationChanged = !_.isEqual(this.location, location);
 | 
				
			||||||
        if(this.locationChanged) this.location = location;
 | 
					        if(this.locationChanged) this.location = location;
 | 
				
			||||||
        if(markForSave) this.save(true);
 | 
					        if(markForSave) return this.save(false, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    addPolygon(polygon: Polygon) {
 | 
					    addPolygon(polygon: Polygon) {
 | 
				
			||||||
@@ -80,6 +91,7 @@ export class SyncService {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
        this.mapData.next(map);
 | 
					        this.mapData.next(map);
 | 
				
			||||||
        this.mapChanged = true;
 | 
					        this.mapChanged = true;
 | 
				
			||||||
 | 
					        this.status.next('modified');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    load(mapCode: string, username: string) {
 | 
					    load(mapCode: string, username: string) {
 | 
				
			||||||
@@ -88,7 +100,12 @@ export class SyncService {
 | 
				
			|||||||
        this.mapDoc = this.db.collection(MAP_COLLECTION).doc(mapCode);
 | 
					        this.mapDoc = this.db.collection(MAP_COLLECTION).doc(mapCode);
 | 
				
			||||||
        this.locationDoc = this.mapDoc.collection(LOCATION_COLLECTION).doc(username);
 | 
					        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 => {
 | 
					            .pipe(map(data => {
 | 
				
			||||||
                let newMap = data[0];
 | 
					                let newMap = data[0];
 | 
				
			||||||
                let oldMap = this.mapData.value;
 | 
					                let oldMap = this.mapData.value;
 | 
				
			||||||
@@ -103,8 +120,9 @@ export class SyncService {
 | 
				
			|||||||
                return mergedMap;
 | 
					                return mergedMap;
 | 
				
			||||||
            })).subscribe((mapData: MapData) => {
 | 
					            })).subscribe((mapData: MapData) => {
 | 
				
			||||||
                this.mapData.next(mapData);
 | 
					                this.mapData.next(mapData);
 | 
				
			||||||
 | 
					                this.status.next(null);
 | 
				
			||||||
                if(this.saveInterval) clearInterval(this.saveInterval);
 | 
					                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;
 | 
					        return map;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    save(locationOnly?) {
 | 
					    removeLocation() {
 | 
				
			||||||
        if(this.locationDoc && this.locationChanged) {
 | 
					        // Hack to delete doc even if page is closed
 | 
				
			||||||
            let ignore = this.locationDoc.set(this.location);
 | 
					        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;
 | 
					            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));
 | 
					            Object.values(map).filter(val => Array.isArray(val)).forEach(val => val.filter(s => s.new).forEach(s => delete s.new));
 | 
				
			||||||
            delete map.locations;
 | 
					            delete map.locations;
 | 
				
			||||||
            let ignore = this.mapDoc.set(map);
 | 
					            promises.push(this.mapDoc.set(map));
 | 
				
			||||||
            this.mapChanged = false;
 | 
					            this.mapChanged = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Promise.all(promises)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async unload() {
 | 
					    unload() {
 | 
				
			||||||
        // Hack to delete doc on page close
 | 
					        this.removeLocation();
 | 
				
			||||||
        navigator.sendBeacon(`https://us-central1-mapalliance-ab38a.cloudfunctions.net/closeSession/?mapCode=${this.mapCode}&username=${this.username}`);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.save();
 | 
					 | 
				
			||||||
        if(this.saveInterval) clearInterval(this.saveInterval);
 | 
					        if(this.saveInterval) clearInterval(this.saveInterval);
 | 
				
			||||||
 | 
					        let saving = this.save(true, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(this.mapSub) {
 | 
					        if(this.mapSub) {
 | 
				
			||||||
            this.mapSub.unsubscribe();
 | 
					            this.mapSub.unsubscribe();
 | 
				
			||||||
@@ -160,5 +187,6 @@ export class SyncService {
 | 
				
			|||||||
        this.mapCode = null;
 | 
					        this.mapCode = null;
 | 
				
			||||||
        this.username = null;
 | 
					        this.username = null;
 | 
				
			||||||
        this.mapData.next({});
 | 
					        this.mapData.next({});
 | 
				
			||||||
 | 
					        return saving;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
<toolbar [(menuItems)]="menu"></toolbar>
 | 
					<toolbar [(menuItems)]="menu" [status]="syncService.status" (save)="syncService.save()"></toolbar>
 | 
				
			||||||
<div id="map"></div>
 | 
					<div id="map"></div>
 | 
				
			||||||
<div *ngIf="showPalette" [@flyInRight] [@flyOutRight] class="palette">
 | 
					<div *ngIf="showPalette" [@flyInRight] [@flyOutRight] class="palette">
 | 
				
			||||||
    <palette [(selected)]="drawColor"></palette>
 | 
					    <palette [(selected)]="drawColor"></palette>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    menu: ToolbarItem[];
 | 
					    menu: ToolbarItem[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(public physicsService: PhysicsService, private syncService: SyncService, private snackBar: MatSnackBar, private bottomSheet: MatBottomSheet, private dialog: MatDialog, private route: ActivatedRoute) {
 | 
					    constructor(public physicsService: PhysicsService, public syncService: SyncService, private snackBar: MatSnackBar, private bottomSheet: MatBottomSheet, private dialog: MatDialog, private route: ActivatedRoute) {
 | 
				
			||||||
        this.name = Adjectives[Math.floor(Math.random() * Adjectives.length)] + Nouns[Math.floor(Math.random() * Nouns.length)];
 | 
					        this.name = Adjectives[Math.floor(Math.random() * Adjectives.length)] + Nouns[Math.floor(Math.random() * Nouns.length)];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.menu = [
 | 
					        this.menu = [
 | 
				
			||||||
@@ -86,7 +86,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
        this.syncService.mapData.pipe(filter(s => !!s)).subscribe((map: MapData) => {
 | 
					        this.syncService.mapData.pipe(filter(s => !!s)).subscribe((map: MapData) => {
 | 
				
			||||||
            this.map.deleteAll();
 | 
					            this.map.deleteAll();
 | 
				
			||||||
            if (map.circles) map.circles.forEach(c => this.map.newCircle(c));
 | 
					            if (map.circles) map.circles.forEach(c => this.map.newCircle(c));
 | 
				
			||||||
            if (map.locations) Object.values(map.locations).forEach(l => this.map.newMarker(l));
 | 
					            if (map.locations) Object.values(map.locations).forEach(l => this.map.newMarker(Object.assign(l, {icon: 'dot'})));
 | 
				
			||||||
            if (map.markers) map.markers.forEach(m => this.map.newMarker(m));
 | 
					            if (map.markers) map.markers.forEach(m => this.map.newMarker(m));
 | 
				
			||||||
            if (map.measurements) map.measurements.forEach(m => this.map.newMeasurement(m));
 | 
					            if (map.measurements) map.measurements.forEach(m => this.map.newMeasurement(m));
 | 
				
			||||||
            if (map.polygons) map.polygons.forEach(p => this.map.newPolygon(p));
 | 
					            if (map.polygons) map.polygons.forEach(p => this.map.newPolygon(p));
 | 
				
			||||||
@@ -116,7 +116,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
            if (this.positionMarker.circle) this.map.delete(this.positionMarker.circle);
 | 
					            if (this.positionMarker.circle) this.map.delete(this.positionMarker.circle);
 | 
				
			||||||
            this.positionMarker.arrow = this.map.newMarker({latlng: {lat: pos.latitude, lng: pos.longitude}, noSelect: true, noDelete: true, noDeleteTool: true, icon: 'arrow', rotationAngle: pos.heading, rotationOrigin: 'center'});
 | 
					            this.positionMarker.arrow = this.map.newMarker({latlng: {lat: pos.latitude, lng: pos.longitude}, noSelect: true, noDelete: true, noDeleteTool: true, icon: 'arrow', rotationAngle: pos.heading, rotationOrigin: 'center'});
 | 
				
			||||||
            this.positionMarker.circle = this.map.newCircle({latlng: {lat: pos.latitude, lng: pos.longitude}, color: '#2873d8', noSelect: true, noDelete: true, noDeleteTool: true, radius: pos.accuracy, interactive: false});
 | 
					            this.positionMarker.circle = this.map.newCircle({latlng: {lat: pos.latitude, lng: pos.longitude}, color: '#2873d8', noSelect: true, noDelete: true, noDeleteTool: true, radius: pos.accuracy, interactive: false});
 | 
				
			||||||
            this.syncService.addMyLocation({latlng: {lat: pos.latitude, lng: pos.longitude}, label: this.name, noDeleteTool: true});
 | 
					            let ignore = this.syncService.addMyLocation({latlng: {lat: pos.latitude, lng: pos.longitude}, label: this.name, noDeleteTool: true});
 | 
				
			||||||
            this.position = pos;
 | 
					            this.position = pos;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -169,7 +169,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
            let dimensions = await this.dialog.open(DimensionsDialogComponent, {data: ['Radius (m)'], panelClass: 'pb-0'}).afterClosed().toPromise();
 | 
					            let dimensions = await this.dialog.open(DimensionsDialogComponent, {data: ['Radius (m)'], panelClass: 'pb-0'}).afterClosed().toPromise();
 | 
				
			||||||
            if(!dimensions) return;
 | 
					            if(!dimensions) return;
 | 
				
			||||||
            menuItem.enabled = false;
 | 
					            menuItem.enabled = false;
 | 
				
			||||||
            let circle = {latlng: e.latlng, radius: dimensions[0] || 500, color: '#ff4141'};
 | 
					            let circle = {latlng: e.latlng, radius: dimensions[0]};
 | 
				
			||||||
            this.syncService.addCircle(circle);
 | 
					            this.syncService.addCircle(circle);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -204,7 +204,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
    startMarker = menuItem => {
 | 
					    startMarker = menuItem => {
 | 
				
			||||||
        this.sub = this.map.click.pipe(skip(1), take(1)).subscribe(e => {
 | 
					        this.sub = this.map.click.pipe(skip(1), take(1)).subscribe(e => {
 | 
				
			||||||
            menuItem.enabled = false;
 | 
					            menuItem.enabled = false;
 | 
				
			||||||
            let marker: Marker = {latlng: e.latlng, color: '#ff4141'};
 | 
					            let marker: Marker = {latlng: e.latlng};
 | 
				
			||||||
            this.syncService.addMarker(marker);
 | 
					            this.syncService.addMarker(marker);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -214,12 +214,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
        this.sub = this.map.click.pipe(skip(1), take(2), finalize(() => this.map.delete(lastPoint))).subscribe(e => {
 | 
					        this.sub = this.map.click.pipe(skip(1), take(2), finalize(() => this.map.delete(lastPoint))).subscribe(e => {
 | 
				
			||||||
            if (lastPoint) {
 | 
					            if (lastPoint) {
 | 
				
			||||||
                menuItem.enabled = false;
 | 
					                menuItem.enabled = false;
 | 
				
			||||||
                let measurement = {
 | 
					                let measurement = {latlng: {lat: lastPoint.getLatLng().lat, lng: lastPoint.getLatLng().lng}, latlng2: e.latlng};
 | 
				
			||||||
                    latlng: {lat: lastPoint.getLatLng().lat, lng: lastPoint.getLatLng().lng},
 | 
					 | 
				
			||||||
                    latlng2: e.latlng,
 | 
					 | 
				
			||||||
                    color: '#ff4141',
 | 
					 | 
				
			||||||
                    weight: 8
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                this.syncService.addMeasurement(measurement);
 | 
					                this.syncService.addMeasurement(measurement);
 | 
				
			||||||
                return this.map.delete(lastPoint);
 | 
					                return this.map.delete(lastPoint);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -231,13 +226,13 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
        let lastPoint;
 | 
					        let lastPoint;
 | 
				
			||||||
        this.sub = this.map.click.pipe(skip(1), finalize(() => this.map.delete(lastPoint))).subscribe(e => {
 | 
					        this.sub = this.map.click.pipe(skip(1), finalize(() => this.map.delete(lastPoint))).subscribe(e => {
 | 
				
			||||||
            if(!this.polygon) {
 | 
					            if(!this.polygon) {
 | 
				
			||||||
                let p = {latlng: [e.latlng], noDelete: true, color: '#ff4141'};
 | 
					                let p = {latlng: [e.latlng], noDelete: true};
 | 
				
			||||||
                this.polygon = this.map.newPolygon(p)
 | 
					                this.polygon = this.map.newPolygon(p)
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                this.polygon.addLatLng(e.latlng);
 | 
					                this.polygon.addLatLng(e.latlng);
 | 
				
			||||||
                this.map.delete(lastPoint);
 | 
					                this.map.delete(lastPoint);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            lastPoint = this.map.newMarker({latlng: e.latlng, color: '#ff4141'});
 | 
					            lastPoint = this.map.newMarker({latlng: e.latlng});
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -246,11 +241,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
        this.sub = this.map.click.pipe(skip(1), take(2), finalize(() => this.map.delete(lastPoint))).subscribe(e => {
 | 
					        this.sub = this.map.click.pipe(skip(1), take(2), finalize(() => this.map.delete(lastPoint))).subscribe(e => {
 | 
				
			||||||
            if (lastPoint) {
 | 
					            if (lastPoint) {
 | 
				
			||||||
                menuItem.enabled = false;
 | 
					                menuItem.enabled = false;
 | 
				
			||||||
                let rect = {
 | 
					                let rect = {latlng: {lat: lastPoint.getLatLng().lat, lng: lastPoint.getLatLng().lng}, latlng2: e.latlng};
 | 
				
			||||||
                    latlng: {lat: lastPoint.getLatLng().lat, lng: lastPoint.getLatLng().lng},
 | 
					 | 
				
			||||||
                    latlng2: e.latlng,
 | 
					 | 
				
			||||||
                    color: '#ff4141'
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                this.syncService.addRectangle(rect);
 | 
					                this.syncService.addRectangle(rect);
 | 
				
			||||||
                return this.map.delete(lastPoint);
 | 
					                return this.map.delete(lastPoint);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -260,7 +251,7 @@ export class MapComponent implements OnDestroy, OnInit {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    stopPolygon = () => {
 | 
					    stopPolygon = () => {
 | 
				
			||||||
        if(this.polygon) {
 | 
					        if(this.polygon) {
 | 
				
			||||||
            let p = {latlng: this.polygon.getLatLngs()[0].map(latlng => ({lat: latlng.lat, lng: latlng.lng})), color: '#ff4141'};
 | 
					            let p = {latlng: this.polygon.getLatLngs()[0].map(latlng => ({lat: latlng.lat, lng: latlng.lng}))};
 | 
				
			||||||
            this.map.delete(this.polygon);
 | 
					            this.map.delete(this.polygon);
 | 
				
			||||||
            this.polygon = null;
 | 
					            this.polygon = null;
 | 
				
			||||||
            this.syncService.addPolygon(p);
 | 
					            this.syncService.addPolygon(p);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user