From 20758c0deb4892e896f7f36a2ff1b6ae79ab3dee Mon Sep 17 00:00:00 2001
From: Aubrey Li <Aubrey-Li>
Date: Wed, 24 Nov 2021 15:03:11 -0500
Subject: map latest

---
 src/client/views/nodes/MapBox/MapBox.tsx | 96 +++++++++++++++++++-------------
 1 file changed, 58 insertions(+), 38 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 9cee7f2a2..6894cea19 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,5 +1,5 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Autocomplete, GoogleMap, GoogleMapProps, InfoWindow, Marker } from '@react-google-maps/api';
+import { Autocomplete, GoogleMap, GoogleMapProps, InfoWindow, LoadScript, Marker } from '@react-google-maps/api';
 import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx';
 import { observer } from "mobx-react";
 import * as React from "react";
@@ -29,22 +29,25 @@ import { SidebarAnnos } from '../../SidebarAnnos';
 import { StyleProp } from '../../StyleProvider';
 import { FieldView, FieldViewProps } from '../FieldView';
 import "./MapBox.scss";
-import { MapMarker } from './MapMarker';
-const _global = (window /* browser */ || global /* node */) as any;
+
+/**
+ * MapBox architecture:
+ * Main component: MapBox.tsx
+ * Supporting Components: SidebarAnnos, CollectionStackingView
+ * 
+ * MapBox is a node that extends the ViewBoxAnnotatableComponent. Similar to PDFBox and WebBox, it supports interaction between sidebar content and document content. 
+ * The main body of MapBox uses Google Maps API to allow location retrieval, adding map markers, pan and zoom, and open street view. 
+ * Dash Document architecture is integrated with Maps API: When drag and dropping documents with ExifData (gps Latitude and Longitude information) available, 
+ * sidebarAddDocument function checks if the document contains lat & lng information, if it does, then the document is added to both the sidebar and the infowindow (a pop up corresponding to a map marker--pin on map).
+ * The lat and lng field of the document is filled when importing (spec see ConvertDMSToDD method and processFileUpload method in Documents.ts).
+ * A map marker is considered a document that contains a collection with stacking view of documents, it has a lat, lng location, which is passed to Maps API's custom marker (red pin) to be rendered on the google maps
+ */
+
+// const _global = (window /* browser */ || global /* node */) as any;
 
 type MapDocument = makeInterface<[typeof documentSchema]>;
 const MapDocument = makeInterface(documentSchema);
 
-export type Coordinates = {
-    lat: number,
-    lng: number,
-}
-
-export type LocationData = {
-    id: string;
-    pos: Coordinates;
-};
-
 const mapContainerStyle = {
     height: '100%',
 };
@@ -58,6 +61,9 @@ const mapOptions = {
     fullscreenControl: false,
 }
 
+/**
+ * Consider integrating later: allows for drawing, circling, making shapes on map
+ */
 const drawingManager = new google.maps.drawing.DrawingManager({
     drawingControl: true,
     drawingControlOptions: {
@@ -65,13 +71,14 @@ const drawingManager = new google.maps.drawing.DrawingManager({
         drawingModes: [
             google.maps.drawing.OverlayType.MARKER,
             // currently we are not supporting the following drawing mode on map, a thought for future development
-            // google.maps.drawing.OverlayType.CIRCLE,
-            // google.maps.drawing.OverlayType.POLYLINE,
+            google.maps.drawing.OverlayType.CIRCLE,
+            google.maps.drawing.OverlayType.POLYLINE,
         ],
     },
 });
 
 
+// options for searchbox in Google Maps Places Autocomplete API
 const options = {
     fields: ["formatted_address", "geometry", "name"], // note: level of details is charged by item per retrieval, not recommended to return all fields
     strictBounds: false,
@@ -96,7 +103,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     // @observable private markerIdToMapMarker: { [id: string]: Doc | MapMarker | undefined } = {};
     @observable private center = navigator.geolocation ? navigator.geolocation.getCurrentPosition : defaultCenter;
     @observable private zoom = 2.5;
-    @observable private infoWindowOpen = false;
     @observable private _marqueeing: number[] | undefined;
     @observable private _isAnnotating = false;
     @observable private bounds = new window.google.maps.LatLngBounds();
@@ -105,10 +111,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     @observable private searchBox = new window.google.maps.places.Autocomplete(this.inputRef.current!, options);
     @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]); }; // method to add MapMarker to allMapMarkers
