aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/MapBox/MapBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/MapBox/MapBox.tsx')
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx153
1 files changed, 55 insertions, 98 deletions
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index c25d10a0d..efe0a3620 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,72 +1,45 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import BingMapsReact from 'bingmaps-react';
-// import 'mapbox-gl/dist/mapbox-gl.css';
-
-import { Button, EditableText, IconButton, Size, Type } from 'browndash-components';
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, flow, toJS, autorun, makeObservable } from 'mobx';
+import { IconButton, Size, Type } from 'browndash-components';
+import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { Utils, emptyFunction, setupMoveUpEvents } from '../../../../Utils';
import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc';
import { DocCss, Highlight } from '../../../../fields/DocSymbols';
-import { Id } from '../../../../fields/FieldSymbols';
-import { Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils';
-import { Docs, DocUtils } from '../../../documents/Documents';
+import { DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { DocumentType } from '../../../documents/DocumentTypes';
+import { DocUtils, Docs } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { LinkManager } from '../../../util/LinkManager';
import { SnappingManager } from '../../../util/SnappingManager';
-import { Transform } from '../../../util/Transform';
-import { undoable, UndoManager } from '../../../util/UndoManager';
-import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
+import { UndoManager, undoable } from '../../../util/UndoManager';
import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent';
-import { Colors } from '../../global/globalEnums';
import { SidebarAnnos } from '../../SidebarAnnos';
+import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
+import { Colors } from '../../global/globalEnums';
import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps } from '../FieldView';
import { FormattedTextBox } from '../formattedText/FormattedTextBox';
import { PinProps, PresBox } from '../trails';
import { MapAnchorMenu } from './MapAnchorMenu';
-import {
- Map as MapboxMap,
- MapRef,
- Marker,
- ControlPosition,
- FullscreenControl,
- MapProvider,
- MarkerProps,
- NavigationControl,
- ScaleControl,
- ViewState,
- ViewStateChangeEvent,
- useControl,
- GeolocateControl,
- Popup,
- MapEvent,
- Source,
- Layer,
-} from 'react-map-gl';
+import { ControlPosition, Layer, MapProvider, MapRef, Map as MapboxMap, Marker, MarkerProps, Source, ViewState, ViewStateChangeEvent } from 'react-map-gl';
import MapboxGeocoder, { GeocoderOptions } from '@mapbox/mapbox-gl-geocoder!';
import './MapBox.scss';
-import { NumberLiteralType } from 'typescript';
// import { GeocoderControl } from './GeocoderControl';
-import mapboxgl, { LngLat, LngLatBoundsLike, LngLatLike, MapLayerMouseEvent, MercatorCoordinate } from 'mapbox-gl!';
-import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, MultiLineString, Position } from 'geojson';
-import { MarkerEvent } from 'react-map-gl/dist/esm/types';
-import { MapboxApiUtility, TransportationType } from './MapboxApiUtility';
-import { Autocomplete, Checkbox, FormControlLabel, TextField } from '@mui/material';
-import { List } from '../../../../fields/List';
-import { listSpec } from '../../../../fields/Schema';
-import { IconLookup, faCircleXmark, faFileExport, faGear, faMinus, faPause, faPlay, faPlus, faRotate } from '@fortawesome/free-solid-svg-icons';
-import { MarkerIcons } from './MarkerIcons';
-import { SettingsManager } from '../../../util/SettingsManager';
+import { IconLookup, faCircleXmark, faGear, faPause, faPlay, faRotate } from '@fortawesome/free-solid-svg-icons';
+import { Checkbox, FormControlLabel, TextField } from '@mui/material';
import * as turf from '@turf/turf';
import * as d3 from 'd3';
-import { AnimationSpeed, AnimationStatus, AnimationUtility } from './AnimationUtility';
-import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons';
+import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, Position } from 'geojson';
+import mapboxgl, { LngLat, LngLatBoundsLike, MapLayerMouseEvent } from 'mapbox-gl!';
import { CirclePicker, ColorResult } from 'react-color';
+import { MarkerEvent } from 'react-map-gl/dist/esm/types';
+import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons';
+import { AnimationSpeed, AnimationStatus, AnimationUtility } from './AnimationUtility';
+import { MapboxApiUtility, TransportationType } from './MapboxApiUtility';
+import { MarkerIcons } from './MarkerIcons';
// amongus
/**
@@ -891,15 +864,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}, 'createpin');
@action
- createMapRoute = undoable((coordinates: Position[], origin: string, destination: any, createPinForDestination: boolean) => {
- const mapRoute = Docs.Create.MapRouteDocument(false, [], { title: `${origin} --> ${destination.place_name}`, routeCoordinates: JSON.stringify(coordinates) });
- this.addDocument(mapRoute, this.annotationKey);
- if (createPinForDestination) {
- this.createPushpin(destination.center[1], destination.center[0], destination.place_name);
+ createMapRoute = undoable((coordinates: Position[], originName: string, destination: any, createPinForDestination: boolean) => {
+ if (originName !== destination.place_name) {
+ const mapRoute = Docs.Create.MapRouteDocument(false, [], { title: `${originName} --> ${destination.place_name}`, routeCoordinates: JSON.stringify(coordinates) });
+ this.addDocument(mapRoute, this.annotationKey);
+ if (createPinForDestination) {
+ this.createPushpin(destination.center[1], destination.center[0], destination.place_name);
+ }
+ return mapRoute;
}
- return mapRoute;
-
- // mapMarker.infoWindowOpen = true;
+ // TODO: Display error that can't create route to same location
}, 'createmaproute');
searchbarKeyDown = (e: any) => e.key === 'Enter' && this.bingSearch();
@@ -958,6 +932,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
@action
handleMapClick = (e: MapLayerMouseEvent) => {
+ this.featuresFromGeocodeResults = [];
if (this._mapRef.current) {
const features = this._mapRef.current.queryRenderedFeatures(e.point, {
layers: ['map-routes-layer'],
@@ -1146,24 +1121,26 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
if (routeDoc) {
MapAnchorMenu.Instance.fadeOut(true);
document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
+ this.featuresFromGeocodeResults = [];
this.routeToAnimate = routeDoc;
}
};
- @observable
- mapboxMapViewState: ViewState = {
- zoom: this.dataDoc.map_zoom ? NumCast(this.dataDoc.map_zoom) : 8,
- longitude: this.dataDoc.longitude ? NumCast(this.dataDoc.longitude) : -71.4128,
- latitude: this.dataDoc.latitude ? NumCast(this.dataDoc.latitude) : 41.824,
- pitch: this.dataDoc.map_pitch ? NumCast(this.dataDoc.map_pitch) : 0,
- bearing: this.dataDoc.map_bearing ? NumCast(this.dataDoc.map_bearing) : 0,
- padding: {
- top: 0,
- bottom: 0,
- left: 0,
- right: 0,
- },
- };
+ @computed get mapboxMapViewState(): ViewState {
+ return {
+ zoom: NumCast(this.dataDoc.map_zoom, 8),
+ longitude: NumCast(this.dataDoc.longitude, -71.4128),
+ latitude: NumCast(this.dataDoc.latitude, 41.824),
+ pitch: NumCast(this.dataDoc.map_pitch),
+ bearing: NumCast(this.dataDoc.map_bearing),
+ padding: {
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ },
+ };
+ }
@computed
get preAnimationViewState() {
@@ -1390,9 +1367,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
this.routeToAnimate = undefined;
this.animationUtility = null;
}
- if (this.preAnimationViewState) {
- this.mapboxMapViewState = this.preAnimationViewState;
- }
};
@action
@@ -1488,10 +1462,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const fixedBearing = Math.max(0, Math.min(360, bearing));
this._mapRef.current.setBearing(fixedBearing);
this.dataDoc.map_bearing = fixedBearing;
- this.mapboxMapViewState = {
- ...this.mapboxMapViewState,
- bearing: fixedBearing,
- };
}
};
@@ -1502,10 +1472,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const fixedPitch = Math.max(0, Math.min(85, pitch));
this._mapRef.current.setPitch(fixedPitch);
this.dataDoc.map_pitch = fixedPitch;
- this.mapboxMapViewState = {
- ...this.mapboxMapViewState,
- pitch: fixedPitch,
- };
}
};
@@ -1516,10 +1482,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const fixedZoom = Math.max(0, Math.min(16, zoom));
this._mapRef.current.setZoom(fixedZoom);
this.dataDoc.map_zoom = fixedZoom;
- this.mapboxMapViewState = {
- ...this.mapboxMapViewState,
- zoom: fixedZoom,
- };
}
};
@@ -1529,23 +1491,18 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
let newZoom: number;
if (increment) {
console.log('inc');
- newZoom = this.mapboxMapViewState.zoom + 1;
+ newZoom = Math.min(16, this.mapboxMapViewState.zoom + 1);
} else {
console.log('dec');
- newZoom = this.mapboxMapViewState.zoom - 1;
+ newZoom = Math.max(0, this.mapboxMapViewState.zoom - 1);
}
this._mapRef.current.setZoom(newZoom);
this.dataDoc.map_zoom = newZoom;
- this.mapboxMapViewState = {
- ...this.mapboxMapViewState,
- zoom: increment ? Math.min(16, newZoom) : Math.max(0, newZoom),
- };
}
};
@action
onMapMove = (e: ViewStateChangeEvent) => {
- this.mapboxMapViewState = e.viewState;
this.dataDoc.longitude = e.viewState.longitude;
this.dataDoc.latitude = e.viewState.latitude;
};
@@ -1581,8 +1538,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}), MapBox._rerenderDelay);
return null;
}
-
const scale = this._props.NativeDimScaling?.() || 1;
+ const parscale = scale === 1 ? 1 : this._props.ScreenToLocalTransform().Scale ?? 1;
const renderAnnotations = (childFilters?: () => string[]) => null;
return (
@@ -1593,7 +1550,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
onPointerDown={async e => {
e.button === 0 && !e.ctrlKey && e.stopPropagation();
}}
- style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
+ style={{ transformOrigin: 'top left', transform: `scale(${scale})`, width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
<div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
{renderAnnotations(this.opaqueFilter)}
{SnappingManager.IsDragging ? null : renderAnnotations()}
@@ -1639,7 +1596,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
</div>
)}
{this.routeToAnimate && (
- <div className="animation-panel">
+ <div className="animation-panel" style={{ width: this.sidebarWidth() === 0 ? '100%' : `calc(100% - ${this.sidebarWidth()}px)` }}>
<div id="route-to-animate-title">{StrCast(this.routeToAnimate.title)}</div>
<div className="route-animation-options">{this.getRouteAnimationOptions()}</div>
</div>
@@ -1683,15 +1640,15 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
<MapboxMap
ref={this._mapRef}
mapboxAccessToken={MAPBOX_ACCESS_TOKEN}
- id="mapbox-map"
- viewState={{ ...this.mapboxMapViewState, width: NumCast(this.layoutDoc._width) / scale, height: NumCast(this.layoutDoc._height) / scale }}
+ viewState={this.isAnimating ? undefined : { ...this.mapboxMapViewState, width: NumCast(this.layoutDoc._width), height: NumCast(this.layoutDoc._height) }}
mapStyle={this.dataDoc.map_style ? StrCast(this.dataDoc.map_style) : 'mapbox://styles/mapbox/streets-v11'}
style={{
- transformOrigin: 'center',
- transform: `scale(${scale < 1 ? 1 : scale})`,
+ position: 'absolute',
+ top: 0,
+ left: 0,
zIndex: '0',
- width: '100%',
- height: '100%',
+ width: NumCast(this.layoutDoc._width) * parscale,
+ height: NumCast(this.layoutDoc._height) * parscale,
}}
initialViewState={this.isAnimating ? undefined : this.mapboxMapViewState}
onMove={this.onMapMove}