diff options
Diffstat (limited to 'src/client/views/nodes/MapBox/MapBox2.tsx')
-rw-r--r-- | src/client/views/nodes/MapBox/MapBox2.tsx | 1194 |
1 files changed, 597 insertions, 597 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx index a77bfc50a..39ed6a47e 100644 --- a/src/client/views/nodes/MapBox/MapBox2.tsx +++ b/src/client/views/nodes/MapBox/MapBox2.tsx @@ -1,597 +1,597 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api'; -import { action, computed, IReactionDisposer, observable, ObservableMap, runInAction } from 'mobx'; -import { observer } from 'mobx-react'; -import * as React from 'react'; -import { Doc, DocListCast, Opt } from '../../../../fields/Doc'; -import { Id } from '../../../../fields/FieldSymbols'; -import { NumCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; -import { Docs } from '../../../documents/Documents'; -import { DragManager } from '../../../util/DragManager'; -import { SnappingManager } from '../../../util/SnappingManager'; -import { UndoManager } from '../../../util/UndoManager'; -import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; -import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; -import { Colors } from '../../global/globalEnums'; -import { AnchorMenu } from '../../pdf/AnchorMenu'; -import { Annotation } from '../../pdf/Annotation'; -import { SidebarAnnos } from '../../SidebarAnnos'; -import { FieldView, FieldViewProps } from '../FieldView'; -import { PinProps } from '../trails'; -import './MapBox2.scss'; -import { MapBoxInfoWindow } from './MapBoxInfoWindow'; - -/** - * MapBox2 architecture: - * Main component: MapBox2.tsx - * Supporting Components: SidebarAnnos, CollectionStackingView - * - * MapBox2 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 MapBox2 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; - -const mapContainerStyle = { - height: '100%', -}; - -const defaultCenter = { - lat: 42.360081, - lng: -71.058884, -}; - -const mapOptions = { - fullscreenControl: false, -}; - -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); - -/** - * Consider integrating later: allows for drawing, circling, making shapes on map - */ -// const drawingManager = new window.google.maps.drawing.DrawingManager({ -// drawingControl: true, -// drawingControlOptions: { -// position: google.maps.ControlPosition.TOP_RIGHT, -// 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, -// ], -// }, -// }); - -// 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, - types: ['establishment'], // type pf places, subject of change according to user need -} as google.maps.places.AutocompleteOptions; - -@observer -export class MapBox2 extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps & Partial<GoogleMapProps>>() { - private _dropDisposer?: DragManager.DragDropDisposer; - private _disposers: { [name: string]: IReactionDisposer } = {}; - private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef(); - @observable private _overlayAnnoInfo: Opt<Doc>; - showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno)); - public static LayoutString(fieldKey: string) { - return FieldView.LayoutString(MapBox2, fieldKey); - } - public get SidebarKey() { - return this.fieldKey + '_sidebar'; - } - private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void); - @computed get inlineTextAnnotations() { - return this.allMapMarkers.filter(a => a.text_inlineAnnotations); - } - - @observable private _map: google.maps.Map = null as unknown as google.maps.Map; - @observable private selectedPlace: Doc | undefined; - @observable private markerMap: { [id: string]: google.maps.Marker } = {}; - @observable private center = navigator.geolocation ? navigator.geolocation.getCurrentPosition : defaultCenter; - @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 _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 toggleAddMarker = false; - - @observable _showSidebar = false; - @computed get SidebarShown() { - return this._showSidebar || this.layoutDoc._layout_showSidebar ? true : false; - } - - static _canAnnotate = true; - static _hadSelection: boolean = false; - private _sidebarRef = React.createRef<SidebarAnnos>(); - private _ref: React.RefObject<HTMLDivElement> = React.createRef(); - - componentDidMount() { - this.props.setContentView?.(this); - } - - @action - private setSearchBox = (searchBox: any) => { - this.searchBox = searchBox; - }; - - // iterate allMarkers to size, center, and zoom map to contain all markers - private fitBounds = (map: google.maps.Map) => { - const curBounds = map.getBounds() ?? new window.google.maps.LatLngBounds(); - const isFitting = this.allMapMarkers.reduce((fits, place) => fits && curBounds?.contains({ lat: NumCast(place.lat), lng: NumCast(place.lng) }), true as boolean); - !isFitting && map.fitBounds(this.allMapMarkers.reduce((bounds, place) => bounds.extend({ lat: NumCast(place.lat), lng: NumCast(place.lng) }), new window.google.maps.LatLngBounds())); - }; - - /** - * Custom control for add marker button - * @param controlDiv - * @param map - */ - private CenterControl = () => { - const controlDiv = document.createElement('div'); - controlDiv.className = 'MapBox2-addMarker'; - // Set CSS for the control border. - const controlUI = document.createElement('div'); - controlUI.style.backgroundColor = '#fff'; - controlUI.style.borderRadius = '3px'; - controlUI.style.cursor = 'pointer'; - controlUI.style.marginTop = '10px'; - controlUI.style.borderRadius = '4px'; - controlUI.style.marginBottom = '22px'; - controlUI.style.textAlign = 'center'; - controlUI.style.position = 'absolute'; - controlUI.style.width = '32px'; - controlUI.style.height = '32px'; - controlUI.title = 'Click to toggle marker mode. In marker mode, click on map to place a marker.'; - - const plIcon = document.createElement('img'); - plIcon.src = 'https://cdn4.iconfinder.com/data/icons/wirecons-free-vector-icons/32/add-256.png'; - plIcon.style.color = 'rgb(25,25,25)'; - plIcon.style.fontFamily = 'Roboto,Arial,sans-serif'; - plIcon.style.fontSize = '16px'; - plIcon.style.lineHeight = '32px'; - plIcon.style.left = '18'; - plIcon.style.top = '15'; - plIcon.style.position = 'absolute'; - plIcon.width = 14; - plIcon.height = 14; - plIcon.innerHTML = 'Add'; - controlUI.appendChild(plIcon); - - // Set CSS for the control interior. - const markerIcon = document.createElement('img'); - markerIcon.src = 'https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678111-map-marker-1024.png'; - markerIcon.style.color = 'rgb(25,25,25)'; - markerIcon.style.fontFamily = 'Roboto,Arial,sans-serif'; - markerIcon.style.fontSize = '16px'; - markerIcon.style.lineHeight = '32px'; - markerIcon.style.left = '-2'; - markerIcon.style.top = '1'; - markerIcon.width = 30; - markerIcon.height = 30; - markerIcon.style.position = 'absolute'; - markerIcon.innerHTML = 'Add'; - controlUI.appendChild(markerIcon); - - // Setup the click event listeners - controlUI.addEventListener('click', () => { - if (this.toggleAddMarker === true) { - this.toggleAddMarker = false; - console.log('add marker button status:' + this.toggleAddMarker); - controlUI.style.backgroundColor = '#fff'; - markerIcon.style.color = 'rgb(25,25,25)'; - } else { - this.toggleAddMarker = true; - console.log('add marker button status:' + this.toggleAddMarker); - controlUI.style.backgroundColor = '#4476f7'; - markerIcon.style.color = 'rgb(255,255,255)'; - } - }); - controlDiv.appendChild(controlUI); - return controlDiv; - }; - - /** - * Place the marker on google maps & store the empty marker as a MapMarker Document in allMarkers list - * @param position - the LatLng position where the marker is placed - * @param map - */ - @action - private placeMarker = (position: google.maps.LatLng, map: google.maps.Map) => { - const marker = new google.maps.Marker({ - position: position, - map: map, - }); - map.panTo(position); - const mapMarker = Docs.Create.PushpinDocument(NumCast(position.lat()), NumCast(position.lng()), false, [], {}); - this.addDocument(mapMarker, this.annotationKey); - }; - - _loadPending = true; - /** - * 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; - this._loadPending = true; - const centerControlDiv = this.CenterControl(); - map.controls[google.maps.ControlPosition.TOP_RIGHT].push(centerControlDiv); - //drawingManager.setMap(map); - // if (navigator.geolocation) { - // navigator.geolocation.getCurrentPosition( - // (position: Position) => { - // const pos = { - // lat: position.coords.latitude, - // lng: position.coords.longitude, - // }; - // this._map.setCenter(pos); - // } - // ); - // } else { - // alert("Your geolocation is not supported by browser.") - // }; - map.setZoom(NumCast(this.dataDoc.map_zoom, 2.5)); - map.setCenter(new google.maps.LatLng(NumCast(this.dataDoc.mapLat), NumCast(this.dataDoc.mapLng))); - setTimeout(() => { - if (this._loadPending && this._map.getBounds()) { - this._loadPending = false; - this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); - } - }, 250); - // listener to addmarker event - this._map.addListener('click', (e: MouseEvent) => { - if (this.toggleAddMarker === true) { - this.placeMarker((e as any).latLng, map); - } - }); - }; - - @action - centered = () => { - if (this._loadPending && this._map.getBounds()) { - this._loadPending = false; - this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); - } - this.dataDoc.mapLat = this._map.getCenter()?.lat(); - this.dataDoc.mapLng = this._map.getCenter()?.lng(); - }; - - @action - zoomChanged = () => { - if (this._loadPending && this._map.getBounds()) { - this._loadPending = false; - this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); - } - this.dataDoc.map_zoom = this._map.getZoom(); - }; - - /** - * 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; - }; - - /** - * 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: google.maps.MapMouseEvent, place: Doc) => { - // set which place was clicked - this.selectedPlace = place; - place.infoWindowOpen = true; - }; - - /** - * 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 - */ - sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => { - console.log('print all sidebar Docs'); - if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); - const docs = doc instanceof Doc ? [doc] : doc; - docs.forEach(doc => { - if (doc.lat !== undefined && doc.lng !== undefined) { - const existingMarker = this.allMapMarkers.find(marker => marker.lat === doc.lat && marker.lng === doc.lng); - if (existingMarker) { - Doc.AddDocToList(existingMarker, 'data', doc); - } else { - const marker = Docs.Create.PushpinDocument(NumCast(doc.lat), NumCast(doc.lng), false, [doc], {}); - this.addDocument(marker, this.annotationKey); - } - } - }); //add to annotation list - - 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._layout_showSidebar) this.toggleSidebar(); - const docs = doc instanceof Doc ? [doc] : doc; - return this.removeDocument(doc, sidebarKey); - }; - - /** - * Toggle sidebar onclick the tiny comment button on the top right corner - * @param e - */ - sidebarBtnDown = (e: React.PointerEvent) => { - setupMoveUpEvents( - this, - e, - (e, down, delta) => - runInAction(() => { - const localDelta = this.props - .ScreenToLocalTransform() - .scale(this.props.NativeDimScaling?.() || 1) - .transformDirection(delta[0], delta[1]); - const fullWidth = NumCast(this.layoutDoc._width); - const mapWidth = fullWidth - this.sidebarWidth(); - if (this.sidebarWidth() + localDelta[0] > 0) { - this._showSidebar = true; - this.layoutDoc._width = fullWidth + localDelta[0]; - this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; - } else { - this._showSidebar = false; - this.layoutDoc._width = mapWidth; - this.layoutDoc._layout_sidebarWidthPercent = '0%'; - } - return false; - }), - emptyFunction, - () => UndoManager.RunInBatch(this.toggleSidebar, 'toggle sidebar map') - ); - }; - - sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); - @computed get layout_sidebarWidthPercent() { - return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); - } - @computed get sidebarColor() { - return StrCast(this.layoutDoc.sidebar_color, 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 = () => { - const place = this.searchBox.getPlace(); - - if (!place.geometry || !place.geometry.location) { - // user entered the name of a place that wasn't suggested & pressed the enter key, or place details request failed - window.alert("No details available for input: '" + place.name + "'"); - return; - } - - // zoom in on the location of the search result - if (place.geometry.viewport) { - this._map.fitBounds(place.geometry.viewport); - } else { - this._map.setCenter(place.geometry.location); - this._map.setZoom(17); - } - - // customize icon => customized icon for the nature of the location selected - const icon = { - url: place.icon as string, - size: new google.maps.Size(71, 71), - origin: new google.maps.Point(0, 0), - anchor: new google.maps.Point(17, 34), - scaledSize: new google.maps.Size(25, 25), - }; - - // put temporary cutomized marker on searched location - this.searchMarkers.forEach(marker => { - marker.setMap(null); - }); - this.searchMarkers = []; - this.searchMarkers.push( - new window.google.maps.Marker({ - map: this._map, - icon, - title: place.name, - position: place.geometry.location, - }) - ); - }; - - /** - * Handles toggle of sidebar on click the little comment button - */ - @computed get sidebarHandle() { - return ( - <div - className="MapBox2-overlayButton-sidebar" - key="sidebar" - title="Toggle Sidebar" - style={{ - display: !this.props.isContentActive() ? 'none' : undefined, - top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5, - backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK, - }} - onPointerDown={this.sidebarBtnDown}> - <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={'comment-alt'} size="sm" /> - </div> - ); - } - - // TODO: Adding highlight box layer to Maps - @action - toggleSidebar = () => { - //1.2 * w * ? = .2 * w .2/1.2 - const prevWidth = this.sidebarWidth(); - this.layoutDoc._layout_showSidebar = (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; - this.layoutDoc._width = this.layoutDoc._layout_showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); - }; - - sidebarDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), true); - }; - sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => { - const bounds = this._ref.current!.getBoundingClientRect(); - this.layoutDoc._layout_sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; - this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%'; - e.preventDefault(); - return false; - }; - - setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func); - - addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => { - return this.addDocument(doc, annotationKey); - }; - - pointerEvents = () => { - return this.props.isContentActive() === false ? 'none' : this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none'; - }; - @computed get annotationLayer() { - return ( - <div className="MapBox2-annotationLayer" style={{ height: Doc.NativeHeight(this.Document) || undefined }} ref={this._annotationLayer}> - {this.inlineTextAnnotations - .sort((a, b) => NumCast(a.y) - NumCast(b.y)) - .map(anno => ( - <Annotation key={`${anno[Id]}-annotation`} {...this.props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} showInfo={this.showInfo} dataDoc={this.dataDoc} anno={anno} /> - ))} - </div> - ); - } - - getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => AnchorMenu.Instance?.GetAnchor(this._savedAnnotations, addAsAnnotation) ?? this.Document; - - /** - * render contents in allMapMarkers (e.g. images with exifData) into google maps as map marker - * @returns - */ - private renderMarkers = () => { - return this.allMapMarkers.map(place => ( - <Marker key={place[Id]} position={{ lat: NumCast(place.lat), lng: NumCast(place.lng) }} onLoad={marker => this.markerLoadHandler(marker, place)} onClick={(e: google.maps.MapMouseEvent) => this.markerClickHandler(e, place)} /> - )); - }; - - // 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()) { - // console.log(SelectionManager.Views().lastElement()); - // } - }; - - panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); - panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); - transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; - opaqueFilter = () => [...this.props.childFilters(), Utils.OpaqueBackgroundFilter]; - infoWidth = () => this.props.PanelWidth() / 5; - infoHeight = () => this.props.PanelHeight() / 5; - anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; - savedAnnotations = () => this._savedAnnotations; - - get MicrosoftMaps() { - return (window as any).Microsoft.Maps; - } - render() { - const renderAnnotations = (childFilters?: () => string[]) => null; - return ( - <div className="MapBox2" ref={this._ref}> - <div - className="MapBox2-wrapper" - onWheel={e => e.stopPropagation()} - onPointerDown={async e => { - e.button === 0 && !e.ctrlKey && e.stopPropagation(); - }} - style={{ width: `calc(100% - ${this.layout_sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}> - <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div> - {renderAnnotations(this.opaqueFilter)} - {SnappingManager.GetIsDragging() ? null : renderAnnotations()} - {this.annotationLayer} - - <div> - <GoogleMap mapContainerStyle={mapContainerStyle} onZoomChanged={this.zoomChanged} onCenterChanged={this.centered} onLoad={this.loadHandler} options={mapOptions}> - <Autocomplete onLoad={this.setSearchBox} onPlaceChanged={this.handlePlaceChanged}> - <input className="MapBox2-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]} - {...this.props} - setContentView={emptyFunction} - 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> - </div> - {/* </LoadScript > */} - <div className="MapBox2-sidebar" style={{ width: `${this.layout_sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}> - <SidebarAnnos - ref={this._sidebarRef} - {...this.props} - fieldKey={this.fieldKey} - Document={this.Document} - layoutDoc={this.layoutDoc} - dataDoc={this.dataDoc} - usePanelWidth={true} - showSidebar={this.SidebarShown} - nativeWidth={NumCast(this.layoutDoc._nativeWidth)} - whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} - PanelWidth={this.sidebarWidth} - sidebarAddDocument={this.sidebarAddDocument} - moveDocument={this.moveDocument} - removeDocument={this.sidebarRemoveDocument} - /> - </div> - {this.sidebarHandle} - </div> - ); - } -} +// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +// import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api'; +// import { action, computed, IReactionDisposer, observable, ObservableMap, runInAction } from 'mobx'; +// import { observer } from 'mobx-react'; +// import * as React from 'react'; +// import { Doc, DocListCast, Opt } from '../../../../fields/Doc'; +// import { Id } from '../../../../fields/FieldSymbols'; +// import { NumCast, StrCast } from '../../../../fields/Types'; +// import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; +// import { Docs } from '../../../documents/Documents'; +// import { DragManager } from '../../../util/DragManager'; +// import { SnappingManager } from '../../../util/SnappingManager'; +// import { UndoManager } from '../../../util/UndoManager'; +// import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; +// import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; +// import { Colors } from '../../global/globalEnums'; +// import { AnchorMenu } from '../../pdf/AnchorMenu'; +// import { Annotation } from '../../pdf/Annotation'; +// import { SidebarAnnos } from '../../SidebarAnnos'; +// import { FieldView, FieldViewProps } from '../FieldView'; +// import { PinProps } from '../trails'; +// import './MapBox2.scss'; +// import { MapBoxInfoWindow } from './MapBoxInfoWindow'; + +// /** +// * MapBox2 architecture: +// * Main component: MapBox2.tsx +// * Supporting Components: SidebarAnnos, CollectionStackingView +// * +// * MapBox2 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 MapBox2 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; + +// const mapContainerStyle = { +// height: '100%', +// }; + +// const defaultCenter = { +// lat: 42.360081, +// lng: -71.058884, +// }; + +// const mapOptions = { +// fullscreenControl: false, +// }; + +// 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); + +// /** +// * Consider integrating later: allows for drawing, circling, making shapes on map +// */ +// // const drawingManager = new window.google.maps.drawing.DrawingManager({ +// // drawingControl: true, +// // drawingControlOptions: { +// // position: google.maps.ControlPosition.TOP_RIGHT, +// // 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, +// // ], +// // }, +// // }); + +// // 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, +// types: ['establishment'], // type pf places, subject of change according to user need +// } as google.maps.places.AutocompleteOptions; + +// @observer +// export class MapBox2 extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps & Partial<GoogleMapProps>>() { +// private _dropDisposer?: DragManager.DragDropDisposer; +// private _disposers: { [name: string]: IReactionDisposer } = {}; +// private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef(); +// @observable private _overlayAnnoInfo: Opt<Doc>; +// showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno)); +// public static LayoutString(fieldKey: string) { +// return FieldView.LayoutString(MapBox2, fieldKey); +// } +// public get SidebarKey() { +// return this.fieldKey + '_sidebar'; +// } +// private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void); +// @computed get inlineTextAnnotations() { +// return this.allMapMarkers.filter(a => a.text_inlineAnnotations); +// } + +// @observable private _map: google.maps.Map = null as unknown as google.maps.Map; +// @observable private selectedPlace: Doc | undefined; +// @observable private markerMap: { [id: string]: google.maps.Marker } = {}; +// @observable private center = navigator.geolocation ? navigator.geolocation.getCurrentPosition : defaultCenter; +// @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 _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 toggleAddMarker = false; + +// @observable _showSidebar = false; +// @computed get SidebarShown() { +// return this._showSidebar || this.layoutDoc._layout_showSidebar ? true : false; +// } + +// static _canAnnotate = true; +// static _hadSelection: boolean = false; +// private _sidebarRef = React.createRef<SidebarAnnos>(); +// private _ref: React.RefObject<HTMLDivElement> = React.createRef(); + +// componentDidMount() { +// this.props.setContentView?.(this); +// } + +// @action +// private setSearchBox = (searchBox: any) => { +// this.searchBox = searchBox; +// }; + +// // iterate allMarkers to size, center, and zoom map to contain all markers +// private fitBounds = (map: google.maps.Map) => { +// const curBounds = map.getBounds() ?? new window.google.maps.LatLngBounds(); +// const isFitting = this.allMapMarkers.reduce((fits, place) => fits && curBounds?.contains({ lat: NumCast(place.lat), lng: NumCast(place.lng) }), true as boolean); +// !isFitting && map.fitBounds(this.allMapMarkers.reduce((bounds, place) => bounds.extend({ lat: NumCast(place.lat), lng: NumCast(place.lng) }), new window.google.maps.LatLngBounds())); +// }; + +// /** +// * Custom control for add marker button +// * @param controlDiv +// * @param map +// */ +// private CenterControl = () => { +// const controlDiv = document.createElement('div'); +// controlDiv.className = 'MapBox2-addMarker'; +// // Set CSS for the control border. +// const controlUI = document.createElement('div'); +// controlUI.style.backgroundColor = '#fff'; +// controlUI.style.borderRadius = '3px'; +// controlUI.style.cursor = 'pointer'; +// controlUI.style.marginTop = '10px'; +// controlUI.style.borderRadius = '4px'; +// controlUI.style.marginBottom = '22px'; +// controlUI.style.textAlign = 'center'; +// controlUI.style.position = 'absolute'; +// controlUI.style.width = '32px'; +// controlUI.style.height = '32px'; +// controlUI.title = 'Click to toggle marker mode. In marker mode, click on map to place a marker.'; + +// const plIcon = document.createElement('img'); +// plIcon.src = 'https://cdn4.iconfinder.com/data/icons/wirecons-free-vector-icons/32/add-256.png'; +// plIcon.style.color = 'rgb(25,25,25)'; +// plIcon.style.fontFamily = 'Roboto,Arial,sans-serif'; +// plIcon.style.fontSize = '16px'; +// plIcon.style.lineHeight = '32px'; +// plIcon.style.left = '18'; +// plIcon.style.top = '15'; +// plIcon.style.position = 'absolute'; +// plIcon.width = 14; +// plIcon.height = 14; +// plIcon.innerHTML = 'Add'; +// controlUI.appendChild(plIcon); + +// // Set CSS for the control interior. +// const markerIcon = document.createElement('img'); +// markerIcon.src = 'https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678111-map-marker-1024.png'; +// markerIcon.style.color = 'rgb(25,25,25)'; +// markerIcon.style.fontFamily = 'Roboto,Arial,sans-serif'; +// markerIcon.style.fontSize = '16px'; +// markerIcon.style.lineHeight = '32px'; +// markerIcon.style.left = '-2'; +// markerIcon.style.top = '1'; +// markerIcon.width = 30; +// markerIcon.height = 30; +// markerIcon.style.position = 'absolute'; +// markerIcon.innerHTML = 'Add'; +// controlUI.appendChild(markerIcon); + +// // Setup the click event listeners +// controlUI.addEventListener('click', () => { +// if (this.toggleAddMarker === true) { +// this.toggleAddMarker = false; +// console.log('add marker button status:' + this.toggleAddMarker); +// controlUI.style.backgroundColor = '#fff'; +// markerIcon.style.color = 'rgb(25,25,25)'; +// } else { +// this.toggleAddMarker = true; +// console.log('add marker button status:' + this.toggleAddMarker); +// controlUI.style.backgroundColor = '#4476f7'; +// markerIcon.style.color = 'rgb(255,255,255)'; +// } +// }); +// controlDiv.appendChild(controlUI); +// return controlDiv; +// }; + +// /** +// * Place the marker on google maps & store the empty marker as a MapMarker Document in allMarkers list +// * @param position - the LatLng position where the marker is placed +// * @param map +// */ +// @action +// private placeMarker = (position: google.maps.LatLng, map: google.maps.Map) => { +// const marker = new google.maps.Marker({ +// position: position, +// map: map, +// }); +// map.panTo(position); +// const mapMarker = Docs.Create.PushpinDocument(NumCast(position.lat()), NumCast(position.lng()), false, [], {}); +// this.addDocument(mapMarker, this.annotationKey); +// }; + +// _loadPending = true; +// /** +// * 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; +// this._loadPending = true; +// const centerControlDiv = this.CenterControl(); +// map.controls[google.maps.ControlPosition.TOP_RIGHT].push(centerControlDiv); +// //drawingManager.setMap(map); +// // if (navigator.geolocation) { +// // navigator.geolocation.getCurrentPosition( +// // (position: Position) => { +// // const pos = { +// // lat: position.coords.latitude, +// // lng: position.coords.longitude, +// // }; +// // this._map.setCenter(pos); +// // } +// // ); +// // } else { +// // alert("Your geolocation is not supported by browser.") +// // }; +// map.setZoom(NumCast(this.dataDoc.map_zoom, 2.5)); +// map.setCenter(new google.maps.LatLng(NumCast(this.dataDoc.mapLat), NumCast(this.dataDoc.mapLng))); +// setTimeout(() => { +// if (this._loadPending && this._map.getBounds()) { +// this._loadPending = false; +// this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); +// } +// }, 250); +// // listener to addmarker event +// this._map.addListener('click', (e: MouseEvent) => { +// if (this.toggleAddMarker === true) { +// this.placeMarker((e as any).latLng, map); +// } +// }); +// }; + +// @action +// centered = () => { +// if (this._loadPending && this._map.getBounds()) { +// this._loadPending = false; +// this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); +// } +// this.dataDoc.mapLat = this._map.getCenter()?.lat(); +// this.dataDoc.mapLng = this._map.getCenter()?.lng(); +// }; + +// @action +// zoomChanged = () => { +// if (this._loadPending && this._map.getBounds()) { +// this._loadPending = false; +// this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map); +// } +// this.dataDoc.map_zoom = this._map.getZoom(); +// }; + +// /** +// * 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; +// }; + +// /** +// * 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: google.maps.MapMouseEvent, place: Doc) => { +// // set which place was clicked +// this.selectedPlace = place; +// place.infoWindowOpen = true; +// }; + +// /** +// * 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 +// */ +// sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => { +// console.log('print all sidebar Docs'); +// if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); +// const docs = doc instanceof Doc ? [doc] : doc; +// docs.forEach(doc => { +// if (doc.lat !== undefined && doc.lng !== undefined) { +// const existingMarker = this.allMapMarkers.find(marker => marker.lat === doc.lat && marker.lng === doc.lng); +// if (existingMarker) { +// Doc.AddDocToList(existingMarker, 'data', doc); +// } else { +// const marker = Docs.Create.PushpinDocument(NumCast(doc.lat), NumCast(doc.lng), false, [doc], {}); +// this.addDocument(marker, this.annotationKey); +// } +// } +// }); //add to annotation list + +// 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._layout_showSidebar) this.toggleSidebar(); +// const docs = doc instanceof Doc ? [doc] : doc; +// return this.removeDocument(doc, sidebarKey); +// }; + +// /** +// * Toggle sidebar onclick the tiny comment button on the top right corner +// * @param e +// */ +// sidebarBtnDown = (e: React.PointerEvent) => { +// setupMoveUpEvents( +// this, +// e, +// (e, down, delta) => +// runInAction(() => { +// const localDelta = this.props +// .ScreenToLocalTransform() +// .scale(this.props.NativeDimScaling?.() || 1) +// .transformDirection(delta[0], delta[1]); +// const fullWidth = NumCast(this.layoutDoc._width); +// const mapWidth = fullWidth - this.sidebarWidth(); +// if (this.sidebarWidth() + localDelta[0] > 0) { +// this._showSidebar = true; +// this.layoutDoc._width = fullWidth + localDelta[0]; +// this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; +// } else { +// this._showSidebar = false; +// this.layoutDoc._width = mapWidth; +// this.layoutDoc._layout_sidebarWidthPercent = '0%'; +// } +// return false; +// }), +// emptyFunction, +// () => UndoManager.RunInBatch(this.toggleSidebar, 'toggle sidebar map') +// ); +// }; + +// sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth(); +// @computed get layout_sidebarWidthPercent() { +// return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); +// } +// @computed get sidebarColor() { +// return StrCast(this.layoutDoc.sidebar_color, 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 = () => { +// const place = this.searchBox.getPlace(); + +// if (!place.geometry || !place.geometry.location) { +// // user entered the name of a place that wasn't suggested & pressed the enter key, or place details request failed +// window.alert("No details available for input: '" + place.name + "'"); +// return; +// } + +// // zoom in on the location of the search result +// if (place.geometry.viewport) { +// this._map.fitBounds(place.geometry.viewport); +// } else { +// this._map.setCenter(place.geometry.location); +// this._map.setZoom(17); +// } + +// // customize icon => customized icon for the nature of the location selected +// const icon = { +// url: place.icon as string, +// size: new google.maps.Size(71, 71), +// origin: new google.maps.Point(0, 0), +// anchor: new google.maps.Point(17, 34), +// scaledSize: new google.maps.Size(25, 25), +// }; + +// // put temporary cutomized marker on searched location +// this.searchMarkers.forEach(marker => { +// marker.setMap(null); +// }); +// this.searchMarkers = []; +// this.searchMarkers.push( +// new window.google.maps.Marker({ +// map: this._map, +// icon, +// title: place.name, +// position: place.geometry.location, +// }) +// ); +// }; + +// /** +// * Handles toggle of sidebar on click the little comment button +// */ +// @computed get sidebarHandle() { +// return ( +// <div +// className="MapBox2-overlayButton-sidebar" +// key="sidebar" +// title="Toggle Sidebar" +// style={{ +// display: !this.props.isContentActive() ? 'none' : undefined, +// top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5, +// backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK, +// }} +// onPointerDown={this.sidebarBtnDown}> +// <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={'comment-alt'} size="sm" /> +// </div> +// ); +// } + +// // TODO: Adding highlight box layer to Maps +// @action +// toggleSidebar = () => { +// //1.2 * w * ? = .2 * w .2/1.2 +// const prevWidth = this.sidebarWidth(); +// this.layoutDoc._layout_showSidebar = (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? `${(100 * 0.2) / 1.2}%` : '0%') !== '0%'; +// this.layoutDoc._width = this.layoutDoc._layout_showSidebar ? NumCast(this.layoutDoc._width) * 1.2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth); +// }; + +// sidebarDown = (e: React.PointerEvent) => { +// setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), true); +// }; +// sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => { +// const bounds = this._ref.current!.getBoundingClientRect(); +// this.layoutDoc._layout_sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%'; +// this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%'; +// e.preventDefault(); +// return false; +// }; + +// setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func); + +// addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => { +// return this.addDocument(doc, annotationKey); +// }; + +// pointerEvents = () => { +// return this.props.isContentActive() === false ? 'none' : this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none'; +// }; +// @computed get annotationLayer() { +// return ( +// <div className="MapBox2-annotationLayer" style={{ height: Doc.NativeHeight(this.Document) || undefined }} ref={this._annotationLayer}> +// {this.inlineTextAnnotations +// .sort((a, b) => NumCast(a.y) - NumCast(b.y)) +// .map(anno => ( +// <Annotation key={`${anno[Id]}-annotation`} {...this.props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} showInfo={this.showInfo} dataDoc={this.dataDoc} anno={anno} /> +// ))} +// </div> +// ); +// } + +// getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => AnchorMenu.Instance?.GetAnchor(this._savedAnnotations, addAsAnnotation) ?? this.Document; + +// /** +// * render contents in allMapMarkers (e.g. images with exifData) into google maps as map marker +// * @returns +// */ +// private renderMarkers = () => { +// return this.allMapMarkers.map(place => ( +// <Marker key={place[Id]} position={{ lat: NumCast(place.lat), lng: NumCast(place.lng) }} onLoad={marker => this.markerLoadHandler(marker, place)} onClick={(e: google.maps.MapMouseEvent) => this.markerClickHandler(e, place)} /> +// )); +// }; + +// // 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()) { +// // console.log(SelectionManager.Views().lastElement()); +// // } +// }; + +// panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth(); +// panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); +// scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); +// transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; +// opaqueFilter = () => [...this.props.childFilters(), Utils.OpaqueBackgroundFilter]; +// infoWidth = () => this.props.PanelWidth() / 5; +// infoHeight = () => this.props.PanelHeight() / 5; +// anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; +// savedAnnotations = () => this._savedAnnotations; + +// get MicrosoftMaps() { +// return (window as any).Microsoft.Maps; +// } +// render() { +// const renderAnnotations = (childFilters?: () => string[]) => null; +// return ( +// <div className="MapBox2" ref={this._ref}> +// <div +// className="MapBox2-wrapper" +// onWheel={e => e.stopPropagation()} +// onPointerDown={async e => { +// e.button === 0 && !e.ctrlKey && e.stopPropagation(); +// }} +// style={{ width: `calc(100% - ${this.layout_sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}> +// <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div> +// {renderAnnotations(this.opaqueFilter)} +// {SnappingManager.GetIsDragging() ? null : renderAnnotations()} +// {this.annotationLayer} + +// <div> +// <GoogleMap mapContainerStyle={mapContainerStyle} onZoomChanged={this.zoomChanged} onCenterChanged={this.centered} onLoad={this.loadHandler} options={mapOptions}> +// <Autocomplete onLoad={this.setSearchBox} onPlaceChanged={this.handlePlaceChanged}> +// <input className="MapBox2-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]} +// {...this.props} +// setContentView={emptyFunction} +// 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> +// </div> +// {/* </LoadScript > */} +// <div className="MapBox2-sidebar" style={{ width: `${this.layout_sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}> +// <SidebarAnnos +// ref={this._sidebarRef} +// {...this.props} +// fieldKey={this.fieldKey} +// Document={this.Document} +// layoutDoc={this.layoutDoc} +// dataDoc={this.dataDoc} +// usePanelWidth={true} +// showSidebar={this.SidebarShown} +// nativeWidth={NumCast(this.layoutDoc._nativeWidth)} +// whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} +// PanelWidth={this.sidebarWidth} +// sidebarAddDocument={this.sidebarAddDocument} +// moveDocument={this.moveDocument} +// removeDocument={this.sidebarRemoveDocument} +// /> +// </div> +// {this.sidebarHandle} +// </div> +// ); +// } +// } |