From becf6eeac2bd370fef2eb67c107ccfaeef5805e4 Mon Sep 17 00:00:00 2001
From: Aubrey-Li <63608597+Aubrey-Li@users.noreply.github.com>
Date: Sat, 21 Aug 2021 13:52:34 -0700
Subject: render map marker gps updates

---
 src/client/views/nodes/MapBox/MapBox.tsx | 163 +++++++++++++++++++++++--------
 1 file changed, 120 insertions(+), 43 deletions(-)

(limited to 'src/client/views/nodes/MapBox/MapBox.tsx')

diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 56203f3ae..e62f835b2 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,19 +1,24 @@
 import { Autocomplete, GoogleMap, GoogleMapProps, InfoWindow, Marker } from '@react-google-maps/api';
-import { action, computed, IReactionDisposer, observable } from 'mobx';
+import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx';
 import { observer } from "mobx-react";
 import * as React from "react";
-import { Doc, DocListCast, WidthSym } from '../../../../fields/Doc';
+import { DataSym, Doc, DocListCast, FieldsSym, WidthSym } from '../../../../fields/Doc';
 import { documentSchema } from '../../../../fields/documentSchemas';
 import { makeInterface } from '../../../../fields/Schema';
 import { NumCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, setupMoveUpEvents } from '../../../../Utils';
+import { Docs } from '../../../documents/Documents';
 import { DragManager } from '../../../util/DragManager';
 import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent';
+import { AnchorMenu } from '../../pdf/AnchorMenu';
 import { SidebarAnnos } from '../../SidebarAnnos';
 import { StyleProp } from '../../StyleProvider';
 import { FieldView, FieldViewProps } from '../FieldView';
 import "./MapBox.scss";
 import { MapMarker } from './MapMarker';
+import { DocumentType } from '../../../documents/DocumentTypes';
+import { identity } from 'lodash';
+import { Id } from '../../../../fields/FieldSymbols';
 
 type MapDocument = makeInterface<[typeof documentSchema]>;
 const MapDocument = makeInterface(documentSchema);
@@ -76,7 +81,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     @observable private inputRef = React.createRef<HTMLInputElement>();
     @observable private searchMarkers: google.maps.Marker[] = [];
     @observable private searchBox = new window.google.maps.places.Autocomplete(this.inputRef.current!, options);
-    @observable private childDocs: MapMarker[] = [];
+    @observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
+    @computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); };
+    @computed get allMapMarkers() { return DocListCast(this.dataDoc[this.annotationKey]); };
+    @observable private allMarkers: Doc[] = [];
 
 
     @observable _showSidebar = false;
@@ -96,17 +104,43 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         this.searchBox = searchBox;
     }
 
-    // iterate childDocs to size, center, and zoom map to contain all markers
+    // iterate allMarkers to size, center, and zoom map to contain all markers
     private fitBounds = (map: google.maps.Map) => {
         console.log('map bound is:' + this.bounds);
-        this.childDocs.map(place => {
-            this.bounds.extend(place._latlngLocation);
+        this.allMarkers.map(place => {
+            this.bounds.extend({ lat: NumCast(place.lat), lng: NumCast(place.lng) });
             return place._markerId;
         });
         map.fitBounds(this.bounds)
     }
 
-    // store a reference to google map instance; fit map bounds to contain all markers
+
+    private hasGeolocation = (doc: Doc) => {
+        return doc.type === DocumentType.IMG
+
+    }
+
+
+    /**
+     * A function that examines allMapMarkers docs in the map node and form MapMarkers
+     */
+    private fillMarkers = () => {
+        this.allMapMarkers?.forEach(doc => {
+            // search for if the map marker exists, else create marker
+            if (doc.lat !== undefined && doc.lng !== undefined) {
+                const marker = Docs.Create.MapMarkerDocument(NumCast(doc.lat), NumCast(doc.lng), [], {})
+                this.allMarkers.push(marker)
+            }
+        })
+    }
+
+
+    /**
+     * store a reference to google map instance
+     * setup the drawing manager on the top right corner of map
+     * fit map bounds to contain all markers 
+     * @param map 
+     */
     @action
     private loadHandler = (map: google.maps.Map) => {
         this._map = map;
@@ -125,11 +159,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             alert("Your geolocation is not supported by browser.")
         }
         this.fitBounds(map);
+        this.fillMarkers();
     }
 
     @action
-    private markerLoadHandler = (marker: google.maps.Marker, place: MapMarker) => {
-        place._markerId ? this.markerMap[place._markerId] = marker : null;
+    private markerLoadHandler = (marker: google.maps.Marker, place: Doc) => {
+        place[Id] ? this.markerMap[place[Id]] = marker : null;
     }
 
     @action
@@ -156,7 +191,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
      */
     sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
         if (!this.layoutDoc._showSidebar) this.toggleSidebar();
-        return this.addDocument(doc, sidebarKey);
+        const docs = doc instanceof Doc ? [doc] : doc
+        docs.forEach(doc => {
+            if (doc.lat !== undefined && doc.lng !== undefined) {
+                const marker = Docs.Create.MapMarkerDocument(NumCast(doc.lat), NumCast(doc.lng), [], {})
+                this.addDocument(marker, this.annotationKey)
+            }
+        }) //add to annotation list
+        return this.addDocument(doc, sidebarKey); // add to sidebar list
     }
 
     /**
@@ -183,6 +225,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); }
 
 
+    /**
+     * function that reads the place inputed from searchbox, then zoom in on the location that's been autocompleted;
+     * add a customized temporary marker on the map
+     */
     @action
     private handlePlaceChanged = () => {
         console.log(this.searchBox);
@@ -228,6 +274,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         )
     }
 
