aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-08-26 21:25:24 -0400
committerbobzel <zzzman@gmail.com>2023-08-26 21:25:24 -0400
commit0a813fdf7d73018ad5248d87fecbd9e55f3dc2d7 (patch)
tree71c1cf29075906d1423d0843749d5642809b8672
parentc973e8cbd4aabb545ea580b213e7f60d41cf2b20 (diff)
many fixes to map search bar, dragging pushpin, highlighting pushpins on link following
-rw-r--r--src/client/documents/Documents.ts8
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx552
-rw-r--r--src/client/views/nodes/MapBox/MapBox2.tsx4
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx16
4 files changed, 170 insertions, 410 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index af8cc07ed..d5d6fb2ba 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -158,6 +158,7 @@ export class DocumentOptions {
_dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units");
latitude?: NUMt = new NumInfo('latitude coordinate for map views');
longitude?: NUMt = new NumInfo('longitude coordinate for map views');
+ map?: STRt = new StrInfo('text location of map');
_timecodeToShow?: NUMt = new NumInfo('the time that a document should be displayed (e.g., when an annotation shows up as a video plays)');
_timecodeToHide?: NUMt = new NumInfo('the time that a document should be hidden');
_width?: NUMt = new NumInfo('displayed width of a document');
@@ -295,8 +296,9 @@ export class DocumentOptions {
config_latitude?: NUMt = new NumInfo('latitude of a map'); // latitude of a map
config_longitude?: NUMt = new NumInfo('longitude of map'); // longitude of map
- config_mapZoom?: NUMt = new NumInfo('zoom of map'); // zoom of map
- config_mapType?: string;
+ config_map_zoom?: NUMt = new NumInfo('zoom of map'); // zoom of map
+ config_map_type?: string;
+ config_map?: string;
config_panX?: NUMt = new NumInfo('panX saved as a view spec');
config_panY?: NUMt = new NumInfo('panY saved as a view spec');
config_viewScale?: NUMt = new NumInfo('viewScale saved as a view Spec');
@@ -527,7 +529,7 @@ export namespace Docs {
DocumentType.MAP,
{
layout: { view: MapBox, dataField: defaultDataKey },
- options: { _height: 600, _width: 800, nativeDimModifiable: true, systemIcon: 'BsFillPinMapFill' },
+ options: { map: '', _height: 600, _width: 800, nativeDimModifiable: true, systemIcon: 'BsFillPinMapFill' },
},
],
[
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 62d622fd6..94944b83d 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,19 +1,14 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { GoogleMapProps, Marker } from '@react-google-maps/api';
import BingMapsReact from 'bingmaps-react';
import { Button, EditableText, IconButton, Type } from 'browndash-components';
-import { docs_v1 } from 'googleapis';
import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { TbHeartMinus } from 'react-icons/tb';
import { Doc, DocListCast, Opt } from '../../../../fields/Doc';
import { Highlight, Width } from '../../../../fields/DocSymbols';
-import { Id } from '../../../../fields/FieldSymbols';
import { InkTool } from '../../../../fields/InkField';
-import { ScriptField } from '../../../../fields/ScriptField';
import { DocCast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnOne, returnTrue, setupMoveUpEvents, Utils } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
@@ -24,9 +19,8 @@ import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
import { MarqueeAnnotator } from '../../MarqueeAnnotator';
-import { Annotation } from '../../pdf/Annotation';
import { SidebarAnnos } from '../../SidebarAnnos';
-import { DocumentView, OpenWhere } from '../DocumentView';
+import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps } from '../FieldView';
import { PinProps, PresBox } from '../trails';
import { MapAnchorMenu } from './MapAnchorMenu';
@@ -45,29 +39,8 @@ import './MapBox.scss';
* 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 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 script = document.createElement('script');
-// script.defer = true;
-// script.async = true;
-// script.src = `https://maps.googleapis.com/maps/api/js?key=${bingApiKey}&libraries=places,drawing`;
-// document.head.appendChild(script);
-
/**
* Consider integrating later: allows for drawing, circling, making shapes on map
*/
@@ -85,169 +58,49 @@ const bingApiKey = process.env.BING_MAPS; // if you're running local, get a Bing
// });
@observer
-export class MapBox 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));
+export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(MapBox, fieldKey);
}
- public get SidebarKey() {
- return this.fieldKey + '_sidebar';
- }
+ private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
+ private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
+ private _sidebarRef = React.createRef<SidebarAnnos>();
+ private _ref: React.RefObject<HTMLDivElement> = React.createRef();
+ private _disposers: { [key: string]: IReactionDisposer } = {};
private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => 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 _marqueeing: number[] | undefined;
- @observable private inputRef = React.createRef<HTMLInputElement>();
- @observable private searchMarkers: google.maps.Marker[] = [];
- @observable private searchBox = undefined as any; // new window.google.maps.places.Autocomplete(this.inputRef.current!, options);
@observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
+ @computed get inlineTextAnnotations() {
+ return this.allMapMarkers.filter(a => a.text_inlineAnnotations);
+ }
@computed get allSidebarDocs() {
return DocListCast(this.dataDoc[this.SidebarKey]);
}
@computed get allMapMarkers() {
return DocListCast(this.dataDoc[this.annotationKey]);
}
- @observable private toggleAddMarker = false;
- private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
-
@computed get SidebarShown() {
return this.layoutDoc._layout_showSidebar ? true : false;
}
+ @computed get 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'));
+ }
+ @computed get SidebarKey() {
+ return this.fieldKey + '_sidebar';
+ }
- static _canAnnotate = true;
- static _hadSelection: boolean = false;
- private _sidebarRef = React.createRef<SidebarAnnos>();
- private _ref: React.RefObject<HTMLDivElement> = React.createRef();
- private _disposer: { [key: string]: IReactionDisposer } = {};
componentDidMount() {
this.props.setContentView?.(this);
}
componentWillUnmount(): void {
this.deselectPin();
- Object.keys(this._disposer).forEach(key => this._disposer[key]?.());
+ Object.keys(this._disposers).forEach(key => this._disposers[key]?.());
}
- // 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()));
- };
-
- /**
- * 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;
- };
-
- /**
- * 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;
-
- @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.mapZoom = this._map.getZoom();
- };
-
- /**
- * 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,
- })
- );
- };
/**
* Called when dragging documents into map sidebar or directly into infowindow; to create a map marker, ref to MapMarkerDocument in Documents.ts
@@ -256,7 +109,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
* @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 => {
@@ -280,11 +132,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
* @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);
- };
+ sidebarRemoveDocument = (doc: Doc | Doc[], sidebarKey?: string) => this.removeDocument(doc, sidebarKey);
/**
* Toggle sidebar onclick the tiny comment button on the top right corner
@@ -317,14 +165,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
() => 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'));
- }
+ sidebarWidth = () => (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth();
/**
* Handles toggle of sidebar on click the little comment button
@@ -349,27 +190,27 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// 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);
};
createNoteAnnotation = () => {
- !this.layoutDoc.layout_showSidebar && this.toggleSidebar();
-
- setTimeout(
- undoable(
- action(() => {
- const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(false));
- if (note && this.selectedPin) {
- note.latitude = this.selectedPin.latitude;
- note.longitude = this.selectedPin.latitude;
- }
- }),
- 'create note annotation'
- )
+ const createFunc = undoable(
+ action(() => {
+ const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(false));
+ if (note && this.selectedPin) {
+ note.latitude = this.selectedPin.latitude;
+ note.longitude = this.selectedPin.longitude;
+ note.map = this.selectedPin.map;
+ }
+ }),
+ 'create note annotation'
);
+ if (!this.layoutDoc.layout_showSidebar) {
+ this.toggleSidebar();
+ setTimeout(createFunc);
+ } else createFunc();
};
sidebarDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), true);
@@ -406,37 +247,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
x !== undefined && y !== undefined && this._setPreviewCursor?.(x, y, false, false);
};
- addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => {
- return this.addDocument(doc, annotationKey);
- };
+ addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => this.addDocument(doc, annotationKey);
pointerEvents = () => (this.props.isContentActive() && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : 'none');
- @computed get annotationLayer() {
- return (
- <div className="mapBox-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>
- );
- }
-
- // Old get anchor function
- // getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => AnchorMenu.Instance?.GetAnchor(this._savedAnnotations, addAsAnnotation) ?? this.rootDoc;
-
- /**
- * 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)} />
- ));
- };
-
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));
@@ -473,25 +287,15 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
} else {
this._bingSearchManager.geocode({
where: query,
- callback: action((r: any) => {
- res(r.results[0].location);
- }),
+ callback: action((r: any) => res(r.results[0].location)),
errorCallback: (e: any) => reject(),
});
}
});
};
- /**
- *
- *
- * ERIC'S BING MAP CODE BELOW
- *
- *
- *
- **/
@observable
- bingSearchBarContents: any = 'enter city/zip/...'; // For Bing Maps: The contents of the Bing search bar (string)
+ bingSearchBarContents: any = this.rootDoc.map; // For Bing Maps: The contents of the Bing search bar (string)
geoDataRequestOptions = {
entityType: 'PopulatedPlace',
@@ -502,14 +306,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
* Creates Pushpin doc and adds it to the list of annotations
*/
@action
- createPushpin = undoable((latitude: number, longitude: number) => {
+ createPushpin = undoable((latitude: number, longitude: number, map?: string) => {
// Stores the pushpin as a MapMarkerDocument
const mapMarker = Docs.Create.PushpinDocument(
NumCast(latitude),
NumCast(longitude),
false,
[],
- {}
+ { map: map }
// ,'pushpinIDamongus'+ this.incrementer++
);
this.addDocument(mapMarker, this.annotationKey);
@@ -517,18 +321,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// mapMarker.infoWindowOpen = true;
}, 'createpin');
- /*
- * Pushpin dblclick
- */
- // @action
- // pushpinDblClicked = (pin: any, pinDoc?: Doc) => {
- // if (pinDoc) this.removePushpin(pinDoc);
- // else this._bingMap.current.entities.remove(pin);
- // };
-
// The pin that is selected
- @observable
- selectedPin: Doc | undefined;
+ @observable selectedPin: Doc | undefined;
@action
deselectPin = () => {
@@ -544,6 +338,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._bingMap.current.entities.push(newpin);
this.map_docToPinMap.set(temp, newpin);
this.selectedPin = undefined;
+ this.bingSearchBarContents = this.rootDoc.map;
}
};
@@ -558,9 +353,10 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
pushpinClicked = (pinDoc: Doc) => {
this.deselectPin();
this.selectedPin = pinDoc;
+ this.bingSearchBarContents = pinDoc.map;
Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match');
- Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.latitude, 'match');
+ Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match');
this.recolorPin(this.selectedPin, 'green');
@@ -575,7 +371,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
MapAnchorMenu.Instance.jumpTo(cpt[0], cpt[1], true);
document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
- // Filter sidebar:
};
/**
@@ -589,54 +384,47 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
* Map OnClick
*/
@action
- mapOnClick = (e: { location: { latitude: any; longitude: any } }) => this.deselectPin();
+ mapOnClick = (e: { location: { latitude: any; longitude: any } }) => {
+ this.props.select(false);
+ this.deselectPin();
+ };
/*
* Updates values of layout doc to match the current map
*/
@action
- updateLayout = () => {
- this.dataDoc.latitude = this._bingMap.current.getCenter().latitude;
- this.dataDoc.longitude = this._bingMap.current.getCenter().longitude;
- this.dataDoc.mapZoom = this._bingMap.current.getZoom();
- // if(this.dataDoc.mapType == 'x'){
- // this.dataDoc.locationToLookAt
- // }
- // this.dataDoc.mapType = new this.MicrosoftMaps.MapTypeId();
+ mapRecentered = () => {
+ if (
+ Math.abs(NumCast(this.dataDoc.latitude) - this._bingMap.current.getCenter().latitude) > 1e-7 || //
+ Math.abs(NumCast(this.dataDoc.longitude) - this._bingMap.current.getCenter().longitude) > 1e-7
+ ) {
+ this.dataDoc.latitude = this._bingMap.current.getCenter().latitude;
+ this.dataDoc.longitude = this._bingMap.current.getCenter().longitude;
+ this.dataDoc.map = '';
+ this.bingSearchBarContents = '';
+ }
+ this.dataDoc.map_zoom = this._bingMap.current.getZoom();
};
/*
* Updates maptype
*/
@action
- updateMapType = () => {
- this.dataDoc.mapType = this._bingMap.current.getMapTypeId();
- };
+ updateMapType = () => (this.dataDoc.map_type = this._bingMap.current.getMapTypeId());
- searched_pin: any;
/*
* For Bing Maps
* Called by search button's onClick
* Finds the geocode of the searched contents and sets location to that location
**/
@action
- bingSearch = async () => {
- const location = await this.bingGeocode(this._bingMap, this.bingSearchBarContents);
- this.dataDoc.latitude = location.latitude;
- this.dataDoc.longitude = location.longitude;
- this.dataDoc.mapZoom = this._bingMap.current.getZoom();
- // Creates a temporary pin but does not add it to the dataDoc
- this.createPushpin(this.dataDoc.latitude, this.dataDoc.longitude);
+ bingSearch = () => {
+ return this.bingGeocode(this._bingMap, this.bingSearchBarContents).then(location => {
+ this.dataDoc.latitude = location.latitude;
+ this.dataDoc.longitude = location.longitude;
+ this.dataDoc.map_zoom = this._bingMap.current.getZoom();
+ this.dataDoc.map = this.bingSearchBarContents;
+ });
};
- /**
- * Adds all pushpins in dataDoc onto the map (render) - OLD & UNUSED
- */
- // @action
- // addAllPins = () => {
- // this._bingMap.current.entities.clear();
- // if (this.searched_pin) this._bingMap.current.entities.push(this.searched_pin);
- // // this.allMapPushpins.map(pin => this.addPushpin(pin));
- // };
-
/*
* Returns doc w/ relevant info
*/
@@ -644,12 +432,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
/// this should use SELECTED pushpin for lat/long if there is a selection, otherwise CENTER
const anchor = Docs.Create.MapanchorDocument({
title: 'MapAnchor:' + this.rootDoc.title,
+ text: StrCast(this.selectedPin?.map) || StrCast(this.rootDoc.map) || 'map location',
config_latitude: NumCast(this.selectedPin?.latitude ?? this.dataDoc.latitude),
config_longitude: NumCast(this.selectedPin?.longitude ?? this.dataDoc.longitude),
- config_mapZoom: NumCast(this.dataDoc.mapZoom),
- config_mapType: StrCast(this.dataDoc.mapType),
- // preslocationToLookAt:this.dataDoc.locationToLookAt,
- // presType:
+ config_map_zoom: NumCast(this.dataDoc.map_zoom),
+ config_map_type: StrCast(this.dataDoc.map_type),
+ config_map: StrCast(this.selectedPin?.map) || StrCast(this.dataDoc.map),
layout_unrendered: true,
});
if (anchor) {
@@ -684,23 +472,13 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.map_docToPinMap.set(pin, pushPin);
};
- @observable
- pinIsSelected_TEMPORARY: boolean = false; // toggles if remove pin button appears
-
/*
* Input: pin doc
* Removes pin from annotations
*/
@action
- removePushpin = (pinDoc: Doc) => {
- // this.allMapPushpins
- // this.allMapPushpins.map(pin => this.addPushpin(pin));
- // this._bingMap.current.entities.clear();
+ removePushpin = (pinDoc: Doc) => this.removeDocument(pinDoc, this.annotationKey);
- this.removeDocument(pinDoc, this.annotationKey);
-
- // this.dataDoc[this.annotationKey]
- };
/*
* Removes pushpin from map render
*/
@@ -725,11 +503,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
tryHideMapAnchorMenu = (e: PointerEvent) => {
let target = document.elementFromPoint(e.x, e.y);
-
- while (target != null) {
- if (target === MapAnchorMenu.top.current) {
- return;
- }
+ while (target) {
+ if (target === MapAnchorMenu.top.current) return;
target = target.parentElement;
}
e.stopPropagation();
@@ -738,13 +513,13 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
};
- // tryhidemenu = e => if( e.parent... == mapanchormenu.top.currrent) do nothing; else hide menu
-
@action
centerOnSelectedPin = () => {
if (this.selectedPin) {
this.dataDoc.latitude = this.selectedPin.latitude;
this.dataDoc.longitude = this.selectedPin.longitude;
+ this.dataDoc.map = this.selectedPin.map ?? '';
+ this.bingSearchBarContents = this.selectedPin.map;
}
MapAnchorMenu.Instance.fadeOut(true);
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu);
@@ -777,33 +552,13 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
},
};
- /**
- * Toggles mode for placing a pin down on map
- */
- @observable
- placePinOn = false;
- @action
- togglePlacePin = () => {
- if (this.placePinOn) this.placePinOn = false;
- else this.placePinOn = true;
- };
-
@action
- searchbarOnEdit = (newText: string) => {
- this.bingSearchBarContents = newText;
- };
+ searchbarOnEdit = (newText: string) => (this.bingSearchBarContents = newText);
recolorPin = (pin: Doc, color?: string) => {
this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin));
this.map_docToPinMap.delete(pin);
- const newpin = new this.MicrosoftMaps.Pushpin(
- new this.MicrosoftMaps.Location(pin.latitude, pin.longitude),
- color
- ? {
- color,
- }
- : {}
- );
+ const newpin = new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(pin.latitude, pin.longitude), color ? { color } : {});
this.MicrosoftMaps.Events.addHandler(newpin, 'click', (e: any) => this.pushpinClicked(pin));
this._bingMap.current.entities.push(newpin);
this.map_docToPinMap.set(pin, newpin);
@@ -822,29 +577,36 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
alert('NO Map!?');
}
this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'click', this.mapOnClick);
- this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'viewchangeend', undoable(this.updateLayout, 'Map Layout Change'));
+ this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'viewchangeend', undoable(this.mapRecentered, 'Map Layout Change'));
this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'maptypechanged', undoable(this.updateMapType, 'Map ViewType Change'));
- this.updateLayout();
- this._disposer.highlight = reaction(
+
+ this._disposers.mapLocation = reaction(
+ () => this.rootDoc.map,
+ mapLoc => (this.bingSearchBarContents = mapLoc),
+ { fireImmediately: true }
+ );
+ this._disposers.highlight = reaction(
() => this.allMapPushpins.map(doc => doc[Highlight]),
- () =>
- this.allMapPushpins
- .map(doc => ({ doc, pushpin: DocCast(doc.mapPin) }))
- .filter(pair => pair.pushpin)
- .forEach(({ doc, pushpin }) => {
- if (doc[Highlight] && !this.map_pinHighlighted.get(pushpin)) {
- this.recolorPin(pushpin, 'orange');
- this.map_pinHighlighted.set(pushpin, true);
- } else if (!pushpin[Highlight] && this.map_pinHighlighted.get(pushpin)) {
- this.recolorPin(pushpin);
- this.map_pinHighlighted.delete(pushpin);
- }
- }),
+ () => {
+ const allPins = this.allMapPushpins.map(doc => ({ doc, pushpin: DocCast(doc.mapPin) })).filter(pair => pair.pushpin);
+ allPins.forEach(({ doc, pushpin }) => {
+ if (!pushpin[Highlight] && this.map_pinHighlighted.get(pushpin)) {
+ this.recolorPin(pushpin);
+ this.map_pinHighlighted.delete(pushpin);
+ }
+ });
+ allPins.forEach(({ doc, pushpin }) => {
+ if (doc[Highlight] && !this.map_pinHighlighted.get(pushpin)) {
+ this.recolorPin(pushpin, 'orange');
+ this.map_pinHighlighted.set(pushpin, true);
+ }
+ });
+ },
{ fireImmediately: true }
);
- // this.updateMapType();
- this._disposer.location = reaction(
- () => ({ lat: this.rootDoc.latitude, lng: this.rootDoc.longitude, zoom: this.rootDoc.mapZoom, mapType: this.rootDoc.mapType }),
+
+ this._disposers.location = reaction(
+ () => ({ lat: this.rootDoc.latitude, lng: this.rootDoc.longitude, zoom: this.rootDoc.map_zoom, mapType: this.rootDoc.map_type }),
locationObject => {
// if (this._bingMap.current)
try {
@@ -862,43 +624,50 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
);
};
- // Keeps track of when dragging a pin onto map
- draggingPin = false;
dragToggle = (e: React.PointerEvent) => {
- // console.log('DRAGGING TOGGLE');
- document.addEventListener('drop', this.dropPin, true);
- document.addEventListener('pointermove', this.pinMove, true);
- e.stopPropagation();
- };
- pinMove = (e: PointerEvent) => {
- // console.log('MOVING');
- e.stopPropagation();
- };
- dropPin = (e: DragEvent) => {
- e.stopPropagation();
- e.preventDefault();
- document.removeEventListener('drop', this.dropPin, true);
- document.removeEventListener('pointermove', this.pinMove, true);
- let target = document.elementFromPoint(e.x, e.y);
+ let dragClone: HTMLDivElement | undefined;
- while (target != null) {
- if (target === this._ref.current) {
- const cpt = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
- const x = cpt[0] - (this.props.PanelWidth() - this.sidebarWidth()) / 2;
- const y = cpt[1] - 32 /* height of search bar */ - this.props.PanelHeight() / 2;
- const location = this._bingMap.current.tryPixelToLocation(new this.MicrosoftMaps.Point(x, y));
- this.createPushpin(location.latitude, location.longitude);
- break;
+ setupMoveUpEvents(
+ e,
+ e,
+ e => {
+ if (!dragClone) {
+ dragClone = this._dragRef.current?.cloneNode(true) as HTMLDivElement;
+ dragClone.style.position = 'absolute';
+ dragClone.style.zIndex = '10000';
+ DragManager.Root().appendChild(dragClone);
+ }
+ dragClone.style.transform = `translate(${e.clientX - 15}px, ${e.clientY - 15}px)`;
+ return false;
+ },
+ e => {
+ if (!dragClone) return;
+ DragManager.Root().removeChild(dragClone);
+ let target = document.elementFromPoint(e.x, e.y);
+ while (target) {
+ if (target === this._ref.current) {
+ const cpt = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+ const x = cpt[0] - (this.props.PanelWidth() - this.sidebarWidth()) / 2;
+ const y = cpt[1] - 32 /* height of search bar */ - this.props.PanelHeight() / 2;
+ const location = this._bingMap.current.tryPixelToLocation(new this.MicrosoftMaps.Point(x, y));
+ this.createPushpin(location.latitude, location.longitude);
+ break;
+ }
+ target = target.parentElement;
+ }
+ },
+ e => {
+ const createPin = () => this.createPushpin(this.rootDoc.latitude, this.rootDoc.longitude, this.rootDoc.map);
+ if (this.bingSearchBarContents) {
+ this.bingSearch().then(createPin);
+ } else createPin();
}
- target = target.parentElement;
- }
+ );
};
- searchbarKeyDown = (e: any) => {
- if (e.key === 'Enter') {
- this.bingSearch();
- }
- };
+ searchbarKeyDown = (e: any) => e.key === 'Enter' && this.bingSearch();
+
+ _dragRef = React.createRef<HTMLDivElement>();
render() {
const renderAnnotations = (childFilters?: () => string[]) => null;
return (
@@ -908,26 +677,18 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
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.layout_sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
+ style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
<div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
{renderAnnotations(this.opaqueFilter)}
{SnappingManager.GetIsDragging() ? null : renderAnnotations()}
- {this.annotationLayer}
<div className="mapBox-searchbar">
<EditableText
// editing
setVal={(newText: string | number) => typeof newText === 'string' && this.searchbarOnEdit(newText)}
onEnter={e => this.bingSearch()}
- placeholder={this.bingSearchBarContents}
+ placeholder={this.bingSearchBarContents || 'enter city/zip/...'}
textAlign="center"
/>
<IconButton
@@ -939,41 +700,34 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
</svg>
}
onClick={this.bingSearch}
- onDoubleClick={function noRefCheck() {}}
- onPointerDown={function noRefCheck() {}}
- onPointerDownCapture={function noRefCheck() {}}
- onPointerMove={function noRefCheck() {}}
- onPointerMoveCapture={function noRefCheck() {}}
- onPointerUp={function noRefCheck() {}}
type={Type.TERT}
/>
- <div draggable={true} style={{ width: 30, height: 30 }} onPointerDown={this.dragToggle}>
+ <div style={{ width: 30, height: 30 }} ref={this._dragRef} onPointerDown={this.dragToggle}>
<Button tooltip="drag to place a pushpin" icon={<FontAwesomeIcon size={'lg'} icon={'bullseye'} />} />
</div>
</div>
<BingMapsReact
- onMapReady={this.bingMapReady}
+ onMapReady={this.bingMapReady} //
bingMapsKey={bingApiKey}
height="100%"
mapOptions={this.bingMapOptions}
width="100%"
viewOptions={this.bingViewOptions}
- onPointerUp
- {...() => (this.draggingPin = false)}></BingMapsReact>
+ />
<div>
{!this._mapReady
? null
: this.allMapPushpins.map(pushpin => (
<DocumentView
{...this.props}
+ renderDepth={this.props.renderDepth + 1}
Document={pushpin}
DataDoc={undefined}
PanelWidth={returnOne}
PanelHeight={returnOne}
NativeWidth={returnOne}
NativeHeight={returnOne}
- onClick={() => new ScriptField(undefined)}
onKey={undefined}
onDoubleClick={undefined}
onBrowseClick={undefined}
@@ -983,7 +737,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
isDocumentActive={returnFalse}
isContentActive={returnFalse}
addDocTab={returnFalse}
- ScreenToLocalTransform={() => new Transform(0, 0, 0)}
+ ScreenToLocalTransform={Transform.Identity}
fitContentsToBox={undefined}
focus={returnOne}
/>
@@ -1019,7 +773,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
)}
</div>
{/* </LoadScript > */}
- <div className="mapBox-sidebar" style={{ width: `${this.layout_sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
+ <div className="mapBox-sidebar" style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
<SidebarAnnos
ref={this._sidebarRef}
{...this.props}
diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx
index f42dec12c..a54bdcd5e 100644
--- a/src/client/views/nodes/MapBox/MapBox2.tsx
+++ b/src/client/views/nodes/MapBox/MapBox2.tsx
@@ -260,7 +260,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// } else {
// alert("Your geolocation is not supported by browser.")
// };
- map.setZoom(NumCast(this.dataDoc.mapZoom, 2.5));
+ 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()) {
@@ -292,7 +292,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this._loadPending = false;
this.layoutDoc.freeform_fitContentsToBox && this.fitBounds(this._map);
}
- this.dataDoc.mapZoom = this._map.getZoom();
+ this.dataDoc.map_zoom = this._map.getZoom();
};
/**
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index afd9bccab..6ff22e929 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -471,12 +471,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
Doc.SetInPlace(bestTarget, 'longitude', NumCast(activeItem.config_longitude), true);
changed = true;
}
- if (bestTarget.zoom !== activeItem.config_mapZoom) {
- Doc.SetInPlace(bestTarget, 'mapZoom', NumCast(activeItem.config_mapZoom), true);
+ if (bestTarget.zoom !== activeItem.config_map_zoom) {
+ Doc.SetInPlace(bestTarget, 'map_zoom', NumCast(activeItem.config_map_zoom), true);
changed = true;
}
- if (bestTarget.mapType !== activeItem.config_mapType) {
- Doc.SetInPlace(bestTarget, 'mapType', StrCast(activeItem.config_mapType), true);
+ if (bestTarget.map_type !== activeItem.config_map_type) {
+ Doc.SetInPlace(bestTarget, 'map_type', StrCast(activeItem.config_map_type), true);
+ changed = true;
+ }
+ if (bestTarget.map !== activeItem.config_map) {
+ Doc.SetInPlace(bestTarget, 'map', StrCast(activeItem.config_map), true);
changed = true;
}
}
@@ -663,8 +667,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (pinProps.pinData.map) {
// pinDoc.config_latitude = targetDoc?.latitude;
// pinDoc.config_longitude = targetDoc?.longitude;
- pinDoc.config_mapZoom = targetDoc?.mapZoom;
- pinDoc.config_mapType = targetDoc?.mapType;
+ pinDoc.config_map_zoom = targetDoc?.map_zoom;
+ pinDoc.config_map_type = targetDoc?.map_type;
//...
}
if (pinProps.pinData.poslayoutview)