From 348e794e7ff341a4358be6ed9515fc6ae723092e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 12 Apr 2020 21:36:26 -0700 Subject: rough pass at collection map view --- src/client/views/collections/CollectionMapView.tsx | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/client/views/collections/CollectionMapView.tsx (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx new file mode 100644 index 000000000..49411f61b --- /dev/null +++ b/src/client/views/collections/CollectionMapView.tsx @@ -0,0 +1,72 @@ +import { observer } from "mobx-react"; +import { makeInterface } from "../../../new_fields/Schema"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import React = require("react"); +import { Map, Marker, MapProps, GoogleApiWrapper } from "google-maps-react"; +import { NumCast, StrCast } from "../../../new_fields/Types"; +import { CollectionSubView } from "./CollectionSubView"; +import { Utils } from "../../../Utils"; + +type MapDocument = makeInterface<[typeof documentSchema]>; +const MapDocument = makeInterface(documentSchema); + +export type LocationData = google.maps.LatLngLiteral & { address?: string }; + +@observer +class CollectionMapView extends CollectionSubView & { google: any }>(MapDocument) { + + render() { + const { childLayoutPairs, props } = this; + const { Document } = props; + const center: LocationData = { lat: NumCast(Document.mapCenterLat), lng: NumCast(Document.mapCenterLng) }; + if (!center.lat) { + center.lat = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLat, 0) : 0; + center.lng = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLng, 0) : 0; + } + return ( +
+ + {childLayoutPairs.map(({ layout }) => { + const location: LocationData = { + lat: NumCast(childLayoutPairs[0].layout.locationLat, 0), + lng: NumCast(childLayoutPairs[0].layout.locationLng, 0) + }; + const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45)); + return ( + { + Document.mapCenterLat = location.lat; + Document.mapCenterLng = location.lng; + }} + icon={{ + size: iconSize, + scaledSize: iconSize, + url: StrCast(Document.mapIconUrl, "https://www.pinclipart.com/picdir/middle/359-3598915_map-marker-icon-location-icon-png-clipart.png") + }} + /> + ); + })} + +
+ ); + } + +} + +declare var process: { + env: { + GOOGLE_MAPS_API_KEY: string; + } +}; + +export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS_API_KEY })(CollectionMapView) as any; \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 8143af6ed24b4d3b02e8be306e1dd6fba1e206ce Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 12 Apr 2020 21:41:06 -0700 Subject: clean up --- src/client/views/collections/CollectionMapView.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 49411f61b..6ab152836 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -39,6 +39,7 @@ class CollectionMapView extends CollectionSubView lng: NumCast(childLayoutPairs[0].layout.locationLng, 0) }; const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45)); + return ( icon={{ size: iconSize, scaledSize: iconSize, - url: StrCast(Document.mapIconUrl, "https://www.pinclipart.com/picdir/middle/359-3598915_map-marker-icon-location-icon-png-clipart.png") + url: StrCast(Document.mapIconUrl, null) }} /> ); -- cgit v1.2.3-70-g09d2 From e3a5dc3ce59b1d8f2dde63395505061b304d64c0 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 13 Apr 2020 00:03:13 -0700 Subject: completed migration to webpack-transferred environment variables, rather than a server route --- src/Utils.ts | 5 ----- src/client/Network.ts | 13 ------------- src/client/cognitive_services/CognitiveServices.ts | 2 +- src/client/views/collections/CollectionMapView.tsx | 8 +------- src/server/ApiManagers/UtilManager.ts | 13 ------------- webpack.config.js | 3 +-- 6 files changed, 3 insertions(+), 41 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index e3ec10dcd..a8cde0624 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -63,11 +63,6 @@ export namespace Utils { return prepend("/corsProxy/") + encodeURIComponent(url); } - export async function getApiKey(target: string): Promise { - const response = await fetch(prepend(`/environment/${target.toUpperCase()}`)); - return response.text(); - } - export function CopyText(text: string) { const textArea = document.createElement("textarea"); textArea.value = text; diff --git a/src/client/Network.ts b/src/client/Network.ts index bd0e6e61a..6982ecf19 100644 --- a/src/client/Network.ts +++ b/src/client/Network.ts @@ -4,23 +4,10 @@ import { Upload } from "../server/SharedMediaTypes"; export namespace Networking { - const EnvVarCache = new Map(); - export async function FetchFromServer(relativeRoute: string) { return (await fetch(relativeRoute)).text(); } - export async function FetchEnvironmentVariable(varNameLiteral: string) { - let resolved = EnvVarCache.get(varNameLiteral); - if (!resolved) { - resolved = await FetchFromServer(`/environment/${varNameLiteral}`); - if (resolved !== undefined) { - EnvVarCache.set(varNameLiteral, resolved); - } - } - return resolved; - } - export async function PostToServer(relativeRoute: string, body?: any) { const options = { uri: Utils.prepend(relativeRoute), diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index 3133bf4b1..8c63ae906 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -45,7 +45,7 @@ export enum Confidence { export namespace CognitiveServices { const ExecuteQuery = async (service: Service, manager: APIManager, data: D): Promise => { - const apiKey = await Utils.getApiKey(service); + const apiKey = process.env[service.toUpperCase()]; if (!apiKey) { console.log(`No API key found for ${service}: ensure index.ts has access to a .env file in your root directory.`); return undefined; diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 6ab152836..a99d5be50 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -64,10 +64,4 @@ class CollectionMapView extends CollectionSubView } -declare var process: { - env: { - GOOGLE_MAPS_API_KEY: string; - } -}; - -export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS_API_KEY })(CollectionMapView) as any; \ No newline at end of file +export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS_API_KEY! })(CollectionMapView) as any; \ No newline at end of file diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts index ad8119bf4..aec523cd0 100644 --- a/src/server/ApiManagers/UtilManager.ts +++ b/src/server/ApiManagers/UtilManager.ts @@ -14,19 +14,6 @@ export default class UtilManager extends ApiManager { protected initialize(register: Registration): void { - register({ - method: Method.GET, - subscription: new RouteSubscriber("environment").add("key"), - secureHandler: ({ req, res }) => { - const { key } = req.params; - const value = process.env[key]; - if (!value) { - console.log(red(`process.env.${key} is not defined.`)); - } - return res.send(value); - } - }); - // register({ // method: Method.POST, // subscription: "/IBMAnalysis", diff --git a/webpack.config.js b/webpack.config.js index 9225093be..c8ef269d4 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -20,8 +20,7 @@ const env = require('dotenv').config().parsed; if (env) { plugins.push(new webpack.DefinePlugin(Object.keys(env).reduce((prev, next) => { if (next.startsWith("DASH_")) { - const resolved = next.replace("DASH_", ""); - prev[`process.env.${resolved}`] = JSON.stringify(env[next]); + prev[`process.env.${next.replace("DASH_", "")}`] = JSON.stringify(env[next]); } return prev; }, {}))); -- cgit v1.2.3-70-g09d2 From bf622aa5b5cd9d3256ee8e4f26245b9858cccfba Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 13 Apr 2020 00:56:21 -0700 Subject: final env cleanup --- src/client/views/collections/CollectionMapView.tsx | 20 +++++++++++-------- src/server/server_Initialization.ts | 1 - webpack.config.js | 23 ++++++++++++++-------- 3 files changed, 27 insertions(+), 17 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index a99d5be50..b67daeb53 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -6,6 +6,7 @@ import { Map, Marker, MapProps, GoogleApiWrapper } from "google-maps-react"; import { NumCast, StrCast } from "../../../new_fields/Types"; import { CollectionSubView } from "./CollectionSubView"; import { Utils } from "../../../Utils"; +import { Opt } from "../../../new_fields/Doc"; type MapDocument = makeInterface<[typeof documentSchema]>; const MapDocument = makeInterface(documentSchema); @@ -38,8 +39,15 @@ class CollectionMapView extends CollectionSubView lat: NumCast(childLayoutPairs[0].layout.locationLat, 0), lng: NumCast(childLayoutPairs[0].layout.locationLng, 0) }; - const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45)); - + let icon: Opt, iconUrl: Opt; + if ((iconUrl = StrCast(Document.mapIconUrl, null))) { + const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45)); + icon = { + size: iconSize, + scaledSize: iconSize, + url: iconUrl + }; + } return ( Document.mapCenterLat = location.lat; Document.mapCenterLng = location.lng; }} - icon={{ - size: iconSize, - scaledSize: iconSize, - url: StrCast(Document.mapIconUrl, null) - }} + icon={icon} /> ); })} @@ -64,4 +68,4 @@ class CollectionMapView extends CollectionSubView } -export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS_API_KEY! })(CollectionMapView) as any; \ No newline at end of file +export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS! })(CollectionMapView) as any; \ No newline at end of file diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 1150118f7..add607761 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -20,7 +20,6 @@ import * as request from 'request'; import RouteSubscriber from './RouteSubscriber'; import { publicDirectory } from '.'; import { logPort, } from './ActionUtilities'; -import { Utils } from '../Utils'; import { blue, yellow } from 'colors'; import * as cors from "cors"; diff --git a/webpack.config.js b/webpack.config.js index c8ef269d4..6265883fd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -16,16 +16,23 @@ const plugins = [ new webpack.HotModuleReplacementPlugin(), ]; -const env = require('dotenv').config().parsed; -if (env) { - plugins.push(new webpack.DefinePlugin(Object.keys(env).reduce((prev, next) => { - if (next.startsWith("DASH_")) { - prev[`process.env.${next.replace("DASH_", "")}`] = JSON.stringify(env[next]); - } - return prev; - }, {}))); +const dotenv = require('dotenv'); + +function transferEnvironmentVariables() { + const prefix = "_CLIENT_"; + const env = dotenv.config().parsed; + if (env) { + plugins.push(new webpack.DefinePlugin(Object.keys(env).reduce((mapping, envKey) => { + if (envKey.startsWith(prefix)) { + mapping[`process.env.${envKey.replace(prefix, "")}`] = JSON.stringify(env[envKey]); + } + return mapping; + }, {}))); + } } +transferEnvironmentVariables(); + module.exports = { mode: 'development', entry: { -- cgit v1.2.3-70-g09d2 From 87268612b9b765d74f1a5317b0894be0ceb1dfd1 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 13 Apr 2020 16:43:50 -0400 Subject: fixed map view pointer events. --- src/client/views/collections/CollectionMapView.scss | 3 +++ src/client/views/collections/CollectionMapView.tsx | 8 ++++---- src/client/views/collections/CollectionView.tsx | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss index c74433902..df7853da6 100644 --- a/src/client/views/collections/CollectionMapView.scss +++ b/src/client/views/collections/CollectionMapView.scss @@ -1,4 +1,7 @@ .collectionMapView-contents { width: 100%; height: 100%; +} +.collectionMapView-contents-none { + pointer-events: none; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index b67daeb53..5075bbf7a 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -7,6 +7,7 @@ import { NumCast, StrCast } from "../../../new_fields/Types"; import { CollectionSubView } from "./CollectionSubView"; import { Utils } from "../../../Utils"; import { Opt } from "../../../new_fields/Doc"; +import "./CollectionMapView.scss"; type MapDocument = makeInterface<[typeof documentSchema]>; const MapDocument = makeInterface(documentSchema); @@ -25,11 +26,10 @@ class CollectionMapView extends CollectionSubView center.lng = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLng, 0) : 0; } return ( -
+
(this.props.active() && e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > { return viewField as any as CollectionViewType; } - active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0; + active = (outsideReaction?: boolean) => (this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0) ? true : false; whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); -- cgit v1.2.3-70-g09d2 From 78986ae808dc9bbb5763e3f74097b7a1bc61f49a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 13 Apr 2020 18:45:52 -0400 Subject: more mapview adjustments --- src/client/documents/Documents.ts | 4 - src/client/views/PreviewCursor.tsx | 2 +- .../views/collections/CollectionMapView.scss | 3 - src/client/views/collections/CollectionMapView.tsx | 104 ++++++++++++++------- 4 files changed, 69 insertions(+), 44 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 3f46c4013..e6f3b21ca 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -49,10 +49,6 @@ import { ContextMenuProps } from "../views/ContextMenuItem"; import { ContextMenu } from "../views/ContextMenu"; import { LinkBox } from "../views/nodes/LinkBox"; import { ScreenshotBox } from "../views/nodes/ScreenshotBox"; -import CollectionMapView from "../views/collections/CollectionMapView"; -import LocationField, { LocationData } from "../../new_fields/LocationField"; -import { action } from "mobx"; -const requestImageSize = require('../util/request-image-size'); const path = require('path'); export interface DocumentOptions { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 92ba13d2f..df30c1215 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -113,7 +113,7 @@ export class PreviewCursor extends React.Component<{}> { addLiveText: (doc: Doc) => void, getTransform: () => Transform, addDocument: (doc: Doc) => boolean, - nudge: (nudgeX: number, nudgeY: number) => void) { + nudge: (nudgeX: number, nudgeY: number) => boolean) { this._clickPoint = [x, y]; this._onKeyPress = onKeyPress; this._addLiveTextDoc = addLiveText; diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss index df7853da6..c74433902 100644 --- a/src/client/views/collections/CollectionMapView.scss +++ b/src/client/views/collections/CollectionMapView.scss @@ -1,7 +1,4 @@ .collectionMapView-contents { width: 100%; height: 100%; -} -.collectionMapView-contents-none { - pointer-events: none; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 5075bbf7a..569f8ba7a 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -1,13 +1,20 @@ +import { GoogleApiWrapper, Map, MapProps, Marker } from "google-maps-react"; import { observer } from "mobx-react"; -import { makeInterface } from "../../../new_fields/Schema"; +import { Doc, Opt, DocListCast } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; -import React = require("react"); -import { Map, Marker, MapProps, GoogleApiWrapper } from "google-maps-react"; -import { NumCast, StrCast } from "../../../new_fields/Types"; -import { CollectionSubView } from "./CollectionSubView"; -import { Utils } from "../../../Utils"; -import { Opt } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { makeInterface } from "../../../new_fields/Schema"; +import { Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types"; +import { TraceMobx } from "../../../new_fields/util"; import "./CollectionMapView.scss"; +import { CollectionSubView } from "./CollectionSubView"; +import React = require("react"); +import { DocumentManager } from "../../util/DocumentManager"; +import { UndoManager } from "../../util/UndoManager"; +import { returnTrue } from "../../../Utils"; +import { CancellationError } from "bluebird"; +import { ln } from "shelljs"; +import { dfareporting } from "googleapis/build/src/apis/dfareporting"; type MapDocument = makeInterface<[typeof documentSchema]>; const MapDocument = makeInterface(documentSchema); @@ -17,28 +24,65 @@ export type LocationData = google.maps.LatLngLiteral & { address?: string }; @observer class CollectionMapView extends CollectionSubView & { google: any }>(MapDocument) { + getLocation = (doc: Opt, fieldKey: string, defaultLocation?: LocationData) => { + if (doc) { + let lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null); + let lng: Opt = Cast(doc[fieldKey + "-lng"], "number", null); + const address = Cast(doc[fieldKey + "-address"], "string", null); + if (address) { + // use geo service to convert to lat/lng + lat = lat; + lng = lng; + } + if (lat === undefined) lat = defaultLocation?.lat; + if (lng === undefined) lng = defaultLocation?.lng; + return ({ lat, lng }); + } + return ({ lat: 35.1592238, lng: -98.4466577 }); + } + renderMarker(layout: Doc, icon: Opt) { + const location = this.getLocation(layout, "location"); + return location.lat === undefined || location.lng === undefined ? (null) : + { + this.props.Document.mapCenterLat = location.lat; + this.props.Document.mapCenterLng = location.lng; + if (layout.isLinkButton && DocListCast(layout.links).length) { + const batch = UndoManager.StartBatch("follow link click"); + await DocumentManager.Instance.FollowLink(undefined, layout, (doc: Doc, where: string, finished?: () => void) => { + this.props.addDocTab(doc, where); + finished?.(); + }, false, this.props.ContainingCollectionDoc, batch.end, undefined); + } else { + ScriptCast(layout.onClick)?.script.run({ this: layout, self: Cast(layout.rootDocument, Doc, null) || layout }); + } + }} + icon={icon} + />; + } render() { - const { childLayoutPairs, props } = this; - const { Document } = props; - const center: LocationData = { lat: NumCast(Document.mapCenterLat), lng: NumCast(Document.mapCenterLng) }; - if (!center.lat) { - center.lat = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLat, 0) : 0; - center.lng = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLng, 0) : 0; + const { childLayoutPairs } = this; + const { Document } = this.props; + let center = this.getLocation(Document, this.props.fieldKey + "-mapCenter"); + if (center.lat === undefined) { + center = this.getLocation(childLayoutPairs.map(pair => pair.layout).find(returnTrue), "location", { lat: 35.1592238, lng: -98.4466577 }); } - return ( -
(this.props.active() && e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > + TraceMobx(); + return center.lat === undefined || center.lng === undefined ? (null) : +
e.stopPropagation()} + onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > {childLayoutPairs.map(({ layout }) => { - const location: LocationData = { - lat: NumCast(childLayoutPairs[0].layout.locationLat, 0), - lng: NumCast(childLayoutPairs[0].layout.locationLng, 0) - }; let icon: Opt, iconUrl: Opt; if ((iconUrl = StrCast(Document.mapIconUrl, null))) { const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45)); @@ -48,22 +92,10 @@ class CollectionMapView extends CollectionSubView url: iconUrl }; } - return ( - { - Document.mapCenterLat = location.lat; - Document.mapCenterLng = location.lng; - }} - icon={icon} - /> - ); + return this.renderMarker(layout, icon); })} -
- ); +
; } } -- cgit v1.2.3-70-g09d2 From 479964e7c13f7b9b1102b36575ad8f4cc8dc00c2 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 13 Apr 2020 21:00:50 -0400 Subject: cleaned up some field key stuff for mapview --- src/client/views/collections/CollectionMapView.tsx | 87 ++++++++++++---------- 1 file changed, 47 insertions(+), 40 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 569f8ba7a..44bb22827 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -11,10 +11,6 @@ import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); import { DocumentManager } from "../../util/DocumentManager"; import { UndoManager } from "../../util/UndoManager"; -import { returnTrue } from "../../../Utils"; -import { CancellationError } from "bluebird"; -import { ln } from "shelljs"; -import { dfareporting } from "googleapis/build/src/apis/dfareporting"; type MapDocument = makeInterface<[typeof documentSchema]>; const MapDocument = makeInterface(documentSchema); @@ -24,32 +20,33 @@ export type LocationData = google.maps.LatLngLiteral & { address?: string }; @observer class CollectionMapView extends CollectionSubView & { google: any }>(MapDocument) { - getLocation = (doc: Opt, fieldKey: string, defaultLocation?: LocationData) => { + getLocation = (doc: Opt, fieldKey: string) => { if (doc) { let lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null); let lng: Opt = Cast(doc[fieldKey + "-lng"], "number", null); + let zoom: Opt = Cast(doc[fieldKey + "-zoom"], "number", null); const address = Cast(doc[fieldKey + "-address"], "string", null); if (address) { // use geo service to convert to lat/lng lat = lat; lng = lng; } - if (lat === undefined) lat = defaultLocation?.lat; - if (lng === undefined) lng = defaultLocation?.lng; - return ({ lat, lng }); + return lat !== undefined && lng !== undefined ? ({ lat, lng, zoom }) : undefined; } - return ({ lat: 35.1592238, lng: -98.4466577 }); + return undefined; } renderMarker(layout: Doc, icon: Opt) { - const location = this.getLocation(layout, "location"); - return location.lat === undefined || location.lng === undefined ? (null) : + const location = this.getLocation(layout, "mapLocation"); + return !location ? (null) : { - this.props.Document.mapCenterLat = location.lat; - this.props.Document.mapCenterLng = location.lng; + this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = 0; + this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = location.lat; + this.layoutDoc[this.props.fieldKey + "-mapCenter-lng"] = location.lng; + location.zoom && (this.layoutDoc[this.props.fieldKey + "-mapCenter-zoom"] = location.zoom); if (layout.isLinkButton && DocListCast(layout.links).length) { const batch = UndoManager.StartBatch("follow link click"); await DocumentManager.Instance.FollowLink(undefined, layout, (doc: Doc, where: string, finished?: () => void) => { @@ -67,35 +64,45 @@ class CollectionMapView extends CollectionSubView const { childLayoutPairs } = this; const { Document } = this.props; let center = this.getLocation(Document, this.props.fieldKey + "-mapCenter"); - if (center.lat === undefined) { - center = this.getLocation(childLayoutPairs.map(pair => pair.layout).find(returnTrue), "location", { lat: 35.1592238, lng: -98.4466577 }); + if (center === undefined) { + center = childLayoutPairs.map(pair => this.getLocation(pair.layout, "mapLocation")).find(layout => layout); + if (center === undefined) { + center = { lat: 35.1592238, lng: -98.444512, zoom: 15 }; // nowhere, OK + } } TraceMobx(); - return center.lat === undefined || center.lng === undefined ? (null) : -
e.stopPropagation()} - onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > - - {childLayoutPairs.map(({ layout }) => { - let icon: Opt, iconUrl: Opt; - if ((iconUrl = StrCast(Document.mapIconUrl, null))) { - const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45)); - icon = { - size: iconSize, - scaledSize: iconSize, - url: iconUrl - }; - } - return this.renderMarker(layout, icon); - })} - -
; + return
e.stopPropagation()} + onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > + console.log(e)} + onRecenter={e => console.log(e)} + onDragend={(centerMoved, center) => console.log(centerMoved, center)} + onProjectionChanged={e => console.log(e)} + onCenterChanged={(e => { + Document[this.props.fieldKey + "-mapCenter-lat"] = typeof e?.center?.lat === "number" ? e.center.lat : center!.lat; + Document[this.props.fieldKey + "-mapCenter-lng"] = typeof e?.center?.lng === "number" ? e.center.lng : center!.lng; + })} + > + {childLayoutPairs.map(({ layout }) => { + let icon: Opt, iconUrl: Opt; + if ((iconUrl = StrCast(Document.mapIconUrl, null))) { + const iconSize = new google.maps.Size(NumCast(layout["mapLocation-iconWidth"], 45), NumCast(layout["mapLocation-iconHeight"], 45)); + icon = { + size: iconSize, + scaledSize: iconSize, + url: iconUrl + }; + } + return this.renderMarker(layout, icon); + })} + +
; } } -- cgit v1.2.3-70-g09d2 From 14b3f6b3580b1987bdf9f8f865a79087e801d367 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 13 Apr 2020 21:10:10 -0400 Subject: fromlast --- src/client/views/collections/CollectionMapView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 44bb22827..2bf3d7c32 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -82,7 +82,7 @@ class CollectionMapView extends CollectionSubView center={center} onBoundsChanged={e => console.log(e)} onRecenter={e => console.log(e)} - onDragend={(centerMoved, center) => console.log(centerMoved, center)} + onDragend={e => console.log(e)} onProjectionChanged={e => console.log(e)} onCenterChanged={(e => { Document[this.props.fieldKey + "-mapCenter-lat"] = typeof e?.center?.lat === "number" ? e.center.lat : center!.lat; -- cgit v1.2.3-70-g09d2 From a888dacc8e6a6400d52cdded0015e05ac5581d3d Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 14 Apr 2020 00:31:20 -0700 Subject: chrome dropdown changes and custom loading container for mapview --- .../views/collections/CollectionMapView.scss | 18 +++++++++++++ src/client/views/collections/CollectionMapView.tsx | 31 +++++++++++++--------- .../views/collections/CollectionViewChromes.tsx | 18 ++++++------- 3 files changed, 46 insertions(+), 21 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss index c74433902..4956ad946 100644 --- a/src/client/views/collections/CollectionMapView.scss +++ b/src/client/views/collections/CollectionMapView.scss @@ -1,4 +1,22 @@ .collectionMapView-contents { width: 100%; height: 100%; +} + +.loadingWrapper { + width: 100%; + height: 100%; + background-color: yellow; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + + .loadingGif { + align-self: center; + justify-self: center; + width: 20%; + height: 20% + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 44bb22827..6d5dcdf1d 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -11,20 +11,21 @@ import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); import { DocumentManager } from "../../util/DocumentManager"; import { UndoManager } from "../../util/UndoManager"; +import * as ReactDOM from 'react-dom'; -type MapDocument = makeInterface<[typeof documentSchema]>; -const MapDocument = makeInterface(documentSchema); +type MapSchema = makeInterface<[typeof documentSchema]>; +const MapSchema = makeInterface(documentSchema); export type LocationData = google.maps.LatLngLiteral & { address?: string }; @observer -class CollectionMapView extends CollectionSubView & { google: any }>(MapDocument) { +class CollectionMapView extends CollectionSubView & { google: any }>(MapSchema) { getLocation = (doc: Opt, fieldKey: string) => { if (doc) { let lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null); let lng: Opt = Cast(doc[fieldKey + "-lng"], "number", null); - let zoom: Opt = Cast(doc[fieldKey + "-zoom"], "number", null); + const zoom: Opt = Cast(doc[fieldKey + "-zoom"], "number", null); const address = Cast(doc[fieldKey + "-address"], "string", null); if (address) { // use geo service to convert to lat/lng @@ -79,12 +80,12 @@ class CollectionMapView extends CollectionSubView google={this.props.google} zoom={center.zoom || 10} initialCenter={center} - center={center} - onBoundsChanged={e => console.log(e)} - onRecenter={e => console.log(e)} - onDragend={(centerMoved, center) => console.log(centerMoved, center)} - onProjectionChanged={e => console.log(e)} - onCenterChanged={(e => { + onBoundsChanged={(props, map, e) => console.log("ON_BOUNDS_CHANGED", props, map, e)} + onRecenter={(props, map, e) => console.log("ON_RECENTER", props, map, e)} + onDragend={(centerMoved, center) => console.log("ON_DRAGEND", centerMoved, center)} + onProjectionChanged={(props, map, e) => console.log("ON_PROJ_CHANGED", props, map, e)} + onCenterChanged={((props, map, e) => { + console.log("ON_CENTER_CHANGED", props, map, e); Document[this.props.fieldKey + "-mapCenter-lat"] = typeof e?.center?.lat === "number" ? e.center.lat : center!.lat; Document[this.props.fieldKey + "-mapCenter-lng"] = typeof e?.center?.lng === "number" ? e.center.lng : center!.lng; })} @@ -92,7 +93,9 @@ class CollectionMapView extends CollectionSubView {childLayoutPairs.map(({ layout }) => { let icon: Opt, iconUrl: Opt; if ((iconUrl = StrCast(Document.mapIconUrl, null))) { - const iconSize = new google.maps.Size(NumCast(layout["mapLocation-iconWidth"], 45), NumCast(layout["mapLocation-iconHeight"], 45)); + const iconWidth = NumCast(layout["mapLocation-iconWidth"], 45); + const iconHeight = NumCast(layout["mapLocation-iconHeight"], 45); + const iconSize = new google.maps.Size(iconWidth, iconHeight); icon = { size: iconSize, scaledSize: iconSize, @@ -107,4 +110,8 @@ class CollectionMapView extends CollectionSubView } -export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS! })(CollectionMapView) as any; \ No newline at end of file +const LoadingContainer = () => { + return
; +}; + +export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS!, LoadingContainer })(CollectionMapView) as any; \ No newline at end of file diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index ba95dce00..0940e9186 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -402,15 +402,15 @@ export class CollectionViewBaseChrome extends React.Component - - - - - - - - - + {Object.values(CollectionViewType).map(type => ["invalid", "docking"].includes(type) ? (null) : ( + + ))}
-- cgit v1.2.3-70-g09d2 From 8a537327fb685fa9267e25e550ec0aa7a3ae86cc Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 14 Apr 2020 04:01:24 -0700 Subject: added bidirectional geocoding for map view --- src/client/views/collections/CollectionMapView.tsx | 128 +++++++++++++++------ webpack.config.js | 64 +++++------ 2 files changed, 126 insertions(+), 66 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index a2d3c328d..8cdc145b8 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -4,37 +4,44 @@ import { Doc, Opt, DocListCast } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; import { Id } from "../../../new_fields/FieldSymbols"; import { makeInterface } from "../../../new_fields/Schema"; -import { Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types"; +import { Cast, NumCast, ScriptCast, StrCast, BoolCast } from "../../../new_fields/Types"; import { TraceMobx } from "../../../new_fields/util"; import "./CollectionMapView.scss"; import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); import { DocumentManager } from "../../util/DocumentManager"; import { UndoManager } from "../../util/UndoManager"; +import { IReactionDisposer, reaction } from "mobx"; +import requestPromise = require("request-promise"); type MapSchema = makeInterface<[typeof documentSchema]>; const MapSchema = makeInterface(documentSchema); -export type LocationData = google.maps.LatLngLiteral & { address?: string }; +export type LocationData = google.maps.LatLngLiteral & { + address?: string + resolvedAddress?: string; + zoom?: number; +}; + +const base = "https://maps.googleapis.com/maps/api/geocode/json?"; @observer class CollectionMapView extends CollectionSubView & { google: any }>(MapSchema) { - getLocation = (doc: Opt, fieldKey: string) => { + private mapRef = React.createRef(); + private addressUpdaters: IReactionDisposer[] = []; + private latlngUpdaters: IReactionDisposer[] = []; + + getLocation = (doc: Opt, fieldKey: string): Opt => { if (doc) { - let lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null); - let lng: Opt = Cast(doc[fieldKey + "-lng"], "number", null); + const lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null); + const lng: Opt = Cast(doc[fieldKey + "-lng"], "number", null); const zoom: Opt = Cast(doc[fieldKey + "-zoom"], "number", null); - const address = Cast(doc[fieldKey + "-address"], "string", null); - if (address) { - // use geo service to convert to lat/lng - lat = lat; - lng = lng; - } return lat !== undefined && lng !== undefined ? ({ lat, lng, zoom }) : undefined; } return undefined; } + renderMarker(layout: Doc, icon: Opt) { const location = this.getLocation(layout, "mapLocation"); return !location ? (null) : @@ -43,6 +50,7 @@ class CollectionMapView extends CollectionSubView & label={StrCast(layout.title)} position={{ lat: location.lat, lng: location.lng }} onClick={async () => { + this.map.panTo(location); this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = 0; this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = location.lat; this.layoutDoc[this.props.fieldKey + "-mapCenter-lng"] = location.lng; @@ -60,6 +68,73 @@ class CollectionMapView extends CollectionSubView & icon={icon} />; } + + private get contents() { + this.addressUpdaters.forEach(disposer => disposer()); + this.addressUpdaters = []; + this.latlngUpdaters.forEach(disposer => disposer()); + this.latlngUpdaters = []; + return this.childLayoutPairs.map(({ layout }) => { + let icon: Opt, iconUrl: Opt; + if ((iconUrl = StrCast(this.props.Document.mapIconUrl, null))) { + const iconWidth = NumCast(layout["mapLocation-iconWidth"], 45); + const iconHeight = NumCast(layout["mapLocation-iconHeight"], 45); + const iconSize = new google.maps.Size(iconWidth, iconHeight); + icon = { + size: iconSize, + scaledSize: iconSize, + url: iconUrl + }; + } + this.addressUpdaters.push(reaction( + () => ({ + lat: NumCast(layout["mapLocation-lat"]), + lng: NumCast(layout["mapLocation-lng"]) + }), + ({ lat, lng }) => { + if (!BoolCast(layout._ignoreNextUpdate)) { + if (lat !== undefined && lng !== undefined) { + const target = `${base}latlng=${lat},${lng}&key=${process.env.GOOGLE_MAPS_GEO!}`; + requestPromise.get(target).then(res => { + layout._ignoreNextUpdate = true; + layout["mapLocation-address"] = JSON.parse(res).results[0]?.formatted_address || ""; + }); + } + } else { + layout._ignoreNextUpdate = false; + } + } + )); + this.latlngUpdaters.push(reaction( + () => ({ address: Cast(layout["mapLocation-address"], "string", null) }), + ({ address }) => { + if (!BoolCast(layout._ignoreNextUpdate)) { + if (address && address.length) { + const target = `${base}address=${address.replace(/\s+/g, "+")}&key=${process.env.GOOGLE_MAPS_GEO!}`; + requestPromise.get(target).then(res => { + const result = JSON.parse(res).results[0]; + const { lat, lng } = result.geometry.location; + layout._ignoreNextUpdate = true; + layout["mapLocation-lat"] = lat; + layout._ignoreNextUpdate = true; + layout["mapLocation-lng"] = lng; + layout._ignoreNextUpdate = true; + layout["mapLocation-address"] = result.formatted_address; + }); + } + } else { + layout._ignoreNextUpdate = false; + } + } + )); + return this.renderMarker(layout, icon); + }); + } + + private get map() { + return (this.mapRef.current as any).map; + } + render() { const { childLayoutPairs } = this; const { Document } = this.props; @@ -76,33 +151,18 @@ class CollectionMapView extends CollectionSubView & onWheel={e => e.stopPropagation()} onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > console.log("ON_BOUNDS_CHANGED", props, map, e)} - onRecenter={(props, map, e) => console.log("ON_RECENTER", props, map, e)} - onDragend={(centerMoved, center) => console.log("ON_DRAGEND", centerMoved, center)} - onProjectionChanged={(props, map, e) => console.log("ON_PROJ_CHANGED", props, map, e)} - onCenterChanged={((props, map, e) => { - console.log("ON_CENTER_CHANGED", props, map, e); - Document[this.props.fieldKey + "-mapCenter-lat"] = typeof e?.center?.lat === "number" ? e.center.lat : center!.lat; - Document[this.props.fieldKey + "-mapCenter-lng"] = typeof e?.center?.lng === "number" ? e.center.lng : center!.lng; - })} + center={center} + onDragend={() => { + const { center } = this.map; + Document[this.props.fieldKey + "-mapCenter-lat"] = center.lat(); + Document[this.props.fieldKey + "-mapCenter-lng"] = center.lng(); + }} > - {childLayoutPairs.map(({ layout }) => { - let icon: Opt, iconUrl: Opt; - if ((iconUrl = StrCast(Document.mapIconUrl, null))) { - const iconWidth = NumCast(layout["mapLocation-iconWidth"], 45); - const iconHeight = NumCast(layout["mapLocation-iconHeight"], 45); - const iconSize = new google.maps.Size(iconWidth, iconHeight); - icon = { - size: iconSize, - scaledSize: iconSize, - url: iconUrl - }; - } - return this.renderMarker(layout, icon); - })} + {this.contents} ; } diff --git a/webpack.config.js b/webpack.config.js index 1027f29a6..6265883fd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -20,7 +20,7 @@ const dotenv = require('dotenv'); function transferEnvironmentVariables() { const prefix = "_CLIENT_"; - const env = dotenv.config({ debug: true }).parsed; + const env = dotenv.config().parsed; if (env) { plugins.push(new webpack.DefinePlugin(Object.keys(env).reduce((mapping, envKey) => { if (envKey.startsWith(prefix)) { @@ -64,42 +64,42 @@ module.exports = { }, module: { rules: [{ - test: [/\.tsx?$/], - use: [{ - loader: 'ts-loader', - options: { - transpileOnly: true - } - }] - }, - { - test: /\.scss|css$/, - use: [{ - loader: "style-loader" + test: [/\.tsx?$/], + use: [{ + loader: 'ts-loader', + options: { + transpileOnly: true + } + }] }, { - loader: "css-loader" + test: /\.scss|css$/, + use: [{ + loader: "style-loader" + }, + { + loader: "css-loader" + }, + { + loader: "sass-loader" + } + ] }, { - loader: "sass-loader" + test: /\.(jpg|png|pdf)$/, + use: [{ + loader: 'file-loader' + }] + }, + { + test: /\.(png|jpg|gif)$/i, + use: [{ + loader: 'url-loader', + options: { + limit: 8192 + } + }] } - ] - }, - { - test: /\.(jpg|png|pdf)$/, - use: [{ - loader: 'file-loader' - }] - }, - { - test: /\.(png|jpg|gif)$/i, - use: [{ - loader: 'url-loader', - options: { - limit: 8192 - } - }] - } ] }, plugins, -- cgit v1.2.3-70-g09d2 From f29782b8cde4a5b0711f619d1bd7c4e223c900b9 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 14 Apr 2020 09:46:40 -0400 Subject: update maps to use local variables not on Doc --- src/client/views/collections/CollectionMapView.tsx | 71 ++++++++++++---------- 1 file changed, 38 insertions(+), 33 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 8cdc145b8..5d0b0c982 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -1,4 +1,4 @@ -import { GoogleApiWrapper, Map, MapProps, Marker } from "google-maps-react"; +import { GoogleApiWrapper, Map as GeoMap, MapProps, Marker } from "google-maps-react"; import { observer } from "mobx-react"; import { Doc, Opt, DocListCast } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; @@ -11,7 +11,7 @@ import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); import { DocumentManager } from "../../util/DocumentManager"; import { UndoManager } from "../../util/UndoManager"; -import { IReactionDisposer, reaction } from "mobx"; +import { IReactionDisposer, reaction, action } from "mobx"; import requestPromise = require("request-promise"); type MapSchema = makeInterface<[typeof documentSchema]>; @@ -28,7 +28,7 @@ const base = "https://maps.googleapis.com/maps/api/geocode/json?"; @observer class CollectionMapView extends CollectionSubView & { google: any }>(MapSchema) { - private mapRef = React.createRef(); + private mapRef = React.createRef(); private addressUpdaters: IReactionDisposer[] = []; private latlngUpdaters: IReactionDisposer[] = []; @@ -51,7 +51,6 @@ class CollectionMapView extends CollectionSubView & position={{ lat: location.lat, lng: location.lng }} onClick={async () => { this.map.panTo(location); - this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = 0; this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = location.lat; this.layoutDoc[this.props.fieldKey + "-mapCenter-lng"] = location.lng; location.zoom && (this.layoutDoc[this.props.fieldKey + "-mapCenter-zoom"] = location.zoom); @@ -69,12 +68,14 @@ class CollectionMapView extends CollectionSubView & />; } + _cancelAddrReq = new Map(); + _cancelLocReq = new Map(); private get contents() { this.addressUpdaters.forEach(disposer => disposer()); this.addressUpdaters = []; this.latlngUpdaters.forEach(disposer => disposer()); this.latlngUpdaters = []; - return this.childLayoutPairs.map(({ layout }) => { + return this.childLayoutPairs.map(({ layout, data }) => { let icon: Opt, iconUrl: Opt; if ((iconUrl = StrCast(this.props.Document.mapIconUrl, null))) { const iconWidth = NumCast(layout["mapLocation-iconWidth"], 45); @@ -92,38 +93,42 @@ class CollectionMapView extends CollectionSubView & lng: NumCast(layout["mapLocation-lng"]) }), ({ lat, lng }) => { - if (!BoolCast(layout._ignoreNextUpdate)) { - if (lat !== undefined && lng !== undefined) { - const target = `${base}latlng=${lat},${lng}&key=${process.env.GOOGLE_MAPS_GEO!}`; - requestPromise.get(target).then(res => { - layout._ignoreNextUpdate = true; - layout["mapLocation-address"] = JSON.parse(res).results[0]?.formatted_address || ""; - }); - } - } else { - layout._ignoreNextUpdate = false; + if (this._cancelLocReq.get(layout[Id])) { + this._cancelLocReq.set(layout[Id], false); + } + else if (lat !== undefined && lng !== undefined) { + const target = `${base}latlng=${lat},${lng}&key=${process.env.GOOGLE_MAPS_GEO!}`; + requestPromise.get(target).then(res => { + const formatted_address = JSON.parse(res).results[0].formatted_address || ""; + if (formatted_address !== layout["mapLocation-address"]) { + this._cancelAddrReq.set(layout[Id], true); + Doc.SetInPlace(layout, "mapLocation-address", formatted_address, true); + } + }); } } )); this.latlngUpdaters.push(reaction( () => ({ address: Cast(layout["mapLocation-address"], "string", null) }), ({ address }) => { - if (!BoolCast(layout._ignoreNextUpdate)) { - if (address && address.length) { - const target = `${base}address=${address.replace(/\s+/g, "+")}&key=${process.env.GOOGLE_MAPS_GEO!}`; - requestPromise.get(target).then(res => { - const result = JSON.parse(res).results[0]; - const { lat, lng } = result.geometry.location; - layout._ignoreNextUpdate = true; - layout["mapLocation-lat"] = lat; - layout._ignoreNextUpdate = true; - layout["mapLocation-lng"] = lng; - layout._ignoreNextUpdate = true; - layout["mapLocation-address"] = result.formatted_address; - }); - } - } else { - layout._ignoreNextUpdate = false; + if (this._cancelAddrReq.get(layout[Id])) { + this._cancelAddrReq.set(layout[Id], false); + } + else if (address?.length) { + const target = `${base}address=${address.replace(/\s+/g, "+")}&key=${process.env.GOOGLE_MAPS_GEO!}`; + requestPromise.get(target).then(action((res: any) => { + const { geometry, formatted_address } = JSON.parse(res).results[0]; + const { lat, lng } = geometry.location; + if (layout["mapLocation-lat"] !== lat || layout["mapLocation-lng"] !== lng) { + this._cancelLocReq.set(layout[Id], true); + Doc.SetInPlace(layout, "mapLocation-lat", lat, true); + Doc.SetInPlace(layout, "mapLocation-lng", lng, true); + } + if (formatted_address !== address) { + this._cancelAddrReq.set(layout[Id], true); + Doc.SetInPlace(layout, "mapLocation-address", formatted_address, true); + } + })); } } )); @@ -150,7 +155,7 @@ class CollectionMapView extends CollectionSubView & style={{ pointerEvents: this.props.active() ? undefined : "none" }} onWheel={e => e.stopPropagation()} onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > - & }} > {this.contents} - + ; } -- cgit v1.2.3-70-g09d2 From 26893de4b384678041523a0bbf71f895ad1cd2b7 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 14 Apr 2020 10:50:15 -0400 Subject: added map undo batches. fixed marker flicker on drag. split up code. --- src/client/views/collections/CollectionMapView.tsx | 111 ++++++++++----------- src/client/views/nodes/DocumentView.tsx | 2 +- 2 files changed, 55 insertions(+), 58 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index 5d0b0c982..fced52275 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -10,8 +10,8 @@ import "./CollectionMapView.scss"; import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); import { DocumentManager } from "../../util/DocumentManager"; -import { UndoManager } from "../../util/UndoManager"; -import { IReactionDisposer, reaction, action } from "mobx"; +import { UndoManager, undoBatch } from "../../util/UndoManager"; +import { IReactionDisposer, reaction, action, computed } from "mobx"; import requestPromise = require("request-promise"); type MapSchema = makeInterface<[typeof documentSchema]>; @@ -28,7 +28,13 @@ const base = "https://maps.googleapis.com/maps/api/geocode/json?"; @observer class CollectionMapView extends CollectionSubView & { google: any }>(MapSchema) { - private mapRef = React.createRef(); + // private mapRef = React.createRef(); + // private get map() { + // return (this.mapRef.current as any).map; + // } + + private _cancelAddrReq = new Map(); + private _cancelLocReq = new Map(); private addressUpdaters: IReactionDisposer[] = []; private latlngUpdaters: IReactionDisposer[] = []; @@ -42,62 +48,62 @@ class CollectionMapView extends CollectionSubView & return undefined; } - renderMarker(layout: Doc, icon: Opt) { + markerClick = action(async (layout: Doc, location: LocationData) => { + //this.map.panTo(location); + const batch = UndoManager.StartBatch("marker click"); + this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = location.lat; + this.layoutDoc[this.props.fieldKey + "-mapCenter-lng"] = location.lng; + location.zoom && (this.layoutDoc[this.props.fieldKey + "-mapCenter-zoom"] = location.zoom); + if (layout.isLinkButton && DocListCast(layout.links).length) { + await DocumentManager.Instance.FollowLink(undefined, layout, (doc: Doc, where: string, finished?: () => void) => { + this.props.addDocTab(doc, where); + finished?.(); + }, false, this.props.ContainingCollectionDoc, batch.end, undefined); + } else { + ScriptCast(layout.onClick)?.script.run({ this: layout, self: Cast(layout.rootDocument, Doc, null) || layout }); + batch.end(); + } + }); + + renderMarkerIcon(layout: Doc) { + const iconUrl = StrCast(this.props.Document.mapIconUrl, null); + if (iconUrl) { + const iconWidth = NumCast(layout["mapLocation-iconWidth"], 45); + const iconHeight = NumCast(layout["mapLocation-iconHeight"], 45); + const iconSize = new google.maps.Size(iconWidth, iconHeight); + return { + size: iconSize, + scaledSize: iconSize, + url: iconUrl + }; + } + } + renderMarker(layout: Doc) { const location = this.getLocation(layout, "mapLocation"); return !location ? (null) : { - this.map.panTo(location); - this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = location.lat; - this.layoutDoc[this.props.fieldKey + "-mapCenter-lng"] = location.lng; - location.zoom && (this.layoutDoc[this.props.fieldKey + "-mapCenter-zoom"] = location.zoom); - if (layout.isLinkButton && DocListCast(layout.links).length) { - const batch = UndoManager.StartBatch("follow link click"); - await DocumentManager.Instance.FollowLink(undefined, layout, (doc: Doc, where: string, finished?: () => void) => { - this.props.addDocTab(doc, where); - finished?.(); - }, false, this.props.ContainingCollectionDoc, batch.end, undefined); - } else { - ScriptCast(layout.onClick)?.script.run({ this: layout, self: Cast(layout.rootDocument, Doc, null) || layout }); - } - }} - icon={icon} + position={location} + onClick={() => this.markerClick(layout, location)} + icon={this.renderMarkerIcon(layout)} />; } - _cancelAddrReq = new Map(); - _cancelLocReq = new Map(); - private get contents() { + @computed get contents() { this.addressUpdaters.forEach(disposer => disposer()); this.addressUpdaters = []; this.latlngUpdaters.forEach(disposer => disposer()); this.latlngUpdaters = []; - return this.childLayoutPairs.map(({ layout, data }) => { - let icon: Opt, iconUrl: Opt; - if ((iconUrl = StrCast(this.props.Document.mapIconUrl, null))) { - const iconWidth = NumCast(layout["mapLocation-iconWidth"], 45); - const iconHeight = NumCast(layout["mapLocation-iconHeight"], 45); - const iconSize = new google.maps.Size(iconWidth, iconHeight); - icon = { - size: iconSize, - scaledSize: iconSize, - url: iconUrl - }; - } + return this.childLayoutPairs.map(({ layout }) => { this.addressUpdaters.push(reaction( - () => ({ - lat: NumCast(layout["mapLocation-lat"]), - lng: NumCast(layout["mapLocation-lng"]) - }), + () => ({ lat: layout["mapLocation-lat"], lng: layout["mapLocation-lng"] }), ({ lat, lng }) => { if (this._cancelLocReq.get(layout[Id])) { this._cancelLocReq.set(layout[Id], false); } else if (lat !== undefined && lng !== undefined) { - const target = `${base}latlng=${lat},${lng}&key=${process.env.GOOGLE_MAPS_GEO!}`; + const target = `${base}latlng=${NumCast(lat)},${NumCast(lng)}&key=${process.env.GOOGLE_MAPS_GEO!}`; requestPromise.get(target).then(res => { const formatted_address = JSON.parse(res).results[0].formatted_address || ""; if (formatted_address !== layout["mapLocation-address"]) { @@ -132,14 +138,9 @@ class CollectionMapView extends CollectionSubView & } } )); - return this.renderMarker(layout, icon); + return this.renderMarker(layout); }); } - - private get map() { - return (this.mapRef.current as any).map; - } - render() { const { childLayoutPairs } = this; const { Document } = this.props; @@ -156,16 +157,15 @@ class CollectionMapView extends CollectionSubView & onWheel={e => e.stopPropagation()} onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > { - const { center } = this.map; - Document[this.props.fieldKey + "-mapCenter-lat"] = center.lat(); - Document[this.props.fieldKey + "-mapCenter-lng"] = center.lng(); - }} + onDragend={undoBatch(action((e: any, map: any) => { + Document[this.props.fieldKey + "-mapCenter-lat"] = map.center.lat(); + Document[this.props.fieldKey + "-mapCenter-lng"] = map.center.lng(); + }))} > {this.contents} @@ -174,8 +174,5 @@ class CollectionMapView extends CollectionSubView & } -const LoadingContainer = () => { - return
; -}; - +const LoadingContainer = () =>
; export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS!, LoadingContainer })(CollectionMapView) as any; \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5b6478e66..0ef7ece9c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -586,7 +586,7 @@ export class DocumentView extends DocComponent(Docu } const docTemplate = docLayoutTemplate || creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) }); - fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate)); + fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate); docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined); } -- cgit v1.2.3-70-g09d2 From 3494d987b72b1e60bf1ded41443391952578e323 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 14 Apr 2020 13:32:33 -0400 Subject: fixed maps to support drag/drop, and fixed to work with docs that just have an address. --- .../views/collections/CollectionMapView.scss | 6 ++- src/client/views/collections/CollectionMapView.tsx | 59 ++++++++++++++-------- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- 3 files changed, 44 insertions(+), 23 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss index 4956ad946..cb58b1750 100644 --- a/src/client/views/collections/CollectionMapView.scss +++ b/src/client/views/collections/CollectionMapView.scss @@ -1,6 +1,10 @@ -.collectionMapView-contents { +.collectionMapView { width: 100%; height: 100%; + .collectionMapView-contents { + width: 100%; + height: 100%; + } } .loadingWrapper { diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index fced52275..a80f0557f 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -40,10 +40,25 @@ class CollectionMapView extends CollectionSubView & getLocation = (doc: Opt, fieldKey: string): Opt => { if (doc) { - const lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null); - const lng: Opt = Cast(doc[fieldKey + "-lng"], "number", null); - const zoom: Opt = Cast(doc[fieldKey + "-zoom"], "number", null); - return lat !== undefined && lng !== undefined ? ({ lat, lng, zoom }) : undefined; + const lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null) || (Cast(doc[fieldKey + "-lat"], "string", null) && Number(Cast(doc[fieldKey + "-lat"], "string", null))) || undefined; + const lng: Opt = Cast(doc[fieldKey + "-lng"], "number", null) || (Cast(doc[fieldKey + "-lng"], "string", null) && Number(Cast(doc[fieldKey + "-lng"], "string", null))) || undefined; + const zoom: Opt = Cast(doc[fieldKey + "-zoom"], "number", null) || (Cast(doc[fieldKey + "-zoom"], "string", null) && Number(Cast(doc[fieldKey + "-zoom"], "string", null))) || undefined; + const address: Opt = Cast(doc[fieldKey + "-address"], "string", null); + if (lat !== undefined && lng !== undefined) { + return ({ lat, lng, zoom }); + } else if (address) { + setTimeout(() => { + const target = `${base}address=${address.replace(/\s+/g, "+")}&key=${process.env.GOOGLE_MAPS_GEO!}`; + requestPromise.get(target).then(action((res: any) => { + const { lat, lng } = JSON.parse(res).results[0].geometry.location; + if (doc[fieldKey + "-lat"] !== lat || doc[fieldKey + "-lng"] !== lng) { + Doc.SetInPlace(doc, fieldKey + "-lat", lat, true); + Doc.SetInPlace(doc, fieldKey + "-lng", lng, true); + } + })); + }); + return ({ lat: 35.1592238, lng: -98.444512, zoom: 15 }); + } } return undefined; } @@ -152,23 +167,25 @@ class CollectionMapView extends CollectionSubView & } } TraceMobx(); - return
e.stopPropagation()} - onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > - { - Document[this.props.fieldKey + "-mapCenter-lat"] = map.center.lat(); - Document[this.props.fieldKey + "-mapCenter-lng"] = map.center.lng(); - }))} - > - {this.contents} - + return
+
e.stopPropagation()} + onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > + { + Document[this.props.fieldKey + "-mapCenter-lat"] = map.center.lat(); + Document[this.props.fieldKey + "-mapCenter-lng"] = map.center.lng(); + }))} + > + {this.contents} + +
; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 9dd3d640b..454c3a5f2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -309,7 +309,7 @@ export class MarqueeView extends React.Component { + getCollection = (selected: Doc[], asTemplate: boolean, isBackground?: boolean) => { const bounds = this.Bounds; // const inkData = this.ink ? this.ink.inkData : undefined; const creator = asTemplate ? Docs.Create.StackingDocument : Docs.Create.FreeformDocument; -- cgit v1.2.3-70-g09d2 From 3d4a7582dcd0df151f9571fdeb24507acefe49e1 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 14 Apr 2020 13:48:25 -0700 Subject: map view cleanup --- .../views/collections/CollectionMapView.scss | 7 +- src/client/views/collections/CollectionMapView.tsx | 142 ++++++++++++--------- 2 files changed, 87 insertions(+), 62 deletions(-) (limited to 'src/client/views/collections/CollectionMapView.tsx') diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss index cb58b1750..2e642be6b 100644 --- a/src/client/views/collections/CollectionMapView.scss +++ b/src/client/views/collections/CollectionMapView.scss @@ -1,6 +1,7 @@ .collectionMapView { width: 100%; height: 100%; + .collectionMapView-contents { width: 100%; height: 100%; @@ -10,7 +11,7 @@ .loadingWrapper { width: 100%; height: 100%; - background-color: yellow; + background-color: pink; display: flex; flex-direction: column; justify-content: center; @@ -20,7 +21,7 @@ .loadingGif { align-self: center; justify-self: center; - width: 20%; - height: 20% + width: 50px; + height: 50px; } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx index a80f0557f..b6772c5a2 100644 --- a/src/client/views/collections/CollectionMapView.tsx +++ b/src/client/views/collections/CollectionMapView.tsx @@ -4,14 +4,13 @@ import { Doc, Opt, DocListCast } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; import { Id } from "../../../new_fields/FieldSymbols"; import { makeInterface } from "../../../new_fields/Schema"; -import { Cast, NumCast, ScriptCast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { TraceMobx } from "../../../new_fields/util"; +import { Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types"; import "./CollectionMapView.scss"; import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); import { DocumentManager } from "../../util/DocumentManager"; import { UndoManager, undoBatch } from "../../util/UndoManager"; -import { IReactionDisposer, reaction, action, computed } from "mobx"; +import { IReactionDisposer, reaction, computed, runInAction } from "mobx"; import requestPromise = require("request-promise"); type MapSchema = makeInterface<[typeof documentSchema]>; @@ -23,21 +22,31 @@ export type LocationData = google.maps.LatLngLiteral & { zoom?: number; }; -const base = "https://maps.googleapis.com/maps/api/geocode/json?"; +// Nowhere, Oklahoma +const defaultLocation = { lat: 35.1592238, lng: -98.444512, zoom: 15 }; + +const query = async (data: string | google.maps.LatLngLiteral) => { + const contents = typeof data === "string" ? `address=${data.replace(/\s+/g, "+")}` : `latlng=${data.lat},${data.lng}`; + const target = `https://maps.googleapis.com/maps/api/geocode/json?${contents}&key=${process.env.GOOGLE_MAPS_GEO}`; + return JSON.parse(await requestPromise.get(target)); +}; @observer class CollectionMapView extends CollectionSubView & { google: any }>(MapSchema) { - // private mapRef = React.createRef(); - // private get map() { - // return (this.mapRef.current as any).map; - // } - private _cancelAddrReq = new Map(); private _cancelLocReq = new Map(); private addressUpdaters: IReactionDisposer[] = []; private latlngUpdaters: IReactionDisposer[] = []; + /** + * Note that all the uses of runInAction below are not included + * as a way to update observables (documents handle this already + * in their property setters), but rather to create a single bulk + * update and thus prevent uneeded invocations of the location- + * and address–updating reactions. + */ + getLocation = (doc: Opt, fieldKey: string): Opt => { if (doc) { const lat: Opt = Cast(doc[fieldKey + "-lat"], "number", null) || (Cast(doc[fieldKey + "-lat"], "string", null) && Number(Cast(doc[fieldKey + "-lat"], "string", null))) || undefined; @@ -48,27 +57,31 @@ class CollectionMapView extends CollectionSubView & return ({ lat, lng, zoom }); } else if (address) { setTimeout(() => { - const target = `${base}address=${address.replace(/\s+/g, "+")}&key=${process.env.GOOGLE_MAPS_GEO!}`; - requestPromise.get(target).then(action((res: any) => { - const { lat, lng } = JSON.parse(res).results[0].geometry.location; - if (doc[fieldKey + "-lat"] !== lat || doc[fieldKey + "-lng"] !== lng) { - Doc.SetInPlace(doc, fieldKey + "-lat", lat, true); - Doc.SetInPlace(doc, fieldKey + "-lng", lng, true); + query(address).then(({ results }) => { + if (results?.length) { + const { lat, lng } = results[0].geometry.location; + if (doc[fieldKey + "-lat"] !== lat || doc[fieldKey + "-lng"] !== lng) { + runInAction(() => { + Doc.SetInPlace(doc, fieldKey + "-lat", lat, true); + Doc.SetInPlace(doc, fieldKey + "-lng", lng, true); + }); + } } - })); + }); }); - return ({ lat: 35.1592238, lng: -98.444512, zoom: 15 }); + return defaultLocation; } } return undefined; } - markerClick = action(async (layout: Doc, location: LocationData) => { - //this.map.panTo(location); + private markerClick = async (layout: Doc, { lat, lng, zoom }: LocationData) => { const batch = UndoManager.StartBatch("marker click"); - this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = location.lat; - this.layoutDoc[this.props.fieldKey + "-mapCenter-lng"] = location.lng; - location.zoom && (this.layoutDoc[this.props.fieldKey + "-mapCenter-zoom"] = location.zoom); + runInAction(() => { + this.layoutDoc[this.props.fieldKey + "-mapCenter-lat"] = lat; + this.layoutDoc[this.props.fieldKey + "-mapCenter-lng"] = lng; + zoom && (this.layoutDoc[this.props.fieldKey + "-mapCenter-zoom"] = zoom); + }); if (layout.isLinkButton && DocListCast(layout.links).length) { await DocumentManager.Instance.FollowLink(undefined, layout, (doc: Doc, where: string, finished?: () => void) => { this.props.addDocTab(doc, where); @@ -78,7 +91,7 @@ class CollectionMapView extends CollectionSubView & ScriptCast(layout.onClick)?.script.run({ this: layout, self: Cast(layout.rootDocument, Doc, null) || layout }); batch.end(); } - }); + } renderMarkerIcon(layout: Doc) { const iconUrl = StrCast(this.props.Document.mapIconUrl, null); @@ -93,6 +106,7 @@ class CollectionMapView extends CollectionSubView & }; } } + renderMarker(layout: Doc) { const location = this.getLocation(layout, "mapLocation"); return !location ? (null) : @@ -116,14 +130,14 @@ class CollectionMapView extends CollectionSubView & ({ lat, lng }) => { if (this._cancelLocReq.get(layout[Id])) { this._cancelLocReq.set(layout[Id], false); - } - else if (lat !== undefined && lng !== undefined) { - const target = `${base}latlng=${NumCast(lat)},${NumCast(lng)}&key=${process.env.GOOGLE_MAPS_GEO!}`; - requestPromise.get(target).then(res => { - const formatted_address = JSON.parse(res).results[0].formatted_address || ""; - if (formatted_address !== layout["mapLocation-address"]) { - this._cancelAddrReq.set(layout[Id], true); - Doc.SetInPlace(layout, "mapLocation-address", formatted_address, true); + } else if (lat !== undefined && lng !== undefined) { + query({ lat: NumCast(lat), lng: NumCast(lng) }).then(({ results }) => { + if (results?.length) { + const { formatted_address } = results[0]; + if (formatted_address !== layout["mapLocation-address"]) { + this._cancelAddrReq.set(layout[Id], true); + Doc.SetInPlace(layout, "mapLocation-address", formatted_address, true); + } } }); } @@ -134,54 +148,58 @@ class CollectionMapView extends CollectionSubView & ({ address }) => { if (this._cancelAddrReq.get(layout[Id])) { this._cancelAddrReq.set(layout[Id], false); - } - else if (address?.length) { - const target = `${base}address=${address.replace(/\s+/g, "+")}&key=${process.env.GOOGLE_MAPS_GEO!}`; - requestPromise.get(target).then(action((res: any) => { - const { geometry, formatted_address } = JSON.parse(res).results[0]; - const { lat, lng } = geometry.location; - if (layout["mapLocation-lat"] !== lat || layout["mapLocation-lng"] !== lng) { - this._cancelLocReq.set(layout[Id], true); - Doc.SetInPlace(layout, "mapLocation-lat", lat, true); - Doc.SetInPlace(layout, "mapLocation-lng", lng, true); - } - if (formatted_address !== address) { - this._cancelAddrReq.set(layout[Id], true); - Doc.SetInPlace(layout, "mapLocation-address", formatted_address, true); + } else if (address?.length) { + query(address).then(({ results }) => { + if (results?.length) { + const { geometry, formatted_address } = results[0]; + const { lat, lng } = geometry.location; + runInAction(() => { + if (layout["mapLocation-lat"] !== lat || layout["mapLocation-lng"] !== lng) { + this._cancelLocReq.set(layout[Id], true); + Doc.SetInPlace(layout, "mapLocation-lat", lat, true); + Doc.SetInPlace(layout, "mapLocation-lng", lng, true); + } + if (formatted_address !== address) { + this._cancelAddrReq.set(layout[Id], true); + Doc.SetInPlace(layout, "mapLocation-address", formatted_address, true); + } + }); } - })); + }); } } )); return this.renderMarker(layout); }); } + render() { const { childLayoutPairs } = this; - const { Document } = this.props; - let center = this.getLocation(Document, this.props.fieldKey + "-mapCenter"); + const { Document, fieldKey, active, google } = this.props; + let center = this.getLocation(Document, fieldKey + "-mapCenter"); if (center === undefined) { center = childLayoutPairs.map(pair => this.getLocation(pair.layout, "mapLocation")).find(layout => layout); if (center === undefined) { - center = { lat: 35.1592238, lng: -98.444512, zoom: 15 }; // nowhere, OK + center = defaultLocation; } } - TraceMobx(); return
e.stopPropagation()} onPointerDown={e => (e.button === 0 && !e.ctrlKey) && e.stopPropagation()} > { - Document[this.props.fieldKey + "-mapCenter-lat"] = map.center.lat(); - Document[this.props.fieldKey + "-mapCenter-lng"] = map.center.lng(); - }))} + onDragend={undoBatch((_props: MapProps, map: google.maps.Map) => { + const { lat, lng } = map.getCenter(); + runInAction(() => { + Document[fieldKey + "-mapCenter-lat"] = lat(); + Document[fieldKey + "-mapCenter-lng"] = lng(); + }); + })} > {this.contents} @@ -191,5 +209,11 @@ class CollectionMapView extends CollectionSubView & } -const LoadingContainer = () =>
; -export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS!, LoadingContainer })(CollectionMapView) as any; \ No newline at end of file +export default GoogleApiWrapper({ + apiKey: process.env.GOOGLE_MAPS!, + LoadingContainer: () => ( +
+ +
+ ) +})(CollectionMapView) as any; \ No newline at end of file -- cgit v1.2.3-70-g09d2