From d675e32fdf2f4e0ca5a7adf8cbc5b462e81bc7f0 Mon Sep 17 00:00:00 2001 From: Aubrey-Li <63608597+Aubrey-Li@users.noreply.github.com> Date: Mon, 5 Jul 2021 13:28:54 -0700 Subject: searchbox zoom in and center on search --- src/client/views/nodes/PresBox.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes') 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(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 } } + //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 /** * 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 load(); } + // The function pauses the auto presentation @action pauseAutoPres = () => { if (this.layoutDoc.presStatus === PresStatus.Autoplay) { @@ -592,6 +599,7 @@ export class PresBox extends ViewBoxBaseComponent }); } + // 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 } } + // The function allows for expanding the view of pres on toggle @action toggleExpandMode = () => { runInAction(() => this._expandBoolean = !this._expandBoolean); this.rootDoc.expandBoolean = this._expandBoolean; -- cgit v1.2.3-70-g09d2 From 992b5ca20414c28eba255cf319eb2b762cb69933 Mon Sep 17 00:00:00 2001 From: Aubrey-Li <63608597+Aubrey-Li@users.noreply.github.com> Date: Tue, 13 Jul 2021 11:05:23 -0700 Subject: npm, sharp, npm-gyp issue, try relaunch --- .../collections/MapView/CollectionMapView.tsx | 309 ++++++++++++--------- src/client/views/nodes/MapMarker/MapMarker.tsx | 23 ++ 2 files changed, 207 insertions(+), 125 deletions(-) create mode 100644 src/client/views/nodes/MapMarker/MapMarker.tsx (limited to 'src/client/views/nodes') 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) { +export default class CollectionMapView extends CollectionSubView>(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(); - @observable private searchBox = new window.google.maps.places.SearchBox(this.inputRef.current!); + @observable private buttonRef = React.createRef(); @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 { + 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 { - 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 { + private markerClickHandler = (e: MouseEvent, place: Doc) => { // set which place was clicked this.selectedPlace = place @@ -96,20 +124,23 @@ export default class CollectionMapView extends CollectionSubView { - 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 { - 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 => ( + this.markerClickHandler(e, place.layout)} //?? + draggable={true} + onDragEnd={marker => this.handleDragMarker(marker, place.layout)} + /> + )) } - }); - - console.log(this.searchMarkers); + {this.infoWindowOpen && selectedMarker && ( + +
+
+ {/* the linkmenu as the ones in other nodes */} + + + +
+ +
+
+
+
+ )} + + } - 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 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 */}
this._map = map} mapContainerStyle={mapContainerStyle} zoom={this.zoom} center={this.center} onLoad={map => this.loadHandler(map)} - onBoundsChanged={this.onBoundsChanged} - onCenterChanged={this.onCenterChanged} > - + onPlaceChanged={this.handlePlaceChanged}> - + + +
+
+
Add Marker
+
+
{this.myPlaces.map(place => ( ))} {this.infoWindowOpen && this.selectedPlace && ( - @@ -281,19 +337,22 @@ export default class CollectionMapView extends CollectionSubView
- + )} 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(MarkerDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapMarker, fieldKey); } + private _markerRef: React.RefObject = React.createRef(); + private _disposers: { [name: string]: IReactionDisposer } = {}; +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From d5c261f306a45fda46e948b9db001874a2d9a0ae Mon Sep 17 00:00:00 2001 From: Aubrey-Li <63608597+Aubrey-Li@users.noreply.github.com> Date: Sat, 17 Jul 2021 12:58:57 -0700 Subject: add MapBox --- src/client/views/nodes/MapBox/MapBox.scss | 32 +++ src/client/views/nodes/MapBox/MapBox.tsx | 374 ++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+) create mode 100644 src/client/views/nodes/MapBox/MapBox.scss create mode 100644 src/client/views/nodes/MapBox/MapBox.tsx (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/MapBox/MapBox.scss b/src/client/views/nodes/MapBox/MapBox.scss new file mode 100644 index 000000000..863907aaf --- /dev/null +++ b/src/client/views/nodes/MapBox/MapBox.scss @@ -0,0 +1,32 @@ +.MapBox { + width: 100%; + height: 100%; + overflow: hidden; + + .MapBox-contents { + width: 100%; + height: 100%; + overflow: hidden; + > 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/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx new file mode 100644 index 000000000..aa220c4da --- /dev/null +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -0,0 +1,374 @@ +import { Autocomplete, GoogleMap, GoogleMapProps, InfoBox, Marker } from '@react-google-maps/api'; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx'; +import { observer } from "mobx-react"; +import * as React from "react"; +import { Doc, WidthSym } from '../../../../fields/Doc'; +import { documentSchema } from '../../../../fields/documentSchemas'; +import { makeInterface } from '../../../../fields/Schema'; +import { NumCast } from '../../../../fields/Types'; +import { setupMoveUpEvents, emptyFunction } from '../../../../Utils'; +import { DragManager } from '../../../util/DragManager'; +import { undoBatch } from '../../../util/UndoManager'; +import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; +import { SidebarAnnos } from '../../SidebarAnnos'; +import { FieldView, FieldViewProps } from '../FieldView'; +import "./MapBox.scss" + +type MapDocument = makeInterface<[typeof documentSchema]>; +const MapDocument = 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 class MapBox extends ViewBoxAnnotatableComponent, MapDocument>(MapDocument) { + private _dropDisposer?: DragManager.DragDropDisposer; + private _disposers: { [name: string]: IReactionDisposer } = {}; + private _sidebarRef = React.createRef(); + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapBox, fieldKey); } + + @observable private _map = null as unknown as google.maps.Map; + @observable private selectedPlace: LocationData = null as any; + @observable private markerMap = {}; + @observable private center = defaultCenter; + @observable private zoom = 2.5; + @observable private clickedLatLng = null; + @observable private infoWindowOpen = false; + @observable private bounds = new window.google.maps.LatLngBounds(); + @observable private inputRef = React.createRef(); + @observable private buttonRef = React.createRef(); + @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 } }, + ]; + + @action + private setSearchBox = (searchBox: any) => { + 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: google.maps.Map) => { + console.log('map bound is:' + this.bounds); + this.myPlaces.map(place => { + this.bounds.extend(place.pos); + return place.id; + }); + map.fitBounds(this.bounds) + } + + // store a reference to google map instance; fit map bounds to contain all markers + @action + private loadHandler = (map: google.maps.Map) => { + this._map = 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(, 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; + console.log("closeinfowindow") + } + else { + this.infoWindowOpen = true; + console.log("open infowindow") + } + } + + sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => { + if (!this.layoutDoc._showSidebar) this.toggleSidebar(); + return this.addDocument(doc, sidebarKey); + } + 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); + } + toggleSidebar = action(() => { + const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]); + const ratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? 250 : 0) + nativeWidth) / nativeWidth; + const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth); + this.layoutDoc.nativeWidth = nativeWidth * ratio; + this.layoutDoc._width = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth; + this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth; + }); + sidebarWidth = () => !this.layoutDoc._showSidebar ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth); + + @action + @undoBatch + private handleDragMarker = (marker: any, place: LocationData) => { + // 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); + // } + } + + @action + private handlePlaceChanged = () => { + console.log(this.searchBox); + 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) { + 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); + } + + /** + * 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), + // }; + + this.searchMarkers.forEach((marker) => { + marker.setMap(null); + }); + this.searchMarkers = []; + this.searchMarkers.push( + new window.google.maps.Marker({ + map: this._map, + title: place.name, + position: 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 => ( + // this.markerClickHandler(e, place.layout)} //?? + // draggable={true} + // onDragEnd={marker => this.handleDragMarker(marker, place.layout)} + // /> + // )) + // } + // {this.infoWindowOpen && selectedMarker && ( + // + //
+ //
+ // {/* the linkmenu as the ones in other nodes */} + //
+ // a link to another node + //
+ //
+ //
+ // a link to another node + //
+ //
+ //
+ // a link to another node + //
+ //
+ //
+ // + //
+ //
+ //
+ //
+ // )} + + // + // } + + @action + private addMarker = (location: google.maps.LatLng | undefined, map: google.maps.Map) => { + new window.google.maps.Marker({ + position: location, + map: map + }); + } + + // @action + // private renderMarkerToMap = (marker: Doc) => { + // const id = StrCast(marker.id); + // const lat = NumCast(marker.lat); + // const lng = NumCast(marker.lng); + + // return this.markerClickHandler(e, marker)} + // /> + // } + + render() { + const { Document, fieldKey, isContentActive: active } = this.props; + + return
+ +
e.stopPropagation()} + onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > + {/* */} +
+ this.loadHandler(map)} + > + + + + +
+
+
Add Marker
+
+
+ + {this.myPlaces.map(place => ( + this.markerLoadHandler(marker, place)} + onClick={e => this.markerClickHandler(e, place)} + draggable={true} + onDragEnd={marker => this.handleDragMarker(marker, place)} + /> + ))} + {this.infoWindowOpen && this.selectedPlace && ( + +
+ +
+
+ )} +
+
+ {/*
*/} + +
+
; + } + +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 53dfd5f380d8c75fedc967577fb16310d08cefea Mon Sep 17 00:00:00 2001 From: Aubrey-Li <63608597+Aubrey-Li@users.noreply.github.com> Date: Mon, 19 Jul 2021 11:57:22 -0700 Subject: map as node --- package-lock.json | 36 ++++-- package.json | 40 +++--- src/client/documents/DocumentTypes.ts | 71 +++++------ src/client/documents/Documents.ts | 26 +++- src/client/util/CurrentUserUtils.ts | 5 + src/client/util/type_decls.d | 1 + src/client/views/MainView.tsx | 6 +- .../collections/MapView/CollectionMapView.tsx | 134 ++++++++++----------- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/search/IconButton.tsx | 1 + src/fields/Doc.ts | 1 + 11 files changed, 185 insertions(+), 139 deletions(-) (limited to 'src/client/views/nodes') diff --git a/package-lock.json b/package-lock.json index 2b1dba232..5c5b2cb49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -324,11 +324,18 @@ "integrity": "sha512-cY+QfDTbZ7XVxzx7jxbC98Oxr/zc7R2QpTLqTxqlfyXDrAJjzi/xUIqAUsygELB62JIrbsWxtSRhayKFkGI7MA==" }, "@fortawesome/fontawesome-svg-core": { - "version": "1.2.29", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.29.tgz", - "integrity": "sha512-xmPmP2t8qrdo8RyKihTkGb09RnZoc+7HFBCnr0/6ZhStdGDSLeEd7ajV181+2W29NWIFfylO13rU+s3fpy3cnA==", + "version": "1.2.35", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz", + "integrity": "sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.2.29" + "@fortawesome/fontawesome-common-types": "^0.2.35" + }, + "dependencies": { + "@fortawesome/fontawesome-common-types": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.35.tgz", + "integrity": "sha512-IHUfxSEDS9dDGqYwIW7wTN6tn/O8E0n5PcAHz9cAaBoZw6UpG20IG/YM3NNLaGPwPqgjBAFjIURzqoQs3rrtuw==" + } } }, "@fortawesome/free-brands-svg-icons": { @@ -355,17 +362,24 @@ } }, "@fortawesome/free-solid-svg-icons": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.13.1.tgz", - "integrity": "sha512-LQH/0L1p4+rqtoSHa9qFYR84hpuRZKqaQ41cfBQx8b68p21zoWSekTAeA54I/2x9VlCHDLFlG74Nmdg4iTPQOg==", + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz", + "integrity": "sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.2.29" + "@fortawesome/fontawesome-common-types": "^0.2.35" + }, + "dependencies": { + "@fortawesome/fontawesome-common-types": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.35.tgz", + "integrity": "sha512-IHUfxSEDS9dDGqYwIW7wTN6tn/O8E0n5PcAHz9cAaBoZw6UpG20IG/YM3NNLaGPwPqgjBAFjIURzqoQs3rrtuw==" + } } }, "@fortawesome/react-fontawesome": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.11.tgz", - "integrity": "sha512-sClfojasRifQKI0OPqTy8Ln8iIhnxR/Pv/hukBhWnBz9kQRmqi6JSH3nghlhAY7SUeIIM7B5/D2G8WjX0iepVg==", + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.14.tgz", + "integrity": "sha512-4wqNb0gRLVaBm/h+lGe8UfPPivcbuJ6ecI4hIgW0LjI7kzpYB9FkN0L9apbVzg+lsBdcTf0AlBtODjcSX5mmKA==", "requires": { "prop-types": "^15.7.2" } diff --git a/package.json b/package.json index 42f2af28f..bd5d73753 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "oldstart": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug -- src/server/index.ts", "debug": "cross-env NODE_OPTIONS=--max_old_space_size=8192 ts-node-dev --transpile-only --inspect -- src/server/index.ts", "monitor": "cross-env MONITORED=true NODE_OPTIONS=--max_old_space_size=4096 ts-node src/server/index.ts", - "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 webpack --env production", + "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 pack --env production", "test": "mocha -r ts-node/register test/**/*.ts", "tsc": "tsc" }, @@ -85,20 +85,20 @@ "@types/typescript": "^2.0.0", "@types/uuid": "^3.4.6", "@types/valid-url": "^1.0.3", - "@types/webpack": "^4.41.27", - "@types/webpack-dev-middleware": "^2.0.7", - "@types/webpack-hot-middleware": "^2.25.4", + "@types/pack": "^4.41.27", + "@types/pack-dev-middleware": "^2.0.7", + "@types/pack-hot-middleware": "^2.25.4", "@types/xregexp": "^4.3.0", "@types/youtube": "0.0.39", "awesome-typescript-loader": "^5.2.1", "chai": "^4.2.0", - "copy-webpack-plugin": "^4.6.0", + "copy-pack-plugin": "^4.6.0", "cross-env": "^5.2.1", "css-loader": "^2.1.1", "dotenv": "^8.6.0", "file-loader": "^3.0.1", - "fork-ts-checker-webpack-plugin": "^1.6.0", - "html-webpack-plugin": "^5.3.2", + "fork-ts-checker-pack-plugin": "^1.6.0", + "html-pack-plugin": "^5.3.2", "jsdom": "^15.2.1", "mocha": "^5.2.0", "sass-loader": "^7.3.1", @@ -110,18 +110,18 @@ "tslint": "^5.20.1", "tslint-loader": "^3.6.0", "typescript": "^3.9.9", - "webpack": "^4.46.0", - "webpack-cli": "^3.3.12", - "webpack-dev-middleware": "^3.7.3", - "webpack-dev-server": "^3.11.0", - "webpack-hot-middleware": "^2.24.3" + "pack": "^4.46.0", + "pack-cli": "^3.3.12", + "pack-dev-middleware": "^3.7.3", + "pack-dev-server": "^3.11.0", + "pack-hot-middleware": "^2.24.3" }, "dependencies": { - "@fortawesome/fontawesome-svg-core": "^1.2.29", + "@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/free-brands-svg-icons": "^5.14.0", "@fortawesome/free-regular-svg-icons": "^5.13.1", - "@fortawesome/free-solid-svg-icons": "^5.13.1", - "@fortawesome/react-fontawesome": "^0.1.11", + "@fortawesome/free-solid-svg-icons": "^5.15.3", + "@fortawesome/react-fontawesome": "^0.1.14", "@hig/flyout": "^1.2.1", "@hig/theme-context": "^2.1.3", "@hig/theme-data": "^2.16.1", @@ -140,8 +140,8 @@ "@types/react-reconciler": "^0.26.1", "@types/reveal": "^3.3.33", "@types/three": "^0.126.2", - "@types/webscopeio__react-textarea-autocomplete": "^4.6.1", - "@webscopeio/react-textarea-autocomplete": "^4.7.0", + "@types/scopeio__react-textarea-autocomplete": "^4.6.1", + "@scopeio/react-textarea-autocomplete": "^4.7.0", "adm-zip": "^0.4.16", "archiver": "^3.1.1", "array-batcher": "^1.2.3", @@ -275,11 +275,11 @@ "use-places-autocomplete": "^1.9.3", "uuid": "^3.4.0", "valid-url": "^1.0.9", - "web-request": "^1.0.7", - "webrtc-adapter": "^7.6.3", + "-request": "^1.0.7", + "rtc-adapter": "^7.6.3", "wikijs": "^6.0.1", "words-to-numbers": "^1.5.1", "xoauth2": "^1.2.0", "xregexp": "^4.3.0" } -} +} \ No newline at end of file diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 8565784b4..422d9c2e3 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -2,44 +2,47 @@ export enum DocumentType { NONE = "none", // core data types - RTF = "rtf", // rich text - IMG = "image", // image box - WEB = "web", // web page or html clipping - COL = "collection", // collection - KVP = "kvp", // key value pane - VID = "video", // video - AUDIO = "audio", // audio - PDF = "pdf", // pdf - INK = "inks", // ink stroke - SCREENSHOT = "screenshot", // view of a desktop application - FONTICON = "fonticonbox", // font icon + RTF = "rtf", + IMG = "image", + WEB = "web", + COL = "collection", + KVP = "kvp", + VID = "video", + AUDIO = "audio", + PDF = "pdf", + INK = "inks", + SCREENSHOT = "screenshot", + FONTICON = "fonticonbox", FILTER = "filter", - SEARCH = "search", // search query - LABEL = "label", // simple text label - BUTTON = "button", // onClick button - WEBCAM = "webcam", // webcam - HTMLANCHOR = "htmlanchor", // text selection anchor in PDF/Web - DATE = "date", // calendar view of a date - SCRIPTING = "script", // script editor - EQUATION = "equation", // equation editor - FUNCPLOT = "funcplot", // function plotter + SEARCH = "search", + LABEL = "label", + BUTTON = "button", + WEBCAM = "webcam", + HTMLANCHOR = "htmlanchor", + DATE = "date", + SCRIPTING = "script", + EQUATION = "equation", + FUNCPLOT = "funcplot", + MAP = "MAP", + // special purpose wrappers that either take no data or are compositions of lower level types - LINK = "link", // link (view of a document that acts as a link) - LINKANCHOR = "linkanchor", // blue dot link anchor (view of a link document's anchor) - IMPORT = "import", // directory import box (file system directory) - SLIDER = "slider", // number slider (view of a number) - PRES = "presentation", // presentation (view of a collection) --- shouldn't this be a view type? technically requires a special view in which documents must have their aliasOf fields filled in - PRESELEMENT = "preselement",// presentation item (view of a document in a collection) - COLOR = "color", // color picker (view of a color picker for a color string) - YOUTUBE = "youtube", // youtube directory (view of you tube search results) + LINK = "link", + LINKANCHOR = "linkanchor", + IMPORT = "import", + SLIDER = "slider", + PRES = "presentation", + PRESELEMENT = "preselement", + COLOR = "color", + YOUTUBE = "youtube", SEARCHITEM = "searchitem", - COMPARISON = "comparison", // before/after view with slider (view of 2 images) - GROUP = "group", // group of users + COMPARISON = "comparison", + GROUP = "group", - LINKDB = "linkdb", // database of links ??? why do we have this - SCRIPTDB = "scriptdb", // database of scripts - GROUPDB = "groupdb", // database of groups + LINKDB = "linkdb", + SCRIPTDB = "scriptdb", + GROUPDB = "groupdb", - TEXTANCHOR = "textanchor" // selection of text in a text box + TEXTANCHOR = "textanchor" // selection of text in a text box + , } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 24682cbd0..5ec0b0063 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -11,7 +11,7 @@ import { RichTextField } from "../../fields/RichTextField"; import { SchemaHeaderField } from "../../fields/SchemaHeaderField"; import { ComputedField, ScriptField } from "../../fields/ScriptField"; import { Cast, NumCast, StrCast } from "../../fields/Types"; -import { AudioField, ImageField, PdfField, VideoField, WebField, YoutubeField } from "../../fields/URLField"; +import { AudioField, ImageField, MapField, PdfField, VideoField, WebField, YoutubeField } from "../../fields/URLField"; import { SharingPermissions } from "../../fields/util"; import { MessageStore } from "../../server/Message"; import { Upload } from "../../server/SharedMediaTypes"; @@ -60,6 +60,7 @@ import { EquationBox } from "../views/nodes/EquationBox"; import { FunctionPlotBox } from "../views/nodes/FunctionPlotBox"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; import { FieldViewProps } from "../views/nodes/FieldView"; +import { MapBox } from "../views/nodes/MapBox/MapBox"; const path = require('path'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); @@ -362,6 +363,10 @@ export namespace Docs { layout: { view: PDFBox, dataField: defaultDataKey }, options: { _curPage: 1, _fitWidth: true, links: ComputedField.MakeFunction("links(self)") as any } }], + [DocumentType.MAP, { + layout: { view: MapBox, dataField: defaultDataKey }, + options: { _height: 600, _width: 800, links: ComputedField.MakeFunction("links(self)") as any } + }], [DocumentType.IMPORT, { layout: { view: DirectoryImportBox, dataField: defaultDataKey }, options: { _height: 150 } @@ -797,6 +802,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.WEB), new HtmlField(html), options); } + export function MapDocument(initial: List = new List(), options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.MAP), initial, options); + } + export function KVPDocument(document: Doc, options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options }); } @@ -822,7 +831,7 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Linear }, id); } - export function MapDocument(documents: Array, options: DocumentOptions = {}) { + export function MapCollectionDocument(documents: Array, options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Map }); } @@ -1148,7 +1157,11 @@ export namespace DocUtils { } else if (field instanceof List && field[0] instanceof Doc) { created = Docs.Create.StackingDocument(DocListCast(field), resolved); layout = CollectionView.LayoutString; - } else { + } else if (field instanceof MapField) { + created = Docs.Create.MapDocument((field).url.href, resolved); + layout = MapBox.LayoutString; + } + else { created = Docs.Create.TextDocument("", { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved }); layout = FormattedTextBox.LayoutString; } @@ -1179,6 +1192,11 @@ export namespace DocUtils { if (!options._width) options._width = 400; if (!options._height) options._height = (options._width as number) * 1200 / 927; } + if (type.indexOf("map") !== -1) { + ctor = Docs.Create.MapDocument; + if (!options._width) options._width = 800; + if (!options._height) options._height = (options._width as number) * 3 / 4; + } if (type.indexOf("html") !== -1) { if (path.includes(window.location.hostname)) { const s = path.split('/'); @@ -1296,6 +1314,8 @@ export namespace DocUtils { fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options); } else if (doc.data instanceof ImageField) { fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options); + } else if (doc.data instanceof MapField) { + fieldTemplate = Docs.Create.MapDocument("http://www.cs.brown.edu", options); } const docTemplate = docLayoutTemplate || creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) }); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 12733e815..21c4ac110 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -447,6 +447,10 @@ export class CurrentUserUtils { if (doc.emptyWebpage === undefined) { doc.emptyWebpage = Docs.Create.WebDocument("", { title: "webpage", _nativeWidth: 850, isTemplateDoc: true, _height: 512, _width: 400, useCors: true, system: true, cloneFieldFilter: new List(["system"]) }); } + if (doc.emptyMap === undefined) { + doc.emptyMap = Docs.Create.MapDocument(new List(), { title: "google map", _width: 800, _height: 600, system: true, cloneFieldFilter: new List(["system"]) }); + // ((doc.emptyMap as Doc).proto as Doc)["dragFactory-count"] = 0; + } if (doc.activeMobileMenu === undefined) { this.setupActiveMobileMenu(doc); } @@ -466,6 +470,7 @@ export class CurrentUserUtils { { toolTip: "Tap to create a mobile view in a new pane, drag for a mobile view", title: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc }, { toolTip: "Tap to create a custom header note document, drag for a custom header note", title: "Custom", icon: "window-maximize", click: 'openOnRight(delegateDragFactory(this.dragFactory))', drag: 'delegateDragFactory(this.dragFactory)', dragFactory: doc.emptyHeader as Doc }, { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", click: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' }, + { toolTip: "Tap to create a map in the new pane, drag for a map", title: "Map", icon: "map-marker-alt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyMap as Doc, noviceMode: true} ]; } diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d index ac0bea46a..9063dc894 100644 --- a/src/client/util/type_decls.d +++ b/src/client/util/type_decls.d @@ -208,6 +208,7 @@ declare const Docs: { PdfDocument(url: string, options?: DocumentOptions): Doc; WebDocument(url: string, options?: DocumentOptions): Doc; HtmlDocument(html: string, options?: DocumentOptions): Doc; + MapDocument(url: string, options?: DocumentOptions): Doc; KVPDocument(document: Doc, options?: DocumentOptions): Doc; FreeformDocument(documents: Doc[], options?: DocumentOptions): Doc; SchemaDocument(columns: string[], documents: Doc[], options?: DocumentOptions): Doc; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4eeb1fc95..6be298085 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -169,7 +169,7 @@ export class MainView extends React.Component { fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical, fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll, fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines, - fa.faSave, fa.faBookmark); + fa.faSave, fa.faBookmark, fa.faMapMarkedAlt); this.initAuthenticationRouters(); } @@ -180,8 +180,8 @@ export class MainView extends React.Component { const targClass = targets[0].className.toString(); if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { const check = targets.some((thing) => - (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || - thing.className === "collectionSchema-header-menuOptions")); + (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || + thing.className === "collectionSchema-header-menuOptions")); !check && SearchBox.Instance.resetSearch(true); } !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu(); diff --git a/src/client/views/collections/MapView/CollectionMapView.tsx b/src/client/views/collections/MapView/CollectionMapView.tsx index ebf57c0c1..290972364 100644 --- a/src/client/views/collections/MapView/CollectionMapView.tsx +++ b/src/client/views/collections/MapView/CollectionMapView.tsx @@ -52,7 +52,7 @@ export default class CollectionMapView extends CollectionSubView { + private markerClickHandler = (e: MouseEvent, place: LocationData) => { // set which place was clicked this.selectedPlace = place @@ -150,7 +150,7 @@ export default class CollectionMapView extends CollectionSubView { + private handleDragMarker = (marker: any, place: LocationData) => { // if (marker != null) { // place = { // id: place.id, @@ -210,58 +210,58 @@ export default class CollectionMapView extends CollectionSubView - { - allMarkers?.map(place => ( - this.markerClickHandler(e, place.layout)} //?? - draggable={true} - onDragEnd={marker => this.handleDragMarker(marker, place.layout)} - /> - )) - } - {this.infoWindowOpen && selectedMarker && ( - -
-
- {/* the linkmenu as the ones in other nodes */} - - - -
- -
-
-
-
- )} - - - } + // @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 => ( + // this.markerClickHandler(e, place.layout)} //?? + // draggable={true} + // onDragEnd={marker => this.handleDragMarker(marker, place.layout)} + // /> + // )) + // } + // {this.infoWindowOpen && selectedMarker && ( + // + //
+ //
+ // {/* the linkmenu as the ones in other nodes */} + //
+ // a link to another node + //
+ //
+ //
+ // a link to another node + //
+ //
+ //
+ // a link to another node + //
+ //
+ //
+ // + //
+ //
+ //
+ //
+ // )} + + // + // } @action private addMarker = (location: google.maps.LatLng | undefined, map: google.maps.Map) => { @@ -271,18 +271,18 @@ export default class CollectionMapView extends CollectionSubView { - const id = StrCast(marker.id); - const lat = NumCast(marker.lat); - const lng = NumCast(marker.lng); - - return this.markerClickHandler(e, marker)} - /> - } + // @action + // private renderMarkerToMap = (marker: Doc) => { + // const id = StrCast(marker.id); + // const lat = NumCast(marker.lat); + // const lng = NumCast(marker.lng); + + // return this.markerClickHandler(e, marker)} + // /> + // } render() { const { Document, fieldKey, isContentActive: active } = this.props; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index f0a54e4ac..388e6aafe 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -40,6 +40,7 @@ import { VideoBox } from "./VideoBox"; import { WebBox } from "./WebBox"; import React = require("react"); import XRegExp = require("xregexp"); +import { MapBox } from "./MapBox/MapBox"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -224,7 +225,7 @@ export class DocumentContentsView extends React.Component{ case (DocumentType.RTF): return "sticky-note"; case (DocumentType.VID): return "video"; case (DocumentType.WEB): return "globe-asia"; + case (DocumentType.MAP): return "map-marker-alt"; default: return "caret-down"; } } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index bd0ba3ad7..63d491b07 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1177,6 +1177,7 @@ export namespace Doc { case DocumentType.INK: return "pen-nib"; case DocumentType.PDF: return "file-pdf"; case DocumentType.LINK: return "link"; + case DocumentType.MAP: return "map-marker-alt" default: return "question"; } } -- cgit v1.2.3-70-g09d2 From aa67222bc1a80ae11d1a29b32d5cb54199b38011 Mon Sep 17 00:00:00 2001 From: Aubrey-Li <63608597+Aubrey-Li@users.noreply.github.com> Date: Sat, 24 Jul 2021 11:15:04 -0700 Subject: backend issues with creating map node --- deploy/index.html | 2 +- src/client/documents/DocumentTypes.ts | 2 +- src/client/documents/Documents.ts | 4 ++-- src/client/util/CurrentUserUtils.ts | 4 ++-- src/client/views/nodes/PresBox.tsx | 5 +++-- src/fields/Doc.ts | 3 ++- src/fields/URLField.ts | 1 + src/fields/documentSchemas.ts | 2 ++ src/server/ApiManagers/DownloadManager.ts | 2 +- src/server/ApiManagers/SearchManager.ts | 1 + src/server/GarbageCollector.ts | 2 +- src/server/remapUrl.ts | 3 ++- src/server/updateProtos.ts | 2 +- src/server/websocket.ts | 1 + 14 files changed, 21 insertions(+), 13 deletions(-) (limited to 'src/client/views/nodes') diff --git a/deploy/index.html b/deploy/index.html index 33cc0906a..a23cbf869 100644 --- a/deploy/index.html +++ b/deploy/index.html @@ -7,7 +7,7 @@ - + - + -