aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/MapBox/MapBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/MapBox/MapBox.tsx')
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx505
1 files changed, 263 insertions, 242 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 0b7264d79..18a6b5453 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,8 +1,8 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api';
import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx';
-import { observer } from "mobx-react";
-import * as React from "react";
+import { observer } from 'mobx-react';
+import * as React from 'react';
import { Doc, DocListCast, Opt, WidthSym } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { InkTool } from '../../../../fields/InkField';
@@ -22,17 +22,17 @@ import { Annotation } from '../../pdf/Annotation';
import { SidebarAnnos } from '../../SidebarAnnos';
import { StyleProp } from '../../StyleProvider';
import { FieldView, FieldViewProps } from '../FieldView';
-import "./MapBox.scss";
+import './MapBox.scss';
import { MapBoxInfoWindow } from './MapBoxInfoWindow';
/**
* MapBox architecture:
* Main component: MapBox.tsx
* Supporting Components: SidebarAnnos, CollectionStackingView
- *
- * MapBox is a node that extends the ViewBoxAnnotatableComponent. Similar to PDFBox and WebBox, it supports interaction between sidebar content and document content.
- * The main body of MapBox uses Google Maps API to allow location retrieval, adding map markers, pan and zoom, and open street view.
- * Dash Document architecture is integrated with Maps API: When drag and dropping documents with ExifData (gps Latitude and Longitude information) available,
+ *
+ * MapBox is a node that extends the ViewBoxAnnotatableComponent. Similar to PDFBox and WebBox, it supports interaction between sidebar content and document content.
+ * The main body of MapBox uses Google Maps API to allow location retrieval, adding map markers, pan and zoom, and open street view.
+ * Dash Document architecture is integrated with Maps API: When drag and dropping documents with ExifData (gps Latitude and Longitude information) available,
* sidebarAddDocument function checks if the document contains lat & lng information, if it does, then the document is added to both the sidebar and the infowindow (a pop up corresponding to a map marker--pin on map).
* The lat and lng field of the document is filled when importing (spec see ConvertDMSToDD method and processFileUpload method in Documents.ts).
* A map marker is considered a document that contains a collection with stacking view of documents, it has a lat, lng location, which is passed to Maps API's custom marker (red pin) to be rendered on the google maps
@@ -77,26 +77,30 @@ document.head.appendChild(script);
// },
// });
-
// 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
+ 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
+ types: ['establishment'], // type pf places, subject of change according to user need
} as google.maps.places.AutocompleteOptions;
@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);
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapBox, fieldKey); }
- public get SidebarKey() { return this.fieldKey + "-sidebar"; }
+ showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno));
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(MapBox, fieldKey);
+ }
+ public get SidebarKey() {
+ return this.fieldKey + '-sidebar';
+ }
private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
- @computed get inlineTextAnnotations() { return this.allMapMarkers.filter(a => a.textInlineAnnotations); }
+ @computed get inlineTextAnnotations() {
+ return this.allMapMarkers.filter(a => a.textInlineAnnotations);
+ }
@observable private _map: google.maps.Map = null as unknown as google.maps.Map;
@observable private selectedPlace: Doc | undefined;
@@ -108,14 +112,19 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@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]); }
+ @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();
-
@observable _showSidebar = false;
- @computed get SidebarShown() { return this._showSidebar || this.layoutDoc._showSidebar ? true : false; }
+ @computed get SidebarShown() {
+ return this._showSidebar || this.layoutDoc._showSidebar ? true : false;
+ }
static _canAnnotate = true;
static _hadSelection: boolean = false;
@@ -129,109 +138,106 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@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()));
- }
+ 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
+ * @param controlDiv
+ * @param map
*/
private CenterControl = () => {
- const controlDiv = document.createElement("div");
- controlDiv.className = "mapBox-addMarker";
+ const controlDiv = document.createElement('div');
+ controlDiv.className = 'mapBox-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";
+ 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";
+ 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";
+ 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";
+ markerIcon.style.position = 'absolute';
+ markerIcon.innerHTML = 'Add';
controlUI.appendChild(markerIcon);
// Setup the click event listeners
- controlUI.addEventListener("click", () => {
+ 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)";
+ 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)";
+ 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
+ * @param map
*/
@action
private placeMarker = (position: google.maps.LatLng, map: google.maps.Map) => {
const marker = new google.maps.Marker({
position: position,
- map: map
+ map: map,
});
map.panTo(position);
const mapMarker = Docs.Create.MapMarkerDocument(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
+ * fit map bounds to contain all markers
+ * @param map
*/
@action
private loadHandler = (map: google.maps.Map) => {
@@ -256,7 +262,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
map.setZoom(NumCast(this.dataDoc.mapZoom, 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.fitContentsToBox && this.fitBounds(this._map);
@@ -268,7 +273,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.placeMarker((e as any).latLng, map);
}
});
- }
+ };
@action
centered = () => {
@@ -278,7 +283,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
this.dataDoc.mapLat = this._map.getCenter()?.lat();
this.dataDoc.mapLng = this._map.getCenter()?.lng();
- }
+ };
@action
zoomChanged = () => {
@@ -287,64 +292,64 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.layoutDoc.fitContentsToBox && this.fitBounds(this._map);
}
this.dataDoc.mapZoom = this._map.getZoom();
- }
+ };
/**
* Load and render all map markers
- * @param marker
- * @param place
+ * @param marker
+ * @param place
*/
@action
private markerLoadHandler = (marker: google.maps.Marker, place: Doc) => {
- place[Id] ? this.markerMap[place[Id]] = marker : null;
- }
+ 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
+ * @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
+ * @param doc
+ * @param sidebarKey
+ * @returns
*/
sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
- console.log("print all sidebar Docs");
+ console.log('print all sidebar Docs');
console.log(this.allSidebarDocs);
if (!this.layoutDoc._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);
- doc.onClickBehavior = "enterPortal";
+ doc.onClickBehavior = 'enterPortal';
if (existingMarker) {
- Doc.AddDocToList(existingMarker, "data", doc);
+ Doc.AddDocToList(existingMarker, 'data', doc);
} else {
const marker = Docs.Create.MapMarkerDocument(NumCast(doc.lat), NumCast(doc.lng), false, [doc], {});
this.addDocument(marker, this.annotationKey);
}
}
}); //add to annotation list
- console.log("sidebaraddDocument");
+ console.log('sidebaraddDocument');
console.log(doc);
return this.addDocument(doc, sidebarKey); // add to sidebar list
- }
+ };
/**
* Removing documents from the sidebar
- * @param doc
- * @param sidebarKey
- * @returns
+ * @param doc
+ * @param sidebarKey
+ * @returns
*/
sidebarRemoveDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
if (this.layoutDoc._showSidebar) this.toggleSidebar();
@@ -354,31 +359,43 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
console.log(this.allSidebarDocs);
});
return this.removeDocument(doc, sidebarKey);
- }
+ };
/**
* Toggle sidebar onclick the tiny comment button on the top right corner
- * @param e
+ * @param e
*/
sidebarBtnDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, (e, down, delta) => {
- const localDelta = this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1).transformDirection(delta[0], delta[1]);
- const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]);
- const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
- const ratio = (curNativeWidth + localDelta[0] / (this.props.scaling?.() || 1)) / nativeWidth;
- if (ratio >= 1) {
- this.layoutDoc.nativeWidth = nativeWidth * ratio;
- this.layoutDoc._width = this.layoutDoc[WidthSym]() + localDelta[0];
- this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
- }
- return false;
- }, emptyFunction, this.toggleSidebar);
- }
-
- sidebarWidth = () => Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth();
- @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); }
- @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); }
+ setupMoveUpEvents(
+ this,
+ e,
+ (e, down, delta) => {
+ const localDelta = this.props
+ .ScreenToLocalTransform()
+ .scale(this.props.scaling?.() || 1)
+ .transformDirection(delta[0], delta[1]);
+ const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth']);
+ const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
+ const ratio = (curNativeWidth + localDelta[0] / (this.props.scaling?.() || 1)) / nativeWidth;
+ if (ratio >= 1) {
+ this.layoutDoc.nativeWidth = nativeWidth * ratio;
+ this.layoutDoc._width = this.layoutDoc[WidthSym]() + localDelta[0];
+ this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
+ }
+ return false;
+ },
+ emptyFunction,
+ this.toggleSidebar
+ );
+ };
+ sidebarWidth = () => (Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth();
+ @computed get sidebarWidthPercent() {
+ return StrCast(this.layoutDoc._sidebarWidthPercent, '0%');
+ }
+ @computed get sidebarColor() {
+ return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + '-backgroundColor'], '#e4e4e4'));
+ }
/**
* function that reads the place inputed from searchbox, then zoom in on the location that's been autocompleted;
@@ -414,7 +431,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
};
// put temporary cutomized marker on searched location
- this.searchMarkers.forEach((marker) => {
+ this.searchMarkers.forEach(marker => {
marker.setMap(null);
});
this.searchMarkers = [];
@@ -426,7 +443,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
position: place.geometry.location,
})
);
- }
+ };
/**
* Handles toggle of sidebar on click the little comment button
@@ -435,95 +452,99 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
TraceMobx();
const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
const color = !annotated ? Colors.WHITE : Colors.BLACK;
- const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props as any, StyleProp.WidgetColor + (annotated ? ":annotated" : ""));
- return (!annotated) ? (null) :
- <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
+ const backgroundColor = !annotated ? (this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK) : this.props.styleProvider?.(this.rootDoc, this.props as any, StyleProp.WidgetColor + (annotated ? ':annotated' : ''));
+ return !annotated ? null : (
+ <div
+ className="formattedTextBox-sidebar-handle"
+ onPointerDown={this.sidebarDown}
style={{
left: `max(0px, calc(100% - ${this.sidebarWidthPercent} - 17px))`,
backgroundColor: backgroundColor,
color: color,
- opacity: annotated ? 1 : undefined
- }} >
- <FontAwesomeIcon icon={"comment-alt"} />
- </div>;
+ opacity: annotated ? 1 : undefined,
+ }}>
+ <FontAwesomeIcon icon={'comment-alt'} />
+ </div>
+ );
}
// TODO: Adding highlight box layer to Maps
@action
toggleSidebar = () => {
const prevWidth = this.sidebarWidth();
- this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "50%" : "0%")) !== "0%";
+ this.layoutDoc._showSidebar = (this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, '0%') === '0%' ? '50%' : '0%') !== '0%';
this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth);
- }
+ };
sidebarDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), false);
- }
+ };
sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => {
const bounds = this._ref.current!.getBoundingClientRect();
- this.layoutDoc._sidebarWidthPercent = "" + 100 * Math.max(0, (1 - (e.clientX - bounds.left) / bounds.width)) + "%";
- this.layoutDoc._showSidebar = this.layoutDoc._sidebarWidthPercent !== "0%";
+ this.layoutDoc._sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%';
+ this.layoutDoc._showSidebar = this.layoutDoc._sidebarWidthPercent !== '0%';
e.preventDefault();
return false;
- }
+ };
- setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => this._setPreviewCursor = func;
+ setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func);
@action
onMarqueeDown = (e: React.PointerEvent) => {
if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.ActiveTool)) {
- setupMoveUpEvents(this, e, action(e => {
- MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- this._marqueeing = [e.clientX, e.clientY];
- return true;
- }), returnFalse, () => MarqueeAnnotator.clearAnnotations(this._savedAnnotations), false);
+ setupMoveUpEvents(
+ this,
+ e,
+ action(e => {
+ MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
+ this._marqueeing = [e.clientX, e.clientY];
+ return true;
+ }),
+ returnFalse,
+ () => MarqueeAnnotator.clearAnnotations(this._savedAnnotations),
+ false
+ );
}
- }
+ };
@action finishMarquee = (x?: number, y?: number) => {
this._marqueeing = undefined;
this._isAnnotating = false;
x !== undefined && y !== undefined && this._setPreviewCursor?.(x, y, false, false);
- }
+ };
addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => {
return this.addDocument(doc, annotationKey);
- }
+ };
pointerEvents = () => {
- return this.props.isContentActive() && this.props.pointerEvents?.() !== "none" && !MarqueeOptionsMenu.Instance.isShown() ?
- "all" :
- SnappingManager.GetIsDragging() ?
- undefined : "none";
- }
+ return this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : '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>;
+ 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>
+ );
}
getAnchor = () => {
- const anchor =
- AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ??
- this.rootDoc;
+ const anchor = AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ?? this.rootDoc;
return anchor;
- }
+ };
/**
* render contents in allMapMarkers (e.g. images with exifData) into google maps as map marker
- * @returns
+ * @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)}
- />
+ <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) => {
@@ -531,7 +552,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// if (SelectionManager.Views().lastElement()) {
// console.log(SelectionManager.Views().lastElement());
// }
- }
+ };
panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
@@ -543,7 +564,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
savedAnnotations = () => this._savedAnnotations;
render() {
- const renderAnnotations = (docFilters?: () => string[]) => (null);
+ 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
@@ -571,88 +592,88 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// addDocument={this.sidebarAddDocument}
// childPointerEvents={true}
// pointerEvents={CurrentUserUtils.ActiveTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
- return <div className="mapBox" ref={this._ref}>
- {/*console.log(apiKey)*/}
- {/* <LoadScript
+ 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 style={{ mixBlendMode: "multiply" }}>
- {renderAnnotations(this.transparentFilter)}
+ <div className="mapBox-wrapper" onWheel={e => e.stopPropagation()} onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()} 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" 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>
+ {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? null : (
+ <MarqueeAnnotator
+ rootDoc={this.rootDoc}
+ anchorMenuClick={this.anchorMenuClick}
+ scrollTop={0}
+ down={this._marqueeing}
+ scaling={returnOne}
+ addDocument={this.addDocumentWrapper}
+ docView={this.props.docViewPath().lastElement()}
+ finishMarquee={this.finishMarquee}
+ savedAnnotations={this.savedAnnotations}
+ annotationLayer={this._annotationLayer.current}
+ mainCont={this._mainCont.current}
+ />
+ )}
</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" 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}
+ {/* </LoadScript > */}
+ <div className="mapBox-sidebar" style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
+ <SidebarAnnos
+ ref={this._sidebarRef}
+ {...this.props}
+ fieldKey={this.fieldKey}
+ rootDoc={this.rootDoc}
+ layoutDoc={this.layoutDoc}
+ dataDoc={this.dataDoc}
+ showSidebar={this.SidebarShown}
+ nativeWidth={NumCast(this.layoutDoc._nativeWidth)}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- />)}
- {this.handleMapCenter(this._map)}
- </GoogleMap>
- {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
- <MarqueeAnnotator rootDoc={this.rootDoc}
- anchorMenuClick={this.anchorMenuClick}
- scrollTop={0}
- down={this._marqueeing} scaling={returnOne}
- addDocument={this.addDocumentWrapper}
- docView={this.props.docViewPath().lastElement()}
- finishMarquee={this.finishMarquee}
- savedAnnotations={this.savedAnnotations}
- annotationLayer={this._annotationLayer.current}
- mainCont={this._mainCont.current} />}
- </div>
- {/* </LoadScript > */}
- <div className="mapBox-sidebar"
- style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
- <SidebarAnnos ref={this._sidebarRef}
- {...this.props}
- fieldKey={this.fieldKey}
- rootDoc={this.rootDoc}
- layoutDoc={this.layoutDoc}
- dataDoc={this.dataDoc}
- showSidebar={this.SidebarShown}
- nativeWidth={NumCast(this.layoutDoc._nativeWidth)}
- whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- PanelWidth={this.sidebarWidth}
- sidebarAddDocument={this.sidebarAddDocument}
- moveDocument={this.moveDocument}
- removeDocument={this.sidebarRemoveDocument}
- />
- </div>
- <div className="mapBox-overlayButton-sidebar" key="sidebar" title="Toggle Sidebar"
- style={{
- display: !this.props.isContentActive() ? "none" : undefined,
- top: StrCast(this.rootDoc._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" />
+ PanelWidth={this.sidebarWidth}
+ sidebarAddDocument={this.sidebarAddDocument}
+ moveDocument={this.moveDocument}
+ removeDocument={this.sidebarRemoveDocument}
+ />
+ </div>
+ <div
+ className="mapBox-overlayButton-sidebar"
+ key="sidebar"
+ title="Toggle Sidebar"
+ style={{
+ display: !this.props.isContentActive() ? 'none' : undefined,
+ top: StrCast(this.rootDoc._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>
</div>
- </div>;
+ );
}
}