aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAubrey-Li <63608597+Aubrey-Li@users.noreply.github.com>2021-07-05 13:28:54 -0700
committerAubrey-Li <63608597+Aubrey-Li@users.noreply.github.com>2021-07-05 13:28:54 -0700
commitd675e32fdf2f4e0ca5a7adf8cbc5b462e81bc7f0 (patch)
tree15d03fbe4baddf351bc95fdb061bcc059ea09bbd /src
parent033e7a1aa20947f28672e8512245c2cd69982350 (diff)
searchbox zoom in and center on search
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/CollectionMapView.tsx127
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/client/views/collections/MapView/CollectionMapView.scss (renamed from src/client/views/collections/CollectionMapView.scss)18
-rw-r--r--src/client/views/collections/MapView/CollectionMapView.tsx312
-rw-r--r--src/client/views/nodes/PresBox.tsx13
-rw-r--r--src/client/views/presentationview/PresElementBox.tsx4
6 files changed, 346 insertions, 130 deletions
diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx
deleted file mode 100644
index 07755ed71..000000000
--- a/src/client/views/collections/CollectionMapView.tsx
+++ /dev/null
@@ -1,127 +0,0 @@
-import { GoogleMap, Marker, InfoWindow, LoadScript, GoogleMapProps } from '@react-google-maps/api';
-import { action, computed, Lambda, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { Doc, DocListCast, Field, FieldResult, Opt } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
-import { Id } from "../../../fields/FieldSymbols";
-import { makeInterface } from "../../../fields/Schema";
-import { Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
-import { LinkManager } from "../../util/LinkManager";
-import { undoBatch, UndoManager } from "../../util/UndoManager";
-import "./CollectionMapView.scss";
-import { CollectionSubView } from "./CollectionSubView";
-import React = require("react");
-import requestPromise = require("request-promise");
-
-type MapSchema = makeInterface<[typeof documentSchema]>;
-const MapSchema = makeInterface(documentSchema);
-
-export type LocationData = google.maps.LatLngLiteral & {
- address?: string
- resolvedAddress?: string;
- zoom?: number;
-};
-
-const mapContainerStyle = {
- height: '100%',
-};
-
-
-const defaultCenter = {
- lat: 0,
- lng: 0,
-}
-//-----------------------------test map marker-----------------------------------
-// const map = new google.maps.Map(document.getElementById('map')!, {
-// zoom: 10,
-// center: new google.maps.LatLng(-33.92, 151.25),
-// mapTypeId: google.maps.MapTypeId.ROADMAP
-// });
-
-// // test display markers
-// let locations = [
-// ['Bondi Beach', -33.890542, 151.274856, 4],
-// ['Coogee Beach', -33.923036, 151.259052, 5],
-// ['Cronulla Beach', -34.028249, 151.157507, 3],
-// ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
-// ['Maroubra Beach', -33.950198, 151.259302, 1]
-// ];
-
-// const infowindow = new google.maps.InfoWindow();
-// let marker: google.maps.Marker
-// let i: number
-
-// for (i = 0; i < locations.length; i++) {
-// marker = new google.maps.Marker({
-// position: new google.maps.LatLng(locations[i][1] as number, locations[i][2] as number),
-// map: map
-// });
-
-// google.maps.event.addListener(marker, 'click', (function (marker, i) {
-// return function () {
-// infowindow.setContent(locations[i][0] as string);
-// infowindow.open(map, marker);
-// }
-// })(marker, i));
-// }
-
-//----------------------------------------------------------------
-
-@observer
-export default class CollectionMapView extends CollectionSubView<MapSchema, GoogleMapProps>(MapSchema) {
-
-
- render() {
- const { childLayoutPairs } = this;
- const { Document, fieldKey, isContentActive: active } = this.props;
-
- // const { isLoaded, loadError } = useLoadScript({
- // googleMapsApiKey: 'AIzaSyALJU8DfCAqEAS0OqMDCmkE0otlz4H81fg',
- // libraries: ['places']
- // })
-
- // if (loadError) return "Error loading maps";
- // if (!isLoaded) return "Loading Maps";
-
-
- return <div className="collectionMapView" ref={this.createDashEventsTarget}>
-
- <div className={"collectionMapView-contents"}
- style={{ pointerEvents: active() ? undefined : "none", overflow: 'hidden' }}
- onWheel={e => e.stopPropagation()}
- onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} >
- <LoadScript
- googleMapsApiKey={process.env.GOOGLE_MAPS!}
- libraries={['places']}
- >
- <div className="map-wrapper">
- <GoogleMap
- mapContainerStyle={mapContainerStyle}
- zoom={5}
- center={defaultCenter}
- >
- <Marker
- // name={'SOMA'}
- position={{ lat: 37.778519, lng: -122.405640 }} />
- <Marker
- // name={'Dolores park'}
- position={{ lat: 47.617701, lng: -122.359485 }} />
- </GoogleMap>
- </div>
- </LoadScript >
- </div>
- </div >;
- }
-
-}
-
-// export default GoogleApiWrapper({
-// // apiKey: process.env.REACT_APP_DASH_GOOGLE_MAPS_API_KEY!,
-// apiKey: 'AIzaSyALJU8DfCAqEAS0OqMDCmkE0otlz4H81fg',
-// LoadingContainer: () => {
-// console.log(process.env.REACT_APP_DASH_GOOGLE_MAPS_API_KEY);
-// return <div className={"loadingWrapper"}>
-// <img className={"loadingGif"} src={"/assets/loading.gif"} />
-// </div>;
-// }
-// })(CollectionMapView) as any; \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index fb60265e3..65188e6f3 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -25,7 +25,7 @@ import { CollectionDockingView } from "./CollectionDockingView";
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import { CollectionGridView } from './collectionGrid/CollectionGridView';
import { CollectionLinearView } from './CollectionLinearView';
-import CollectionMapView from './CollectionMapView';
+import CollectionMapView from './MapView/CollectionMapView';
import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView';
import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView';
import { CollectionPileView } from './CollectionPileView';
diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/MapView/CollectionMapView.scss
index 874511533..c76f1d4b9 100644
--- a/src/client/views/collections/CollectionMapView.scss
+++ b/src/client/views/collections/MapView/CollectionMapView.scss
@@ -10,6 +10,24 @@
> div {
position: unset !important; // when the sidebar filter flys out, this prevents the map from extending outside the document box
}
+
+ .map-wrapper {
+ .searchbox {
+ box-sizing: border-box;
+ border: 1px solid transparent;
+ width: 240px;
+ height: 32px;
+ padding: 0 12px;
+ border-radius: 3px;
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
+ font-size: 14px;
+ outline: none;
+ text-overflow: ellipses;
+ position: absolute;
+ left: 50%;
+ margin-left: -120px;
+ }
+ }
}
}
diff --git a/src/client/views/collections/MapView/CollectionMapView.tsx b/src/client/views/collections/MapView/CollectionMapView.tsx
new file mode 100644
index 000000000..b3a5bdbff
--- /dev/null
+++ b/src/client/views/collections/MapView/CollectionMapView.tsx
@@ -0,0 +1,312 @@
+import { GoogleMap, Marker, InfoWindow, InfoBox, LoadScript, GoogleMapProps, StandaloneSearchBox, DrawingManager } from '@react-google-maps/api';
+import { observable, action, computed, Lambda, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import { Doc, DocListCast, Field, FieldResult, Opt } from "../../../../fields/Doc";
+import { documentSchema } from "../../../../fields/documentSchemas";
+import { Id } from "../../../../fields/FieldSymbols";
+import { makeInterface } from "../../../../fields/Schema";
+import { Cast, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
+import { LinkManager } from "../../../util/LinkManager";
+import { undoBatch, UndoManager } from "../../../util/UndoManager";
+import "./CollectionMapView.scss";
+import { CollectionSubView } from "../CollectionSubView";
+import React = require("react");
+import requestPromise = require("request-promise");
+import ReactDOM from 'react-dom';
+
+
+type MapSchema = makeInterface<[typeof documentSchema]>;
+const MapSchema = makeInterface(documentSchema);
+
+export type LocationData = {
+ id?: number;
+ pos?: { lat: number, lng: number };
+};
+
+const mapContainerStyle = {
+ height: '100%',
+};
+
+const defaultCenter = {
+ lat: 38.685,
+ lng: -115.234,
+};
+
+@observer
+export default class CollectionMapView extends CollectionSubView<MapSchema, GoogleMapProps>(MapSchema) {
+
+ @observable private mapRef = null as any;
+ @observable private selectedPlace: LocationData = { id: undefined, pos: undefined };
+ @observable private markerMap = {};
+ @observable private center = defaultCenter;
+ @observable private zoom = 2.5;
+ @observable private clickedLatLng = null;
+ @observable private infoWindowOpen = false;
+
+ @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 } }
+ ];
+
+ // iterate myPlaces to size, center, and zoom map to contain all markers
+ private fitBounds = (map: any) => {
+ const bounds = new window.google.maps.LatLngBounds();
+ console.log('map bound is:' + bounds);
+ this.myPlaces.map(place => {
+ bounds.extend(place.pos);
+ return place.id;
+ });
+ map.fitBounds(bounds)
+ }
+
+ // store a reference to google map instance; fit map bounds to contain all markers
+ @action
+ private loadHandler = (map: any) => {
+ this.mapRef = map;
+ this.fitBounds(map);
+
+ // //add a custom control for button add marker
+ // //TODO: why this doesn't work
+ // const google = window.google;
+ // console.log("google window: " + google)
+ // const controlButtonDiv = document.createElement('div');
+ // ReactDOM.render(<button onClick={() => console.log('click me to add marker!')}>Add Marker</button>, controlButtonDiv);
+ // map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlButtonDiv);
+ }
+
+ @action
+ private markerClickHandler = (e: MouseEvent, place: LocationData) => {
+ // set which place was clicked
+ this.selectedPlace = place
+
+ console.log(this.selectedPlace.id);
+ console.log(this.selectedPlace.pos);
+
+ // used so clicking a second marker works
+ if (this.infoWindowOpen) {
+ this.infoWindowOpen = false;
+ }
+
+ this.infoWindowOpen = true;
+ }
+
+ @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) {
+ // this.markerMap[place.id] = marker;
+ // }
+ // }
+
+ @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);
+ }
+ }
+
+ /**
+ * func that handles user's search location and zoom/pan on the input location
+ */
+ private searchLocation = () => {
+
+ }
+
+ /**
+ * func that adds marker to google maps
+ */
+ @undoBatch
+ private addMarker = () => {
+
+ }
+
+ /**
+ * func that updates suggested results (and auto-complete) during user input
+ */
+ private handleChange = () => {
+
+ }
+
+ // private mapRef = document.getElementById("map")
+ // private markers: google.maps.Marker[] = [];
+ @observable private input: HTMLInputElement | undefined;
+
+ @action
+ private setInputRef = (element: HTMLInputElement) => {
+ this.input = element;
+ console.log("htmlinputelement is:" + this.input)
+ }
+ // private searchBox = new window.google.maps.places.SearchBox(this.input);
+
+ private handlePlacesChanged = () => {
+ const searchBox = new window.google.maps.places.SearchBox(this.input!)
+ const places = searchBox.getPlaces();
+
+ console.log(places);
+
+ if (places.length == 0) { return; }
+
+ // // clear out old markers
+ // this.markers.forEach((marker) => {
+ // marker.setMap(null);
+ // });
+ // this.markers = []
+
+ // // for each place, get icon, name, location
+ const bounds = new window.google.maps.LatLngBounds();
+ 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),
+ // }
+
+ // //create a marker for each place
+ // this.markers.push(
+ // new google.maps.Marker({
+ // mapRef,
+ // title: place.name,
+ // position: place.geometry.location,
+ // })
+ // );
+
+ if (place.geometry.viewport) {
+ // only geocodes have viewport
+ bounds.union(place.geometry.viewport);
+ }
+ else {
+ bounds.extend(place.geometry.location);
+ }
+ });
+ }
+
+ // 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
+ // }
+
+ private onPolygonComplete = (polygon: any) => {
+ console.log(polygon)
+ }
+
+ private onMarkerComplete = (marker: any) => {
+ this.myPlaces.push(marker)
+ }
+
+ render() {
+ const { Document, fieldKey, isContentActive: active } = this.props;
+
+ return <div className="collectionMapView" ref={this.createDashEventsTarget}>
+
+ <div className={"collectionMapView-contents"}
+ style={{ pointerEvents: active() ? undefined : "none", overflow: 'hidden' }}
+ onWheel={e => e.stopPropagation()}
+ onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} >
+ <LoadScript
+ googleMapsApiKey={process.env.GOOGLE_MAPS!}
+ libraries={['places', 'drawing']}
+ >
+ <div className="map-wrapper">
+ <GoogleMap
+ mapContainerStyle={mapContainerStyle}
+ zoom={this.zoom}
+ center={this.center}
+ onLoad={map => this.loadHandler(map)}
+ >
+ <StandaloneSearchBox
+ onPlacesChanged={this.handlePlacesChanged}>
+ <input ref={this.setInputRef} className="searchbox" type="text" placeholder="Search anywhere:" />
+ </StandaloneSearchBox>
+
+ {this.myPlaces.map(place => (
+ <Marker
+ key={place.id}
+ position={place.pos}
+ // onLoad={marker => this.markerLoadHandler(marker, place)}
+ onClick={e => this.markerClickHandler(e, place)}
+ draggable={true}
+ onDragEnd={marker => this.handleDragMarker(marker, place)}
+ />
+ ))}
+ {this.infoWindowOpen && this.selectedPlace && (
+ <InfoWindow
+ // anchor={this.markerMap[this.selectedPlace.id]}
+ onCloseClick={this.handleInfoWindowClose}
+ position={this.selectedPlace.pos}
+ // options={{ enableEventPropagation: true }}
+ >
+ <div style={{ backgroundColor: 'white', opacity: 0.75, padding: 12 }}>
+ <div style={{ fontSize: 16 }}>
+ <div>
+ <a>a link to another node</a>
+ </div>
+ <div>
+ <a>a link to another node</a>
+ </div>
+ <div>
+ <a>a link to another node</a>
+ </div>
+ <div>
+ <button>New +</button>
+ </div>
+ </div>
+ </div>
+ </InfoWindow>
+ )}
+ {/* <DrawingManager
+ onPolygonComplete={this.onPolygonComplete}
+ onMarkerComplete={this.onMarkerComplete}
+ /> */}
+ </GoogleMap>
+ </div>
+ </LoadScript >
+ </div >
+ </div >;
+ }
+
+} \ No newline at end of file
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index f3fb6ff17..693348613 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -80,7 +80,12 @@ const PresBoxDocument = makeInterface(documentSchema);
@observer
export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
-
+
+ /**
+ * transitions & effects for documents
+ * @param renderDoc
+ * @param layoutDoc
+ */
static renderEffectsDoc(renderDoc: any, layoutDoc: Doc) {
const effectProps = {
left: layoutDoc.presEffectDirection === PresEffect.Left,
@@ -258,6 +263,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
}
+ //TODO: al: it seems currently that tempMedia doesn't stop onslidechange after clicking the button; the time the tempmedia stop depends on the start & end time
// No more frames in current doc and next slide is defined, therefore move to next slide
nextSlide = (activeNext: Doc) => {
const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null);
@@ -453,7 +459,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
/**
* Uses the viewfinder to progressivize through the different views of a single collection.
- * @param presTargetDoc: document for which internal zoom is used
+ * @param activeItem: document for which internal zoom is used
*/
zoomProgressivizeNext = (activeItem: Doc) => {
const targetDoc: Doc = this.targetDoc;
@@ -569,6 +575,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
load();
}
+ // The function pauses the auto presentation
@action
pauseAutoPres = () => {
if (this.layoutDoc.presStatus === PresStatus.Autoplay) {
@@ -592,6 +599,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
});
}
+ // The function allows for viewing the pres path on toggle
@action togglePath = (srcContext: Doc, off?: boolean) => {
if (off) {
this._pathBoolean = false;
@@ -602,6 +610,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
}
+ // The function allows for expanding the view of pres on toggle
@action toggleExpandMode = () => {
runInAction(() => this._expandBoolean = !this._expandBoolean);
this.rootDoc.expandBoolean = this._expandBoolean;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index f15d51764..19893af7e 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -164,6 +164,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
e.preventDefault();
}
+ /**
+ * Function to drag and drop the pres element to a diferent location
+ */
startDrag = (e: PointerEvent) => {
const miniView: boolean = this.toolbarWidth <= 100;
const activeItem = this.rootDoc;
@@ -242,6 +245,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
e.stopPropagation();
});
+ // set the value/title of the individual pres element
@undoBatch
@action
onSetValue = (value: string) => {