-    //TODO: change all markers to a filter function to change 
+    @computed get allMapMarkers() { return DocListCast(this.dataDoc[this.annotationKey]); };
     @observable private toggleAddMarker = false;
-
     private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
 
 
@@ -241,18 +245,26 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 console.log(this.allMapMarkers)
             }
         })
-        // this._map.addListener(drawingManager, 'markercomplete', this.addMarker)
     }
 
+    /**
+     * Load and render all map markers
+     * @param marker 
+     * @param place 
+     */
     @action
     private markerLoadHandler = (marker: google.maps.Marker, place: Doc) => {
         place[Id] ? this.markerMap[place[Id]] = marker : null;
-        // place[Id] ? this.markerIdToMapMarker[place[Id]] = place : null;
 
         console.log("the following is a markerMap from id to Marker:")
         console.log(this.markerMap);
     }
 
+    /**
+     * on clicking the map marker, set the selected place to the marker document & set infowindowopen to be true
+     * @param e 
+     * @param place 
+     */
     @action
     private markerClickHandler = (e: MouseEvent, place: Doc) => {
         // set which place was clicked
@@ -266,7 +278,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     /**
-     * Called when dragging documents into map sidebar or directly into infowindow
+     * Called when dragging documents into map sidebar or directly into infowindow; to create a map marker, ref to MapMarkerDocument in Documents.ts
      * @param doc 
      * @param sidebarKey 
      * @returns 
@@ -294,6 +306,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return this.addDocument(doc, sidebarKey); // add to sidebar list
     }
 
+    /**
+     * Removing documents from the sidebar
+     * @param doc 
+     * @param sidebarKey 
+     * @returns 
+     */
     sidebarRemoveDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
         if (this.layoutDoc._showSidebar) this.toggleSidebar();
         const docs = doc instanceof Doc ? [doc] : doc;
@@ -386,6 +404,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         place.infoWindowOpen = false;
     }
 
+    /**
+     * Handles toggle of sidebar on click the little comment button
+     */
     @computed get sidebarHandle() {
         TraceMobx();
         const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
@@ -403,6 +424,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             </div>;
     }
 
+    // TODO: Adding highlight box layer to Maps
     @action
     toggleSidebar = () => {
         const prevWidth = this.sidebarWidth();
@@ -459,20 +481,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     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);
+            this.rootDoc
         return anchor;
     }
 
     infoWidth = () => this.props.PanelWidth() / 5;
     infoHeight = () => this.props.PanelWidth() / 5;
 
-    //documentView 
+    // Collection stacking view for documents in the infowindow of a map marker
     private renderChildDocs = (selectedDoc: Doc) => {
         return <div style={{ width: this.infoWidth(), height: this.infoHeight() }}>
             <CollectionStackingView {
@@ -521,6 +537,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         ))
     }
 
+    /**
+     * Renders infowindow corresponding to a map marker document
+     * @param place 
+     * @returns 
+     */
     private renderInfoWindow = (place: Doc) => {
 
         return place.infoWindowOpen && (
@@ -540,6 +561,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         )
     }
 
+    // TODO: auto center on select a document in the sidebar
     private handleMapCenter = (map: google.maps.Map) => {
         console.log("print the selected views in selectionManager:")
         if (SelectionManager.Views().lastElement()) {
@@ -579,13 +601,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 addDocument={this.sidebarAddDocument}
                 childPointerEvents={true}
                 pointerEvents={CurrentUserUtils.SelectedTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
-        return <div className="mapBox" ref={this._ref}
-        // style={{ pointerEvents: this.isContentActive() ? undefined : "none" }} 
-        >
-            {/* // {/* <LoadScript
-                //     googleMapsApiKey={process.env.GOOGLE_MAPS!}
-                //     libraries={['places', 'drawing']}
-                // >  */}
+        return <div className="mapBox" ref={this._ref}>
+            {/* <LoadScript
+                googleMapsApiKey={process.env.GOOGLE_MAPS!}
+                libraries={['places', 'drawing']}
+            > */}
             <div className="mapBox-wrapper"
                 onWheel={e => e.stopPropagation()}
                 onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()}
@@ -627,7 +647,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                         annotationLayer={this._annotationLayer.current}
                         mainCont={this._mainCont.current} />}
             </div>
-            {/* {/* </LoadScript > */}
+            {/* </LoadScript > */}
             <div className="mapBox-sidebar"
                 style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
                 <SidebarAnnos ref={this._sidebarRef}
-- 
cgit v1.2.3-70-g09d2