+
     @action
     private handleInfoWindowClose = () => {
         if (this.infoWindowOpen) {
@@ -246,6 +293,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     public get SidebarKey() { return this.fieldKey + "-sidebar"; }
+
     @computed get sidebarHandle() {
         const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
         return (!annotated && !this.isContentActive()) ? (null) : <div className="mapBox-sidebar-handle" onPointerDown={this.sidebarDown}
@@ -254,6 +302,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 background: this.props.styleProvider?.(this.rootDoc, this.props as any, StyleProp.WidgetColor + (annotated ? ":annotated" : ""))
             }} />;
     }
+
     @action
     toggleSidebar = () => {
         const prevWidth = this.sidebarWidth();
@@ -271,6 +320,65 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return false;
     }
 
+    // TODO what's the difference between savedAnnotations & allMapMarkers?
+    getAnchor = () => {
+        const anchor =
+            AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ??
+            this.rootDoc // if anchormenu pops up else return rootDoc (map)
+        // Docs.Create.MapMarkerDocument(this.allMapMarkers, {
+        //     title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
+        //     annotationOn: this.rootDoc,
+        //     y: NumCast(this.layoutDoc._scrollTop),
+        // });
+        // this.addDocument(anchor);
+        return anchor;
+    }
+
+    private saveMarkerInfo = () => {
+
+    }
+    // create marker prop --> func that 
+    private renderMarkers = () => {
+        this.allMarkers.map(place => (
+            <Marker
+                key={place[Id]}
+                position={{ lat: NumCast(place.lat), lng: NumCast(place.lng) }}
+                onLoad={marker => this.markerLoadHandler(marker, place)}
+                onClick={e => this.markerClickHandler(e, place)}
+            />
+        ))
+    }
+
+    private renderInfoWindow = (marker: MapMarker) => {
+        return this.infoWindowOpen && this.selectedPlace && (
+            <InfoWindow
+                anchor={this.markerMap[this.selectedPlace._markerId!]}
+                onCloseClick={this.handleInfoWindowClose}
+            >
+                <div style={{ backgroundColor: 'white', opacity: 0.75, padding: 12 }}>
+                    <div style={{ fontSize: 16 }}>
+                        <div>
+                            {// TODO need to figure out how to render these childDocs of the MapMarker in InfoWindow
+                                marker.childDocs}
+                            <hr />
+                            <form>
+                                <label>Title: </label><br />
+                                <input type="text" id="title" name="title"></input><br />
+                                <label>Desription: </label><br />
+                                <textarea style={{ height: 150 }} id="description" name="description" placeholder="Notes, a short description of this location, a brief comment, etc."></textarea>
+                                <button type="submit">Save</button>
+                            </form>
+                            <hr />
+                            <div>
+                                <button>New link+</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </InfoWindow>
+        )
+    }
+
     render() {
         return <div className="mapBox" ref={this._ref}
             style={{ pointerEvents: this.isContentActive() ? undefined : "none" }} >
@@ -295,39 +403,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                         <input ref={this.inputRef} className="searchbox" type="text" placeholder="Search anywhere:" />
                     </Autocomplete>
 
-                    {this.childDocs.map(place => (
-                        <Marker
-                            key={place._markerId}
-                            position={place._latlngLocation}
-                            onLoad={marker => this.markerLoadHandler(marker, place)}
-                            onClick={e => this.markerClickHandler(e, place)}
-                        />
-                    ))}
-                    {this.infoWindowOpen && this.selectedPlace && (
-                        <InfoWindow
-                            anchor={this.markerMap[this.selectedPlace._markerId!]}
-                            onCloseClick={this.handleInfoWindowClose}
-                        >
-                            <div style={{ backgroundColor: 'white', opacity: 0.75, padding: 12 }}>
-                                <div style={{ fontSize: 16 }}>
-                                    <div>
-                                        <img src="http://placekitten.com/200/300" />
-                                        <hr />
-                                        <form>
-                                            <label>Title: </label><br />
-                                            <input type="text" id="fname" name="fname"></input><br />
-                                            <label>Desription: </label><br />
-                                            <textarea style={{ height: 150 }} id="lname" name="lname" placeholder="Notes, a short description of this location, a brief comment, etc."></textarea>
-                                        </form>
-                                        <hr />
-                                        <div>
-                                            <button>New link+</button>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </InfoWindow>
-                    )}
+                    {this.renderMarkers}
+                    {this.renderInfoWindow}
                 </GoogleMap>
             </div>
             {/* {/* </LoadScript > */}
-- 
cgit v1.2.3-70-g09d2

