From 639eb465369f89dc541dfbeeaed34dfe133a8810 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 7 Dec 2021 11:23:36 -0500 Subject: restored keeping properties pane open when selection changes. added Doc paraemter to fitWidth() prop function. split MapBoxInfoWindow out of MapBox and added an Add Note button. --- src/client/util/SelectionManager.ts | 5 +- .../views/collections/CollectionStackingView.tsx | 12 +- src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/MapBox/MapBox.scss | 7 + src/client/views/nodes/MapBox/MapBox.tsx | 194 +++++++-------------- src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx | 86 +++++++++ 7 files changed, 162 insertions(+), 148 deletions(-) create mode 100644 src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx (limited to 'src') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 6674f684d..b71086561 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -44,11 +44,8 @@ export namespace SelectionManager { } @action DeselectAll(): void { - if (CurrentUserUtils.propertiesWidth > 0) { - CurrentUserUtils.propertiesWidth = 0; - } manager.SelectedSchemaDocument = undefined; - Array.from(manager.SelectedViews.keys()).map(dv => dv.props.whenChildContentsActiveChanged(false)); + Array.from(manager.SelectedViews.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false)); manager.SelectedViews.clear(); } } diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index bffaf86b1..eddb97878 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -231,8 +231,8 @@ export class CollectionStackingView extends CollectionSubView lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim)(NumCast(this.layoutDoc.childLimitHeight, -1)); - const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.()) ? d[WidthSym]() : 0); - const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.()) ? d[HeightSym]() : 0); + const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); + const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); if (nw && nh) { const colWid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid); @@ -291,7 +291,7 @@ export class CollectionStackingView extends CollectionSubView JSX.Element[]) | React.ReactNode; childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox) childDocumentsActive?: () => boolean;// whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode) - childFitWidth?: () => boolean; + childFitWidth?: (child: Doc) => boolean; childShowTitle?: () => string; childOpacity?: () => number; childContextMenuItems?: () => { script: ScriptField, label: string }[]; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 138bad9b8..9fc4b7890 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -118,7 +118,7 @@ export interface DocumentViewSharedProps { layerProvider: undefined | ((doc: Doc, assign?: boolean) => boolean); styleProvider: Opt; focus: DocFocusFunc; - fitWidth?: () => boolean; + fitWidth?: (doc: Doc) => boolean; docFilters: () => string[]; docRangeFilters: () => string[]; searchFilterDocs: () => Doc[]; @@ -1140,7 +1140,7 @@ export class DocumentView extends React.Component { get ComponentView() { return this.docView?._componentView; } get allLinks() { return this.docView?.allLinks || []; } get LayoutFieldKey() { return this.docView?.LayoutFieldKey || "layout"; } - get fitWidth() { return this.props.fitWidth?.() || this.layoutDoc.fitWidth; } + get fitWidth() { return this.props.fitWidth?.(this.rootDoc) || this.layoutDoc.fitWidth; } @computed get docViewPath() { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; } @computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); } diff --git a/src/client/views/nodes/MapBox/MapBox.scss b/src/client/views/nodes/MapBox/MapBox.scss index f275bed54..1714fcaa9 100644 --- a/src/client/views/nodes/MapBox/MapBox.scss +++ b/src/client/views/nodes/MapBox/MapBox.scss @@ -8,6 +8,13 @@ position: unset !important; // when the sidebar filter flys out, this prevents the map from extending outside the document box } + .mapBox-infoWindow { + background-color: white; + opacity: 0.75; + padding: 12; + font-size: 17; + } + .mapBox-overlayButton-sidebar { background: #121721; height: 25px; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 7875060e2..8b23405d8 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1,5 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Autocomplete, GoogleMap, GoogleMapProps, InfoWindow, LoadScript, Marker } from '@react-google-maps/api'; +import { Autocomplete, GoogleMap, GoogleMapProps, Marker } from '@react-google-maps/api'; +import * as dotenv from 'dotenv'; import { action, computed, IReactionDisposer, observable, ObservableMap } from 'mobx'; import { observer } from "mobx-react"; import * as React from "react"; @@ -10,16 +11,12 @@ import { InkTool } from '../../../../fields/InkField'; import { makeInterface } from '../../../../fields/Schema'; import { NumCast, StrCast } from '../../../../fields/Types'; import { TraceMobx } from '../../../../fields/util'; -import { emptyFunction, OmitKeys, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { CurrentUserUtils } from '../../../util/CurrentUserUtils'; import { DragManager } from '../../../util/DragManager'; -import { SelectionManager } from '../../../util/SelectionManager'; import { SnappingManager } from '../../../util/SnappingManager'; -import { undoBatch } from '../../../util/UndoManager'; import { CollectionFreeFormView, MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; -import { CollectionStackingView } from '../../collections/CollectionStackingView'; -import { CollectionViewType } from '../../collections/CollectionView'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { MarqueeAnnotator } from '../../MarqueeAnnotator'; @@ -28,8 +25,8 @@ import { Annotation } from '../../pdf/Annotation'; import { SidebarAnnos } from '../../SidebarAnnos'; import { StyleProp } from '../../StyleProvider'; import { FieldView, FieldViewProps } from '../FieldView'; -import * as dotenv from 'dotenv'; import "./MapBox.scss"; +import { MapBoxInfoWindow } from './MapBoxInfoWindow'; /** * MapBox architecture: @@ -146,7 +143,6 @@ export class MapBox extends ViewBoxAnnotatableComponent { - console.log('map bound is:' + this.bounds); this.allMapMarkers.map(place => { this.bounds.extend({ lat: NumCast(place.lat), lng: NumCast(place.lng) }); }); @@ -232,7 +228,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { + (position: Position) => { const pos = { lat: position.coords.latitude, lng: position.coords.longitude, @@ -243,17 +239,13 @@ export class MapBox extends ViewBoxAnnotatableComponent { - console.log("add marker map status:" + this.toggleAddMarker); + this._map.addListener('click', (e: MouseEvent) => { if (this.toggleAddMarker == true) { - this.placeMarker(e.latLng, map) - console.log(this.allMapMarkers) + this.placeMarker((e as any).latLng, map); } }) } @@ -266,9 +258,6 @@ export class MapBox extends ViewBoxAnnotatableComponent { place[Id] ? this.markerMap[place[Id]] = marker : null; - - console.log("the following is a markerMap from id to Marker:") - console.log(this.markerMap); } /** @@ -277,15 +266,10 @@ export class MapBox extends ViewBoxAnnotatableComponent { + private markerClickHandler = (e: google.maps.MapMouseEvent, place: Doc) => { // set which place was clicked this.selectedPlace = place; - - console.log("you have selected this location:"); - console.log(this.selectedPlace); - place.infoWindowOpen = true; - console.log("open infowindow") } /** @@ -406,15 +390,6 @@ export class MapBox extends ViewBoxAnnotatableComponent { - if (place.infoWindowOpen) { - place.infoWindowOpen = false; - } - place.infoWindowOpen = false; - } - /** * Handles toggle of sidebar on click the little comment button */ @@ -476,19 +451,16 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.isContentActive() && this.props.pointerEvents !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" : SnappingManager.GetIsDragging() ? undefined : "none"; - @computed get annotationLayer() { - TraceMobx(); - const pe = this.pointerEvents(); + const pe = this.props.isContentActive() && this.props.pointerEvents !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" : + SnappingManager.GetIsDragging() ? undefined : "none" return
{this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno => - )} + )}
; - } - getAnchor = () => { const anchor = AnchorMenu.Instance?.GetAnchor(this._savedAnnotations) ?? @@ -496,43 +468,6 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.PanelWidth() / 5; - infoHeight = () => this.props.PanelWidth() / 5; - - // Collection stacking view for documents in the infowindow of a map marker - private renderChildDocs = (selectedDoc: Doc) => { - return
-
; - } - /** * render contents in allMapMarkers (e.g. images with exifData) into google maps as map marker * @returns @@ -543,41 +478,17 @@ export class MapBox extends ViewBoxAnnotatableComponent this.markerLoadHandler(marker, place)} - onClick={e => this.markerClickHandler(e, place)} + onClick={(e: google.maps.MapMouseEvent) => this.markerClickHandler(e, place)} /> )) } - /** - * Renders infowindow corresponding to a map marker document - * @param place - * @returns - */ - private renderInfoWindow = (place: Doc) => { - - return place.infoWindowOpen && ( - this.handleInfoWindowClose(place)} - > -
- {this.renderChildDocs(place)} -
-
- -
-
-
- ) - } - // TODO: auto center on select a document in the sidebar private handleMapCenter = (map: google.maps.Map) => { - console.log("print the selected views in selectionManager:") - if (SelectionManager.Views().lastElement()) { - console.log(SelectionManager.Views().lastElement()); - } + // console.log("print the selected views in selectionManager:") + // if (SelectionManager.Views().lastElement()) { + // console.log(SelectionManager.Views().lastElement()); + // } } panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1) - this.sidebarWidth(); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); @@ -585,35 +496,41 @@ export class MapBox extends ViewBoxAnnotatableComponent this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; - + infoWidth = () => this.props.PanelWidth() / 5; + infoHeight = () => this.props.PanelHeight() / 5; anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; render() { - const renderAnnotations = (docFilters?: () => string[]) => - ; + const renderAnnotations = (docFilters?: () => string[]) => (null); + // bcz: commmented this out. Otherwise, any documents that are rendered with an InfoWindow of a marker + // will also be rendered as freeform annotations on the map. However, it doesn't seem that rendering + // freeform documents on the map does anything anyway, so getting rid of it for now. Also, since documents + // are rendered twice, adding a new note to the InfoWindow loses focus immediately on creation since it gets + // shifted to the non-visible view of the document in this freeform view. + // ; return
- {console.log(apiKey)} + {/*console.log(apiKey)*/} {/* {this.renderMarkers()} - {this.allMapMarkers.map(place => ( - this.renderInfoWindow(place) - ))} + {this.allMapMarkers.filter(marker => marker.infoWindowOpen).map(marker => )} {this.handleMapCenter(this._map)} {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : @@ -688,4 +612,4 @@ export class MapBox extends ViewBoxAnnotatableComponent
; } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx new file mode 100644 index 000000000..e6f98e5cf --- /dev/null +++ b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx @@ -0,0 +1,86 @@ +import { InfoWindow } from '@react-google-maps/api'; +import { action, computed } from 'mobx'; +import { observer } from "mobx-react"; +import * as React from "react"; +import { Doc } from '../../../../fields/Doc'; +import { Id } from '../../../../fields/FieldSymbols'; +import { emptyFunction, OmitKeys, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents } from '../../../../Utils'; +import { Docs } from '../../../documents/Documents'; +import { DocumentType } from '../../../documents/DocumentTypes'; +import { CollectionStackingView } from '../../collections/CollectionStackingView'; +import { CollectionViewType } from '../../collections/CollectionView'; +import { ViewBoxAnnotatableProps } from '../../DocComponent'; +import { FieldViewProps } from '../FieldView'; +import { FormattedTextBox } from '../formattedText/FormattedTextBox'; +import "./MapBox.scss"; + + +interface MapBoxInfoWindowProps { + place: Doc; + renderDepth: number; + markerMap: { [id: string]: google.maps.Marker }; + isAnyChildContentActive: () => boolean; +} +@observer +export class MapBoxInfoWindow extends React.Component{ + + @action + private handleInfoWindowClose = () => { + if (this.props.place.infoWindowOpen) { + this.props.place.infoWindowOpen = false; + } + this.props.place.infoWindowOpen = false; + } + + addNoteClick = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => { + const newBox = Docs.Create.TextDocument("Note", { _autoHeight: true }); + FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed + Doc.AddDocToList(this.props.place, "data", newBox); + e.stopPropagation(); + e.preventDefault(); + }); + } + + // Collection stacking view for documents in the infowindow of a map marker + @computed get renderChildDocs() { + return; + } + render() { + return +
+
+ doc.type === DocumentType.RTF} + // childDocumentsActive={returnFalse} + removeDocument={(doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.RemoveDocFromList(this.props.place, "data", d), true as boolean)} + addDocument={(doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.AddDocToList(this.props.place, "data", d), true as boolean)} + renderDepth={this.props.renderDepth + 1} + viewType={CollectionViewType.Stacking} + pointerEvents="all" + /> +
+
+
{ e.stopPropagation(); e.preventDefault(); }} > + Add Note +
+
+
; + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2