From 32f5040c44dc302e3dd53cecd9be4cd51a474d3f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 14 Feb 2023 14:57:25 -0500
Subject: fixed pinning regions on pdf/web pages to allow proper pres
 following.  added click on pres item# to select w/o navigation.  fixed
 dashDocView to be selectable without losing selection to parent textbox. 
 added BingMaps rudimentary option to googleMaps

---
 src/client/views/nodes/MapBox/MapBox.tsx | 148 +++++++++++++++++++------------
 1 file changed, 91 insertions(+), 57 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 5940fc075..039f11cd1 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,5 +1,6 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api';
+import BingMapsReact from 'bingmaps-react';
 import { action, computed, IReactionDisposer, observable, ObservableMap, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
@@ -43,20 +44,22 @@ const mapContainerStyle = {
 };
 
 const defaultCenter = {
-    lat: 38.685,
-    lng: -115.234,
+    lat: 42.360081,
+    lng: -71.058884,
 };
 
 const mapOptions = {
     fullscreenControl: false,
 };
 
+const bingApiKey = process.env.BING_MAPS; // if you're running local, get a Bing Maps api key here: https://www.bingmapsportal.com/  and then add it to the .env file in the Dash-Web root directory as: _CLIENT_BING_MAPS=<your apikey>
 const apiKey = process.env.GOOGLE_MAPS;
 
 const script = document.createElement('script');
 script.defer = true;
 script.async = true;
 script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places,drawing`;
+console.log(script.src);
 document.head.appendChild(script);
 
 /**
@@ -84,6 +87,7 @@ const options = {
 
 @observer
 export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps & Partial<GoogleMapProps>>() {
+    static UseBing = true;
     private _dropDisposer?: DragManager.DragDropDisposer;
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
@@ -551,69 +555,99 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     infoHeight = () => this.props.PanelHeight() / 5;
     anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
     savedAnnotations = () => this._savedAnnotations;
+
+    _bingSearchManager: any;
+    _bingMap: any;
+    get MicrosoftMaps() {
+        return (window as any).Microsoft.Maps;
+    }
+    // uses Bing Search to retrieve lat/lng for a location.  eg.,
+    //   const results = this.geocodeQuery(map.map, 'Philadelphia, PA');
+    // to move the map to that location:
+    //     const location = await this.geocodeQuery(this._bingMap, 'Philadelphia, PA');
+    //     this._bingMap.current.setView({
+    //        mapTypeId: this.MicrosoftMaps.MapTypeId.aerial,
+    //        center: new this.MicrosoftMaps.Location(loc.latitude, loc.longitude),
+    //     });
+    //
+    bingGeocode = (map: any, query: string) => {
+        return new Promise<{ latitude: number; longitude: number }>((res, reject) => {
+            //If search manager is not defined, load the search module.
+            if (!this._bingSearchManager) {
+                //Create an instance of the search manager and call the geocodeQuery function again.
+                this.MicrosoftMaps.loadModule('Microsoft.Maps.Search', () => {
+                    this._bingSearchManager = new this.MicrosoftMaps.Search.SearchManager(map.current);
+                    res(this.bingGeocode(map, query));
+                });
+            } else {
+                this._bingSearchManager.geocode({
+                    where: query,
+                    callback: action((r: any) => {
+                        res(r.results[0].location);
+                    }),
+                    errorCallback: (e: any) => reject(),
+                });
+            }
+        });
+    };
+
+    bingViewOptions = {
+        center: { latitude: defaultCenter.lat, longitude: defaultCenter.lng },
+        mapTypeId: 'grayscale',
+    };
+    bingMapOptions = {
+        navigationBarMode: 'square',
+    };
+    bingMapReady = (map: any) => (this._bingMap = map.map);
     render() {
         const renderAnnotations = (docFilters?: () => string[]) => null;
-        // bcz: commmented this out.  Otherwise, any documents that are rendered with an InfoWindow of a marker
-        //      will also be rendered as freeform annotations on the map. However, it doesn't seem that rendering
-        //      freeform documents on the map does anything anyway, so getting rid of it for now.  Also, since documents
-        //      are rendered twice, adding a new note to the InfoWindow loses focus immediately on creation since it gets
-        //      shifted to the non-visible view of the document in this freeform view.
-        // <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
-        //     renderDepth={this.props.renderDepth + 1}
-        //     isAnnotationOverlay={true}
-        //     fieldKey={this.annotationKey}
-        //     CollectionView={undefined}
-        //     setPreviewCursor={this.setPreviewCursor}
-        //     PanelWidth={this.panelWidth}
-        //     PanelHeight={this.panelHeight}
-        //     ScreenToLocalTransform={this.scrollXf}
-        //     scaling={returnOne}
-        //     dropAction={"alias"}
-        //     docFilters={docFilters || this.props.docFilters}
-        //     dontRenderDocuments={docFilters ? false : true}
-        //     select={emptyFunction}
-        //     bringToFront={emptyFunction}
-        //     whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
-        //     removeDocument={this.removeDocument}
-        //     moveDocument={this.moveDocument}
-        //     addDocument={this.sidebarAddDocument}
-        //     childPointerEvents={"all"}
-        //     pointerEvents={Doc.ActiveTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
         return (
             <div className="mapBox" ref={this._ref}>
-                {/*console.log(apiKey)*/}
-                {/* <LoadScript
-                googleMapsApiKey={apiKey!}
-                libraries={['places', 'drawing']}
-            > */}
-                <div className="mapBox-wrapper" onWheel={e => e.stopPropagation()} onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()} style={{ width: `calc(100% - ${this.sidebarWidthPercent})` }}>
+                <div
+                    className="mapBox-wrapper"
+                    onWheel={e => e.stopPropagation()}
+                    onPointerDown={async e => {
+                        e.button === 0 && !e.ctrlKey && e.stopPropagation();
+                        // just a simple test of bing maps geocode api
+                        // const loc = await this.bingGeocode(this._bingMap, 'Philadelphia, PA');
+                        // this._bingMap.current.setView({
+                        //     mapTypeId: this.MicrosoftMaps.MapTypeId.aerial,
+                        //     center: new this.MicrosoftMaps.Location(loc.latitude, loc.longitude),
+                        //     zoom: 15,
+                        // });
+                    }}
+                    style={{ width: `calc(100% - ${this.sidebarWidthPercent})` }}>
                     <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
                     {renderAnnotations(this.opaqueFilter)}
                     {SnappingManager.GetIsDragging() ? null : renderAnnotations()}
                     {this.annotationLayer}
-                    <GoogleMap mapContainerStyle={mapContainerStyle} onZoomChanged={this.zoomChanged} onCenterChanged={this.centered} onLoad={this.loadHandler} options={mapOptions}>
-                        <Autocomplete onLoad={this.setSearchBox} onPlaceChanged={this.handlePlaceChanged}>
-                            <input className="mapBox-input" ref={this.inputRef} type="text" onKeyDown={e => e.stopPropagation()} placeholder="Enter location" />
-                        </Autocomplete>
-
-                        {this.renderMarkers()}
-                        {this.allMapMarkers
-                            .filter(marker => marker.infoWindowOpen)
-                            .map(marker => (
-                                <MapBoxInfoWindow
-                                    key={marker[Id]}
-                                    {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
-                                    place={marker}
-                                    markerMap={this.markerMap}
-                                    PanelWidth={this.infoWidth}
-                                    PanelHeight={this.infoHeight}
-                                    moveDocument={this.moveDocument}
-                                    isAnyChildContentActive={this.isAnyChildContentActive}
-                                    whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
-                                />
-                            ))}
-                        {/* {this.handleMapCenter(this._map)} */}
-                    </GoogleMap>
+
+                    {!MapBox.UseBing ? null : <BingMapsReact onMapReady={this.bingMapReady} bingMapsKey={bingApiKey} height="100%" mapOptions={this.bingMapOptions} width="100%" viewOptions={this.bingViewOptions} />}
+                    <div style={{ display: MapBox.UseBing ? 'none' : undefined }}>
+                        <GoogleMap mapContainerStyle={mapContainerStyle} onZoomChanged={this.zoomChanged} onCenterChanged={this.centered} onLoad={this.loadHandler} options={mapOptions}>
+                            <Autocomplete onLoad={this.setSearchBox} onPlaceChanged={this.handlePlaceChanged}>
+                                <input className="mapBox-input" ref={this.inputRef} type="text" onKeyDown={e => e.stopPropagation()} placeholder="Enter location" />
+                            </Autocomplete>
+
+                            {this.renderMarkers()}
+                            {this.allMapMarkers
+                                .filter(marker => marker.infoWindowOpen)
+                                .map(marker => (
+                                    <MapBoxInfoWindow
+                                        key={marker[Id]}
+                                        {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+                                        place={marker}
+                                        markerMap={this.markerMap}
+                                        PanelWidth={this.infoWidth}
+                                        PanelHeight={this.infoHeight}
+                                        moveDocument={this.moveDocument}
+                                        isAnyChildContentActive={this.isAnyChildContentActive}
+                                        whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
+                                    />
+                                ))}
+                            {/* {this.handleMapCenter(this._map)} */}
+                        </GoogleMap>
+                    </div>
                     {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? null : (
                         <MarqueeAnnotator
                             rootDoc={this.rootDoc}
-- 
cgit v1.2.3-70-g09d2

