aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAubrey-Li <63608597+Aubrey-Li@users.noreply.github.com>2021-07-13 11:05:23 -0700
committerAubrey-Li <63608597+Aubrey-Li@users.noreply.github.com>2021-07-13 11:05:23 -0700
commit992b5ca20414c28eba255cf319eb2b762cb69933 (patch)
treed5c9e6d3268936e34ccfcff3d565d27aabb88690 /src
parent5f3486d68dd6a6c2b13acf7127188220a4012290 (diff)
npm, sharp, npm-gyp issue, try relaunch
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/MapView/CollectionMapView.tsx309
-rw-r--r--src/client/views/nodes/MapMarker/MapMarker.tsx23
2 files changed, 207 insertions, 125 deletions
diff --git a/src/client/views/collections/MapView/CollectionMapView.tsx b/src/client/views/collections/MapView/CollectionMapView.tsx
index 4243b89a5..ebf57c0c1 100644
--- a/src/client/views/collections/MapView/CollectionMapView.tsx
+++ b/src/client/views/collections/MapView/CollectionMapView.tsx
@@ -1,5 +1,5 @@
-import { GoogleMap, Marker, InfoWindow, InfoBox, useJsApiLoader, LoadScript, GoogleMapProps, StandaloneSearchBox, DrawingManager } from '@react-google-maps/api';
-import { observable, action, computed, Lambda, runInAction } from "mobx";
+import { GoogleMap, Marker, InfoWindow, InfoBox, useJsApiLoader, LoadScript, GoogleMapProps, StandaloneSearchBox, Autocomplete } from '@react-google-maps/api';
+import { observable, action, computed, Lambda, runInAction, IReactionDisposer } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCast, Field, FieldResult, Opt } from "../../../../fields/Doc";
import { documentSchema } from "../../../../fields/documentSchemas";
@@ -13,8 +13,21 @@ import { CollectionSubView } from "../CollectionSubView";
import React = require("react");
import requestPromise = require("request-promise");
import ReactDOM from 'react-dom';
+import { DragManager } from '../../../util/DragManager';
+import { MapMarker } from '../../nodes/MapMarker/MapMarker';
+/**
+ * Idea behind storing a marker:
+ * 1. on the map api, have a button "add marker" that adds the marker on the map & store the marker as a node in the collection
+ * (but don't render the marker in the collection itself)
+ * 2. each marker, as a node, has the same feature as all other nodes for linking (the same way one could form a link between a node inside a child collection
+ * and a node outside the child collection)
+ *
+ * /util/LinkManager.ts -- link relations
+ *
+ */
+
type MapSchema = makeInterface<[typeof documentSchema]>;
const MapSchema = makeInterface(documentSchema);
@@ -33,11 +46,13 @@ const defaultCenter = {
};
@observer
-export default class CollectionMapView extends CollectionSubView<MapSchema, GoogleMapProps>(MapSchema) {
+export default class CollectionMapView extends CollectionSubView<MapSchema, Partial<GoogleMapProps>>(MapSchema) {
+ private _dropDisposer?: DragManager.DragDropDisposer;
+ private _disposers: { [name: string]: IReactionDisposer } = {};
+
- @observable private _map = null as any
- @observable private mapRef = null as any;
- @observable private selectedPlace: LocationData = { id: undefined, pos: undefined };
+ @observable private _map = null as unknown as google.maps.Map;
+ @observable private selectedPlace: Doc = ;
@observable private markerMap = {};
@observable private center = defaultCenter;
@observable private zoom = 2.5;
@@ -45,14 +60,21 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
@observable private infoWindowOpen = false;
@observable private bounds = new window.google.maps.LatLngBounds();
@observable private inputRef = React.createRef<HTMLInputElement>();
- @observable private searchBox = new window.google.maps.places.SearchBox(this.inputRef.current!);
+ @observable private buttonRef = React.createRef<HTMLDivElement>();
@observable private searchMarkers: google.maps.Marker[] = [];
+ private 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;
+
+ @observable private searchBox = new window.google.maps.places.Autocomplete(this.inputRef.current!, this.options);
+
@observable private myPlaces = [
{ id: 1, pos: { lat: 39.09366509575983, lng: -94.58751660204751 } },
{ id: 2, pos: { lat: 41.82399, lng: -71.41283 } },
{ id: 3, pos: { lat: 47.606214, lng: -122.33207 } },
- { id: 4, pos: { lat: 36.7783, lng: 119.4179 } }
];
@action
@@ -60,8 +82,14 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
this.searchBox = searchBox;
}
+ @action
+ private setButton = (button: any) => {
+ this.buttonRef = button;
+ this._map.controls[google.maps.ControlPosition.TOP_RIGHT].push(this.buttonRef.current!)
+ }
+
// iterate myPlaces to size, center, and zoom map to contain all markers
- private fitBounds = (map: any) => {
+ private fitBounds = (map: google.maps.Map) => {
console.log('map bound is:' + this.bounds);
this.myPlaces.map(place => {
this.bounds.extend(place.pos);
@@ -72,8 +100,8 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
// store a reference to google map instance; fit map bounds to contain all markers
@action
- private loadHandler = (map: any) => {
- this.mapRef = map;
+ private loadHandler = (map: google.maps.Map) => {
+ this._map = map;
this.fitBounds(map);
// //add a custom control for button add marker
@@ -86,7 +114,7 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
}
@action
- private markerClickHandler = (e: MouseEvent, place: LocationData) => {
+ private markerClickHandler = (e: MouseEvent, place: Doc) => {
// set which place was clicked
this.selectedPlace = place
@@ -96,20 +124,23 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
// used so clicking a second marker works
if (this.infoWindowOpen) {
this.infoWindowOpen = false;
+ console.log("closeinfowindow")
}
-
- this.infoWindowOpen = true;
- }
-
- @action
- private handleInfoWindowClose = () => {
- if (this.infoWindowOpen) {
- this.infoWindowOpen = false;
+ else {
+ this.infoWindowOpen = true;
+ console.log("open infowindow")
}
- this.infoWindowOpen = false;
- this.selectedPlace = { id: undefined, pos: undefined };
}
+ // @action
+ // private handleInfoWindowClose = () => {
+ // if (this.infoWindowOpen) {
+ // this.infoWindowOpen = false;
+ // }
+ // this.infoWindowOpen = false;
+ // this.selectedPlace = { id: undefined, pos: undefined };
+ // }
+
// @action
// private markerLoadHandler = (marker: any, place: LocationData) => {
// if (marker != null) {
@@ -119,118 +150,140 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
@action
@undoBatch
- private handleDragMarker = (marker: any, place: LocationData) => {
- if (marker != null) {
- place = {
- id: place.id,
- pos: {
- lat: marker.latLng.lat().toFixed(3),
- lng: marker.latLng.lng().toFixed(3)
- }
- }
-
- console.log(place);
- console.log(this.myPlaces);
- }
+ private handleDragMarker = (marker: any, place: Doc) => {
+ // if (marker != null) {
+ // place = {
+ // id: place.id,
+ // position: {
+ // lat: marker.latLng.lat().toFixed(3),
+ // lng: marker.latLng.lng().toFixed(3)
+ // }
+ // }
+
+ // console.log(place);
+ // console.log(this.myPlaces);
+ // }
}
- // private mapRef = document.getElementById("map")
- // private markers: google.maps.Marker[] = [];
-
-
- // @action
- // private setInputRef = (element: HTMLInputElement) => {
- // if (this.inputRef.current) {
- // this.inputRef! = element;
- // console.log("htmlinputelement is:" + this.inputRef)
- // }
- // }
-
- // @observable private searchBox = new window.google.maps.places.SearchBox(this.inputRef.current!);
-
@action
- private handlePlacesChanged = () => {
+ private handlePlaceChanged = () => {
console.log(this.searchBox);
- const places = this.searchBox.getPlaces();
+ 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;
+ }
- console.log(places);
+ // zoom in on the location of the search result
+ if (place.geometry.viewport) {
+ console.log(this._map);
+ this._map.fitBounds(place.geometry.viewport);
+ } else {
+ console.log(this._map);
+ this._map.setCenter(place.geometry.location);
+ this._map.setZoom(17);
+ }
- if (places.length == 0) { return; }
+ /**
+ * customize icon => customized icon for the nature of the location selected (hard to tell from other pre-existing markers, probably won't implement
+ */
+ // 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),
+ // };
- // clear out old markers
this.searchMarkers.forEach((marker) => {
marker.setMap(null);
});
- this.searchMarkers = []
-
- // for each place, get icon, name, location
- places.forEach((place) => {
- if (!place.geometry || !place.geometry.location) {
- console.log("Returned place contains no geometry");
- return;
- }
-
- 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),
- }
+ this.searchMarkers = [];
+ this.searchMarkers.push(
+ new window.google.maps.Marker({
+ map: this._map,
+ title: place.name,
+ position: place.geometry.location,
+ })
+ )
+ }
- //create a marker for each place
- this.searchMarkers.push(
- new google.maps.Marker({
- map: this._map,
- icon: icon,
- title: place.name,
- position: place.geometry.location,
- })
- );
-
- if (place.geometry.viewport) {
- // only geocodes have viewport
- this.bounds.union(place.geometry.viewport);
- }
- else {
- this.bounds.extend(place.geometry.location);
+ @computed get markerContent() {
+ const allMarkers = this.childLayoutPairs
+ const markerId = NumCast(this.layoutDoc._itemIndex);
+ const selectedMarker = this.childLayoutPairs?.[markerId];
+ const position = {
+ lat: NumCast(this.layoutDoc.lat),
+ lng: NumCast(this.layoutDoc.lng)
+ }
+ return <>
+ {
+ allMarkers?.map(place => (
+ <Marker
+ key={markerId}
+ position={position}
+ onClick={e => this.markerClickHandler(e, place.layout)} //??
+ draggable={true}
+ onDragEnd={marker => this.handleDragMarker(marker, place.layout)}
+ />
+ ))
}
- });
-
- console.log(this.searchMarkers);
+ {this.infoWindowOpen && selectedMarker && (
+ <InfoBox
+ //anchor={selectedMarker}
+ // onCloseClick={this.handleInfoWindowClose}
+ position={position}
+ // options={{ enableEventPropagation: true }}
+ >
+ <div style={{ backgroundColor: 'white', opacity: 0.75, padding: 12 }}>
+ <div style={{ fontSize: 16 }}>
+ {/* the linkmenu as the ones in other nodes */}
+ <div>
+ <a>a link to another node</a>
+ <hr />
+ </div>
+ <div>
+ <a>a link to another node</a>
+ <hr />
+ </div>
+ <div>
+ <a>a link to another node</a>
+ <hr />
+ </div>
+ <div>
+ <button>New +</button>
+ </div>
+ </div>
+ </div>
+ </InfoBox>
+ )}
+
+ </>
}
- private onBoundsChanged = () => {
- this.searchBox.setBounds(this.bounds);
+ @action
+ private addMarker = (location: google.maps.LatLng | undefined, map: google.maps.Map) => {
+ new window.google.maps.Marker({
+ position: location,
+ map: map
+ });
}
- private onCenterChanged = () => {
-
+ @action
+ private renderMarkerToMap = (marker: Doc) => {
+ const id = StrCast(marker.id);
+ const lat = NumCast(marker.lat);
+ const lng = NumCast(marker.lng);
+
+ return <Marker
+ key={id}
+ position={{ lat: lat, lng: lng }}
+ onClick={e => this.markerClickHandler(e, marker)}
+ />
}
- // private setBounds = () => {
- // const places = this.searchBox.getPlaces();
- // if (places.length == 0) { return; }
-
- // const bounds = new google.maps.LatLngBounds();
- // places.forEach((place) => {
- // if (!place.geometry || !place.geometry.location) {
- // console.log("Returned place contains no geometry");
- // return;
- // }
-
- // if (place.geometry.viewport) {
- // // only geocodes have viewport
- // bounds.union(place.geometry.viewport);
- // }
- // else {
- // bounds.extend(place.geometry.location);
- // }
- // });
-
- // return bounds
- // }
-
render() {
const { Document, fieldKey, isContentActive: active } = this.props;
@@ -246,19 +299,22 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
> */}
<div className="map-wrapper">
<GoogleMap
- ref={(map) => this._map = map}
mapContainerStyle={mapContainerStyle}
zoom={this.zoom}
center={this.center}
onLoad={map => this.loadHandler(map)}
- onBoundsChanged={this.onBoundsChanged}
- onCenterChanged={this.onCenterChanged}
>
- <StandaloneSearchBox
+ <Autocomplete
onLoad={this.setSearchBox}
- onPlacesChanged={this.handlePlacesChanged}>
+ onPlaceChanged={this.handlePlaceChanged}>
<input ref={this.inputRef} className="searchbox" type="text" placeholder="Search anywhere:" />
- </StandaloneSearchBox>
+ </Autocomplete>
+
+ <div onLoad={this.setButton}>
+ <div ref={this.buttonRef} className="add-button-UI" >
+ <div className="add-button-Text">Add Marker</div>
+ </div>
+ </div>
{this.myPlaces.map(place => (
<Marker
@@ -271,9 +327,9 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
/>
))}
{this.infoWindowOpen && this.selectedPlace && (
- <InfoWindow
+ <InfoBox
// anchor={this.markerMap[this.selectedPlace.id]}
- onCloseClick={this.handleInfoWindowClose}
+ // onCloseClick={this.handleInfoWindowClose}
position={this.selectedPlace.pos}
// options={{ enableEventPropagation: true }}
>
@@ -281,19 +337,22 @@ export default class CollectionMapView extends CollectionSubView<MapSchema, Goog
<div style={{ fontSize: 16 }}>
<div>
<a>a link to another node</a>
+ <hr />
</div>
<div>
<a>a link to another node</a>
+ <hr />
</div>
<div>
<a>a link to another node</a>
+ <hr />
</div>
<div>
<button>New +</button>
</div>
</div>
</div>
- </InfoWindow>
+ </InfoBox>
)}
</GoogleMap>
</div>
diff --git a/src/client/views/nodes/MapMarker/MapMarker.tsx b/src/client/views/nodes/MapMarker/MapMarker.tsx
new file mode 100644
index 000000000..9705986a8
--- /dev/null
+++ b/src/client/views/nodes/MapMarker/MapMarker.tsx
@@ -0,0 +1,23 @@
+//TODO: mock imagebox, create marker as a doc
+import { IReactionDisposer } from "mobx";
+import { observer } from "mobx-react";
+import * as React from "react";
+import { documentSchema } from "../../../../fields/documentSchemas";
+import { createSchema, makeInterface } from "../../../../fields/Schema";
+import { ViewBoxBaseComponent } from "../../DocComponent";
+import { FieldView, FieldViewProps } from "../FieldView";
+
+export const markerSchema = createSchema({
+ lat: "number",
+ lng: "number"
+});
+
+type MarkerDocument = makeInterface<[typeof markerSchema, typeof documentSchema]>;
+const MarkerDocument = makeInterface(markerSchema, documentSchema);
+
+@observer
+export class MapMarker extends ViewBoxBaseComponent<FieldViewProps, MarkerDocument>(MarkerDocument) {
+ public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapMarker, fieldKey); }
+ private _markerRef: React.RefObject<google.maps.Marker> = React.createRef();
+ private _disposers: { [name: string]: IReactionDisposer } = {};
+} \ No newline at end of file