aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx96
-rw-r--r--src/client/views/nodes/MapBox/MapMarker.tsx117
2 files changed, 58 insertions, 155 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 9cee7f2a2..6894cea19 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Autocomplete, GoogleMap, GoogleMapProps, InfoWindow, Marker } from '@react-google-maps/api';
+import { Autocomplete, GoogleMap, GoogleMapProps, InfoWindow, LoadScript, Marker } from '@react-google-maps/api';
import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx';
import { observer } from "mobx-react";
import * as React from "react";
@@ -29,22 +29,25 @@ import { SidebarAnnos } from '../../SidebarAnnos';
import { StyleProp } from '../../StyleProvider';
import { FieldView, FieldViewProps } from '../FieldView';
import "./MapBox.scss";
-import { MapMarker } from './MapMarker';
-const _global = (window /* browser */ || global /* node */) as any;
+
+/**
+ * MapBox architecture:
+ * Main component: MapBox.tsx
+ * Supporting Components: SidebarAnnos, CollectionStackingView
+ *
+ * MapBox is a node that extends the ViewBoxAnnotatableComponent. Similar to PDFBox and WebBox, it supports interaction between sidebar content and document content.
+ * The main body of MapBox uses Google Maps API to allow location retrieval, adding map markers, pan and zoom, and open street view.
+ * Dash Document architecture is integrated with Maps API: When drag and dropping documents with ExifData (gps Latitude and Longitude information) available,
+ * sidebarAddDocument function checks if the document contains lat & lng information, if it does, then the document is added to both the sidebar and the infowindow (a pop up corresponding to a map marker--pin on map).
+ * The lat and lng field of the document is filled when importing (spec see ConvertDMSToDD method and processFileUpload method in Documents.ts).
+ * A map marker is considered a document that contains a collection with stacking view of documents, it has a lat, lng location, which is passed to Maps API's custom marker (red pin) to be rendered on the google maps
+ */
+
+// const _global = (window /* browser */ || global /* node */) as any;
type MapDocument = makeInterface<[typeof documentSchema]>;
const MapDocument = makeInterface(documentSchema);
-export type Coordinates = {
- lat: number,
- lng: number,
-}
-
-export type LocationData = {
- id: string;
- pos: Coordinates;
-};
-
const mapContainerStyle = {
height: '100%',
};
@@ -58,6 +61,9 @@ const mapOptions = {
fullscreenControl: false,
}
+/**
+ * Consider integrating later: allows for drawing, circling, making shapes on map
+ */
const drawingManager = new google.maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
@@ -65,13 +71,14 @@ const drawingManager = new google.maps.drawing.DrawingManager({
drawingModes: [
google.maps.drawing.OverlayType.MARKER,
// currently we are not supporting the following drawing mode on map, a thought for future development
- // google.maps.drawing.OverlayType.CIRCLE,
- // google.maps.drawing.OverlayType.POLYLINE,
+ google.maps.drawing.OverlayType.CIRCLE,
+ google.maps.drawing.OverlayType.POLYLINE,
],
},
});
+// options for searchbox in Google Maps Places Autocomplete API
const options = {
fields: ["formatted_address", "geometry", "name"], // note: level of details is charged by item per retrieval, not recommended to return all fields
strictBounds: false,
@@ -96,7 +103,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
// @observable private markerIdToMapMarker: { [id: string]: Doc | MapMarker | undefined } = {};
@observable private center = navigator.geolocation ? navigator.geolocation.getCurrentPosition : defaultCenter;
@observable private zoom = 2.5;
- @observable private infoWindowOpen = false;
@observable private _marqueeing: number[] | undefined;
@observable private _isAnnotating = false;
@observable private bounds = new window.google.maps.LatLngBounds();
@@ -105,10 +111,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@observable private searchBox = new window.google.maps.places.Autocomplete(this.inputRef.current!, options);
@observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
@computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); };
- @computed get allMapMarkers() { return DocListCast(this.dataDoc[this.annotationKey]); }; // method to add MapMarker to allMapMarkers
- //TODO: change all markers to a filter function to change
+ @computed get allMapMarkers() { return DocListCast(this.dataDoc[this.annotationKey]); };
@observable private toggleAddMarker = false;
-
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
@@ -241,18 +245,26 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
console.log(this.allMapMarkers)
}
})
- // this._map.addListener(drawingManager, 'markercomplete', this.addMarker)
}
+ /**
+ * Load and render all map markers
+ * @param marker
+ * @param place
+ */
@action
private markerLoadHandler = (marker: google.maps.Marker, place: Doc) => {
place[Id] ? this.markerMap[place[Id]] = marker : null;
- // place[Id] ? this.markerIdToMapMarker[place[Id]] = place : null;
console.log("the following is a markerMap from id to Marker:")
console.log(this.markerMap);
}
+ /**
+ * on clicking the map marker, set the selected place to the marker document & set infowindowopen to be true
+ * @param e
+ * @param place
+ */
@action
private markerClickHandler = (e: MouseEvent, place: Doc) => {
// set which place was clicked
@@ -266,7 +278,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
/**
- * Called when dragging documents into map sidebar or directly into infowindow
+ * Called when dragging documents into map sidebar or directly into infowindow; to create a map marker, ref to MapMarkerDocument in Documents.ts
* @param doc
* @param sidebarKey
* @returns
@@ -294,6 +306,12 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
return this.addDocument(doc, sidebarKey); // add to sidebar list
}
+ /**
+ * Removing documents from the sidebar
+ * @param doc
+ * @param sidebarKey
+ * @returns
+ */
sidebarRemoveDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
if (this.layoutDoc._showSidebar) this.toggleSidebar();
const docs = doc instanceof Doc ? [doc] : doc;
@@ -386,6 +404,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
place.infoWindowOpen = false;
}
+ /**
+ * Handles toggle of sidebar on click the little comment button
+ */
@computed get sidebarHandle() {
TraceMobx();
const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
@@ -403,6 +424,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
</div>;
}
+ // TODO: Adding highlight box layer to Maps
@action
toggleSidebar = () => {
const prevWidth = this.sidebarWidth();
@@ -459,20 +481,14 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
getAnchor = () => {
const anchor =
AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ??
- this.rootDoc // if anchormenu pops up else return rootDoc (map)
- // Docs.Create.MapMarkerDocument(this.allMapMarkers, {
- // title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
- // annotationOn: this.rootDoc,
- // y: NumCast(this.layoutDoc._scrollTop),
- // });
- // this.addDocument(anchor);
+ this.rootDoc
return anchor;
}
infoWidth = () => this.props.PanelWidth() / 5;
infoHeight = () => this.props.PanelWidth() / 5;
- //documentView
+ // Collection stacking view for documents in the infowindow of a map marker
private renderChildDocs = (selectedDoc: Doc) => {
return <div style={{ width: this.infoWidth(), height: this.infoHeight() }}>
<CollectionStackingView {
@@ -521,6 +537,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
))
}
+ /**
+ * Renders infowindow corresponding to a map marker document
+ * @param place
+ * @returns
+ */
private renderInfoWindow = (place: Doc) => {
return place.infoWindowOpen && (
@@ -540,6 +561,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
)
}
+ // TODO: auto center on select a document in the sidebar
private handleMapCenter = (map: google.maps.Map) => {
console.log("print the selected views in selectionManager:")
if (SelectionManager.Views().lastElement()) {
@@ -579,13 +601,11 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
addDocument={this.sidebarAddDocument}
childPointerEvents={true}
pointerEvents={CurrentUserUtils.SelectedTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
- return <div className="mapBox" ref={this._ref}
- // style={{ pointerEvents: this.isContentActive() ? undefined : "none" }}
- >
- {/* // {/* <LoadScript
- // googleMapsApiKey={process.env.GOOGLE_MAPS!}
- // libraries={['places', 'drawing']}
- // > */}
+ return <div className="mapBox" ref={this._ref}>
+ {/* <LoadScript
+ googleMapsApiKey={process.env.GOOGLE_MAPS!}
+ libraries={['places', 'drawing']}
+ > */}
<div className="mapBox-wrapper"
onWheel={e => e.stopPropagation()}
onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()}
@@ -627,7 +647,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
annotationLayer={this._annotationLayer.current}
mainCont={this._mainCont.current} />}
</div>
- {/* {/* </LoadScript > */}
+ {/* </LoadScript > */}
<div className="mapBox-sidebar"
style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
<SidebarAnnos ref={this._sidebarRef}
diff --git a/src/client/views/nodes/MapBox/MapMarker.tsx b/src/client/views/nodes/MapBox/MapMarker.tsx
deleted file mode 100644
index fbad0cf65..000000000
--- a/src/client/views/nodes/MapBox/MapMarker.tsx
+++ /dev/null
@@ -1,117 +0,0 @@
-import { action, computed, IReactionDisposer, observable } from "mobx";
-import { observer } from "mobx-react";
-import { Transaction } from "prosemirror-state";
-import { EditorView } from "prosemirror-view";
-import * as React from "react";
-import { Doc, DocListCast, Opt } from "../../../../fields/Doc";
-import { documentSchema } from "../../../../fields/documentSchemas";
-import { Id } from "../../../../fields/FieldSymbols";
-import { createSchema, makeInterface } from "../../../../fields/Schema";
-import { Cast, NumCast } from "../../../../fields/Types";
-import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
-import { DragManager } from "../../../util/DragManager";
-import { CollectionViewType } from "../../collections/CollectionView";
-import { TabDocView } from "../../collections/TabDocView";
-import { ViewBoxAnnotatableProps, ViewBoxAnnotatableComponent } from "../../DocComponent";
-import { AnchorMenu } from "../../pdf/AnchorMenu";
-import { FieldView, FieldViewProps } from "../FieldView";
-import { FormattedTextBox } from "../formattedText/FormattedTextBox";
-import { RichTextMenu } from "../formattedText/RichTextMenu";
-
-type MarkerDocument = makeInterface<[typeof documentSchema]>;
-const MarkerDocument = makeInterface(documentSchema);
-
-export type Coordinates = {
- lat: number,
- lng: number,
-}
-
-//TODO: MapMarkerBox
-@observer
-export class MapMarker extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, MarkerDocument>(MarkerDocument) {
- makeLinkAnchor(arg1: string, undefined: undefined, arg3: string) {
- throw new Error("Method not implemented.");
- }
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapMarker, fieldKey); }
- private _markerRef: React.RefObject<google.maps.Marker> = React.createRef();
- private _disposers: { [name: string]: IReactionDisposer } = {};
- _latlngLocation!: Coordinates;
- _markerId!: number;
- private _editorView: Opt<EditorView> // we'll see if this becomes useful for marker annotation/create link
- @observable _title: string = ""; // the title of the marker
- @observable _description: string = ""; // the description of the marker contents
- @observable isMarkerActive: boolean = false; // whether the marker is selected (we'll see if we need this)
- @observable activeLinks: Doc[] = []; //TBD: what linking data structure looks like
- @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); } // a list of documents with the same/similar geographic coordinates
- @computed get tagDocs() { // might come in handy for filtering
- const tagDocs: Doc[] = [];
- for (const doc of this.childDocs) {
- const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
- tagDocs.push(tagDoc);
- }
- return tagDocs;
- }
-
- @computed get lat() { return NumCast(this.dataDoc.lat) }
- @computed get lng() { return NumCast(this.dataDoc.lng) }
-
- /**
- * Methods
- */
- componentDidMount() { }
-
- componentWillMount() { }
-
- @computed private get filterAssociatedDocs() {
- return
- }
-
- addLinkToMarker = () => { }
-
-
-
- @action
- setupAnchorMenu = () => {
- AnchorMenu.Instance.Status = "marquee";
- AnchorMenu.Instance.Highlight = action((color: string, isLinkButton: boolean) => {
- this._editorView?.state && RichTextMenu.Instance.insertHighlight(color, this._editorView.state, this._editorView?.dispatch);
- return undefined;
- });
- /**
- * This function is used by the PDFmenu to create an anchor highlight and a new linked text annotation.
- * It also initiates a Drag/Drop interaction to place the text annotation.
- */
- AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => {
- e.preventDefault();
- e.stopPropagation();
- const targetCreator = (annotationOn?: Doc) => {
- const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.rootDoc.title, 0, 0, 100, 100, undefined, annotationOn);
- FormattedTextBox.SelectOnLoad = target[Id];
- return target;
- };
-
- // DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docViewPath().lastElement(), this.getAnchor, targetCreator), e.pageX, e.pageY);
- });
- const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
- this.props.isSelected(true) && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom);
- }
-
- // will see if end up using this
- dispatchTransaction = (tx: Transaction) => { }
-
-
- //will see if needed
- // for inserting timestamps
- insertTime = () => { }
-
- //for setting the title of the marker
- @action
- private updateTitle = () => { }
-
- //for updating the description of the marker
- @action
- private updateDescrption = () => { }
-
-
-
-} \ No newline at end of file