From 0eb9d37a9dd1a6539f331f953d5f20c761d5f940 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 17 Aug 2023 10:00:10 -0400
Subject: fixed brushing of pinned viewports for chrome to not flash. converted
 pres<Property> to config_<property> and treeView<Property> to
 treeView_Property.  fixed text toolbar to show/set text properties based on
 insertion point.

---
 src/client/views/pdf/PDFViewer.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 1319a236d..395fbd1ca 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -68,7 +68,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     private _styleRule: any; // stylesheet rule for making hyperlinks clickable
     private _retries = 0; // number of times tried to create the PDF viewer
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
-    private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }) => void);
+    private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void);
     private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _viewer: React.RefObject<HTMLDivElement> = React.createRef();
@@ -95,7 +95,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         return DocUtils.FilterDocs(DocListCast(this.props.dataDoc[this.props.fieldKey + '_annotations']), this.props.childFilters(), this.props.childFiltersByRanges());
     }
     @computed get inlineTextAnnotations() {
-        return this.allAnnotations.filter(a => a.textInlineAnnotations);
+        return this.allAnnotations.filter(a => a.text_inlineAnnotations);
     }
 
     componentDidMount = async () => {
@@ -195,7 +195,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         return focusSpeed;
     };
     crop = (region: Doc | undefined, addCrop?: boolean) => this.props.crop(region, addCrop);
-    brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._setBrushViewer?.(view);
+    brushView = (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => this._setBrushViewer?.(view, transTime);
 
     @action
     setupPdfJsViewer = async () => {
@@ -470,7 +470,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     };
 
     setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func);
-    setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => (this._setBrushViewer = func);
+    setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void) => (this._setBrushViewer = func);
 
     @action
     onZoomWheel = (e: React.WheelEvent) => {
-- 
cgit v1.2.3-70-g09d2


From bf1777b93be0707e17e3b3c0ca6c965facebfe14 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 27 Aug 2023 02:50:01 -0400
Subject: fixed filters to filter by linkedTo instead of lat/lng.  made links
 to pushpins when anything is added to sidebar and pushpin is selected

---
 src/client/documents/Documents.ts        |  32 +++++---
 src/client/views/MainView.tsx            |  40 +++++++++-
 src/client/views/SidebarAnnos.tsx        |   8 +-
 src/client/views/nodes/MapBox/MapBox.tsx | 127 ++++++++++++++++---------------
 src/client/views/pdf/PDFViewer.tsx       |   2 +-
 src/fields/Doc.ts                        |   6 +-
 src/fields/documentSchemas.ts            |  11 ++-
 7 files changed, 140 insertions(+), 86 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index add12896e..ceee8c76f 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1075,8 +1075,8 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.MAP), new List(documents), options);
         }
 
-        export function PushpinDocument(lat: number, lng: number, infoWindowOpen: boolean, documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.PUSHPIN), new List(documents), { latitude: lat, longitude: lng, infoWindowOpen, ...options }, id);
+        export function PushpinDocument(latitude: number, longitude: number, infoWindowOpen: boolean, documents: Array<Doc>, options: DocumentOptions, id?: string) {
+            return InstanceFromProto(Prototypes.get(DocumentType.PUSHPIN), new List(documents), { latitude, longitude, infoWindowOpen, ...options }, id);
         }
 
         // shouldn't ever need to create a KVP document-- instead set the LayoutTemplateString to be a KeyValueBox for the DocumentView (see addDocTab in TabDocView)
@@ -1097,9 +1097,6 @@ export namespace Docs {
         export function HTMLMarkerDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Freeform }, id);
         }
-        export function MapMarkerDocument(lat: number, lng: number, infoWindowOpen: boolean, documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { latitude: lat, longitude: lng, infoWindowOpen, ...options, _type_collection: CollectionViewType.Freeform }, id);
-        }
 
         export function PileDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
             return InstanceFromProto(
@@ -1274,10 +1271,23 @@ export namespace DocUtils {
                   if (d.cookies && (!filterFacets.cookies || !Object.keys(filterFacets.cookies).some(key => d.cookies === key))) {
                       return false;
                   }
-
                   for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== 'cookies' && fkey !== Utils.noDragsDocFilter.split(Doc.FilterSep)[0])) {
                       const facet = filterFacets[facetKey];
 
+                      let links = true;
+                      const linkedTo = filterFacets['-linkedTo'] && Array.from(Object.keys(filterFacets['-linkedTo']))?.[0];
+                      const linkedToField = filterFacets['-linkedTo']?.[linkedTo];
+                      const allLinks = linkedTo && linkedToField ? LinkManager.Instance.getAllRelatedLinks(d) : [];
+                      // prettier-ignore
+                      if (linkedTo) {
+                          if (allLinks.some(d => linkedTo === Field.toScriptString(DocCast(DocCast(d.link_anchor_1)?.[linkedToField]))) || //
+                           allLinks.some(d => linkedTo === Field.toScriptString(DocCast(DocCast(d.link_anchor_2)?.[linkedToField]))))
+                          {
+                              links = true;
+                          } 
+                          else links = false
+                      }
+
                       // facets that match some value in the field of the document (e.g. some text field)
                       const matches = Object.keys(facet).filter(value => value !== 'cookies' && facet[value] === 'match');
 
@@ -1293,7 +1303,7 @@ export namespace DocUtils {
                       // facets that have an x next to them
                       const xs = Object.keys(facet).filter(value => facet[value] === 'x');
 
-                      if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true;
+                      if (!linkedTo && !unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true;
                       const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value));
                       const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value));
                       const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined);
@@ -1312,11 +1322,11 @@ export namespace DocUtils {
                             });
                       // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria
                       if (parentCollection?.childFilters_boolean === 'OR') {
-                          if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
+                          if (links && satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true;
                       }
                       // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria
                       else {
-                          if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
+                          if (!links || !satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false;
                       }
                   }
                   return parentCollection?.childFilters_boolean === 'OR' ? false : true;
@@ -1800,8 +1810,8 @@ export namespace DocUtils {
                 const longitude = result.exifData?.data?.GPSLongitude;
                 const longitudeDirection = result.exifData?.data?.GPSLongitudeRef;
                 if (latitude !== undefined && longitude !== undefined && latitudeDirection !== undefined && longitudeDirection !== undefined) {
-                    proto.lat = ConvertDMSToDD(latitude[0], latitude[1], latitude[2], latitudeDirection);
-                    proto.lng = ConvertDMSToDD(longitude[0], longitude[1], longitude[2], longitudeDirection);
+                    proto.latitude = ConvertDMSToDD(latitude[0], latitude[1], latitude[2], latitudeDirection);
+                    proto.longitude = ConvertDMSToDD(longitude[0], longitude[1], longitude[2], longitudeDirection);
                 }
             }
             if (Upload.isVideoInformation(result)) {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 344a401f3..2a9f0cc02 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -60,6 +60,7 @@ import { ImageBox } from './nodes/ImageBox';
 import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
 import { LinkDocPreview } from './nodes/LinkDocPreview';
 import { MapAnchorMenu } from './nodes/MapBox/MapAnchorMenu';
+import { MapBox } from './nodes/MapBox/MapBox';
 import { RadialMenu } from './nodes/RadialMenu';
 import { TaskCompletionBox } from './nodes/TaskCompletedBox';
 import { OverlayView } from './OverlayView';
@@ -956,6 +957,42 @@ export class MainView extends React.Component {
     @computed get linkDocPreview() {
         return LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : null;
     }
+    @observable mapBoxHackBool = false;
+    @computed get mapBoxHack() {
+        return this.mapBoxHackBool ? null : (
+            <MapBox
+                ref={action((r: any) => r && (this.mapBoxHackBool = true))}
+                fieldKey="data"
+                select={returnFalse}
+                isSelected={returnFalse}
+                Document={this.headerBarDoc}
+                DataDoc={undefined}
+                addDocTab={returnFalse}
+                pinToPres={emptyFunction}
+                docViewPath={returnEmptyDoclist}
+                styleProvider={DefaultStyleProvider}
+                rootSelected={returnTrue}
+                addDocument={returnFalse}
+                removeDocument={returnFalse}
+                fitContentsToBox={returnTrue}
+                isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events)
+                isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive
+                ScreenToLocalTransform={Transform.Identity}
+                childHideResizeHandles={returnTrue}
+                childDragAction="move"
+                dontRegisterView={true}
+                PanelWidth={this.headerBarDocWidth}
+                PanelHeight={this.headerBarDocHeight}
+                renderDepth={0}
+                focus={emptyFunction}
+                whenChildContentsActiveChanged={emptyFunction}
+                bringToFront={emptyFunction}
+                childFilters={returnEmptyFilter}
+                childFiltersByRanges={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
+            />
+        );
+    }
 
     render() {
         return (
@@ -1011,7 +1048,7 @@ export class MainView extends React.Component {
                 <ContextMenu />
                 <RadialMenu />
                 <AnchorMenu />
-                <MapAnchorMenu/>
+                <MapAnchorMenu />
                 <DashFieldViewMenu />
                 <MarqueeOptionsMenu />
                 <TimelineMenu />
@@ -1020,6 +1057,7 @@ export class MainView extends React.Component {
                 {this.snapLines}
                 <LightboxView key="lightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} />
                 <OverlayView />
+                {this.mapBoxHack}
                 <GPTPopup key="gptpopup" />
                 <GenerativeFill imageEditorOpen={ImageBox.imageEditorOpen} imageEditorSource={ImageBox.imageEditorSource} imageRootDoc={ImageBox.imageRootDoc} addDoc={ImageBox.addDoc} />
                 {/* <NewLightboxView key="newLightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} /> */}
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 520485a71..c48a7241a 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -66,7 +66,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
         return '_' + this.sidebarKey + '_childFilters';
     }
 
-    anchorMenuClick = (anchor: Doc) => {
+    anchorMenuClick = (anchor: Doc, filterExlusions?: string[]) => {
         const startup = StrListCast(this.props.rootDoc.childFilters)
             .map(filter => filter.split(':')[0])
             .join(' ');
@@ -79,6 +79,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
             _layout_autoHeight: true,
             _text_fontSize: StrCast(Doc.UserDoc().fontSize),
             _text_fontFamily: StrCast(Doc.UserDoc().fontFamily),
+            target: 'HELLO' as any,
         });
         FormattedTextBox.SelectOnLoad = target[Id];
         FormattedTextBox.DontSelectInitialText = true;
@@ -87,7 +88,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
 
         const taggedContent = this.childFilters()
             .filter(data => data.split(':')[0])
-            .filter(data => data.split(':')[0] !== 'latitude' && data.split(':')[0] !== 'longitude')
+            .filter(data => !filterExlusions?.includes(data.split(':')[0]))
             .map(data => {
                 const key = data.split(':')[0];
                 const val = Field.Copy(this.allMetadata.get(key));
@@ -188,7 +189,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
     };
     render() {
         const renderTag = (tag: string) => {
-            const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`tags:${tag}:check`);
+            const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`tags::${tag}::check`);
             return (
                 <div key={tag} className={`sidebarAnnos-filterTag${active ? '-active' : ''}`} onClick={e => Doc.setDocFilter(this.props.rootDoc, 'tags', tag, 'check', true, this.sidebarKey, e.shiftKey)}>
                     {tag}
@@ -231,7 +232,6 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
                         .map(key => renderMeta(key, this.allMetadata.get(key)))} */}
                 </div>
 
-
                 <div style={{ width: '100%', height: `calc(100% - 38px)`, position: 'relative' }}>
                     <CollectionStackingView
                         {...this.props}
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 284e598c5..6f552953d 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -4,14 +4,16 @@ import { Button, EditableText, IconButton, Type } from 'browndash-components';
 import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc, DocListCast, Opt } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
 import { DocCss, Highlight, Width } from '../../../../fields/DocSymbols';
 import { InkTool } from '../../../../fields/InkField';
 import { DocCast, NumCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnOne, returnTrue, setupMoveUpEvents, Utils } from '../../../../Utils';
-import { Docs } from '../../../documents/Documents';
+import { Docs, DocUtils } from '../../../documents/Documents';
+import { DocumentType } from '../../../documents/DocumentTypes';
 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';
@@ -72,15 +74,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
 
     @observable private _marqueeing: number[] | undefined;
     @observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
-    @computed get inlineTextAnnotations() {
-        return this.allMapMarkers.filter(a => a.text_inlineAnnotations);
-    }
     @computed get allSidebarDocs() {
         return DocListCast(this.dataDoc[this.SidebarKey]);
     }
-    @computed get allMapMarkers() {
+    // this list contains pushpins and configs
+    @computed get allAnnotations() {
         return DocListCast(this.dataDoc[this.annotationKey]);
     }
+    @computed get allPushpins() {
+        return this.allAnnotations.filter(anno => anno.type === DocumentType.PUSHPIN);
+    }
     @computed get SidebarShown() {
         return this.layoutDoc._layout_showSidebar ? true : false;
     }
@@ -113,14 +116,20 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar();
         const docs = doc instanceof Doc ? [doc] : doc;
         docs.forEach(doc => {
-            if (doc.lat !== undefined && doc.lng !== undefined) {
-                const existingMarker = this.allMapMarkers.find(marker => marker.lat === doc.lat && marker.lng === doc.lng);
-                if (existingMarker) {
-                    Doc.AddDocToList(existingMarker, 'data', doc);
-                } else {
-                    const marker = Docs.Create.PushpinDocument(NumCast(doc.lat), NumCast(doc.lng), false, [doc], {});
-                    this.addDocument(marker, this.annotationKey);
-                }
+            let existingPin = this.allPushpins.find(pin => pin.latitude === doc.latitude && pin.longitude === doc.longitude) ?? this.selectedPin;
+            if (doc.latitude !== undefined && doc.longitude !== undefined && !existingPin) {
+                existingPin = this.createPushpin(NumCast(doc.latitude), NumCast(doc.longitude), StrCast(doc.map));
+            }
+            if (existingPin) {
+                setTimeout(() => {
+                    // we use a timeout in case this is called from the sidebar which may have just added a link that hasn't made its way into th elink manager yet
+                    if (!LinkManager.Instance.getAllRelatedLinks(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) {
+                        const anchor = this.getAnchor(true, undefined, existingPin);
+                        anchor && DocUtils.MakeLink(anchor, doc, { link_relationship: 'link to map location' });
+                        doc.latitude = existingPin?.latitude;
+                        doc.longitude = existingPin?.longitude;
+                    }
+                });
             }
         }); //add to annotation list
 
@@ -199,7 +208,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     createNoteAnnotation = () => {
         const createFunc = undoable(
             action(() => {
-                const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(false));
+                const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(false), ['latitude', 'longitude', '-linkedTo']);
                 if (note && this.selectedPin) {
                     note.latitude = this.selectedPin.latitude;
                     note.longitude = this.selectedPin.longitude;
@@ -309,7 +318,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     @action
     createPushpin = undoable((latitude: number, longitude: number, map?: string) => {
         // Stores the pushpin as a MapMarkerDocument
-        const mapMarker = Docs.Create.PushpinDocument(
+        const pushpin = Docs.Create.PushpinDocument(
             NumCast(latitude),
             NumCast(longitude),
             false,
@@ -317,8 +326,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             { map: map }
             // ,'pushpinIDamongus'+ this.incrementer++
         );
-        this.addDocument(mapMarker, this.annotationKey);
-
+        this.addDocument(pushpin, this.annotationKey);
+        return pushpin;
         // mapMarker.infoWindowOpen = true;
     }, 'createpin');
 
@@ -331,6 +340,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             // Removes filter
             Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove');
             Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove');
+            Doc.setDocFilter(this.rootDoc, '-linkedTo', Field.toString(DocCast(this.selectedPin.mapPin)), 'removeAll');
 
             const temp = this.selectedPin;
             this._bingMap.current.entities.remove(this.map_docToPinMap.get(temp));
@@ -356,8 +366,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         this.selectedPin = pinDoc;
         this.bingSearchBarContents = pinDoc.map;
 
-        Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match');
-        Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match');
+        // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match');
+        // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match');
+        Doc.setDocFilter(this.rootDoc, '-linkedTo', Field.toScriptString(this.selectedPin), 'mapPin' as any);
 
         this.recolorPin(this.selectedPin, 'green');
 
@@ -374,13 +385,6 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true);
     };
 
-    /**
-     * Returns a list of Pushpin docs
-     */
-    @computed get allMapPushpins() {
-        return DocListCast(this.dataDoc[this.annotationKey]);
-    }
-
     /**
      * Map OnClick
      */
@@ -429,20 +433,20 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     /*
      * Returns doc w/ relevant info
      */
-    getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
+    getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps, existingPin?: Doc) => {
         /// this should use SELECTED pushpin for lat/long  if there is a selection, otherwise CENTER
         const anchor = Docs.Create.ConfigDocument({
             title: 'MapAnchor:' + this.rootDoc.title,
             text: StrCast(this.selectedPin?.map) || StrCast(this.rootDoc.map) || 'map location',
-            config_latitude: NumCast(this.selectedPin?.latitude ?? this.dataDoc.latitude),
-            config_longitude: NumCast(this.selectedPin?.longitude ?? this.dataDoc.longitude),
+            config_latitude: NumCast((existingPin ?? this.selectedPin)?.latitude ?? this.dataDoc.latitude),
+            config_longitude: NumCast((existingPin ?? this.selectedPin)?.longitude ?? this.dataDoc.longitude),
             config_map_zoom: NumCast(this.dataDoc.map_zoom),
             config_map_type: StrCast(this.dataDoc.map_type),
-            config_map: StrCast(this.selectedPin?.map) || StrCast(this.dataDoc.map),
+            config_map: StrCast((existingPin ?? this.selectedPin)?.map) || StrCast(this.dataDoc.map),
             layout_unrendered: true,
         });
         if (anchor) {
-            anchor.mapPin = this.selectedPin;
+            anchor.mapPin = existingPin ?? this.selectedPin;
             if (!addAsAnnotation) anchor.backgroundColor = 'transparent';
             /* addAsAnnotation &&*/ this.addDocument(anchor);
             PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.rootDoc);
@@ -495,6 +499,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             // Removes filter
             Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove');
             Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove');
+            Doc.setDocFilter(this.rootDoc, '-linkedTo', Field.toString(DocCast(this.selectedPin.mapPin)), 'removeAll');
 
             this.removePushpin(this.selectedPin);
         }
@@ -587,16 +592,16 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             { fireImmediately: true }
         );
         this._disposers.highlight = reaction(
-            () => this.allMapPushpins.map(doc => doc[Highlight]),
+            () => this.allAnnotations.map(doc => doc[Highlight]),
             () => {
-                const allPins = this.allMapPushpins.map(doc => ({ doc, pushpin: DocCast(doc.mapPin) })).filter(pair => pair.pushpin);
-                allPins.forEach(({ doc, pushpin }) => {
+                const allConfigPins = this.allAnnotations.map(doc => ({ doc, pushpin: DocCast(doc.mapPin) })).filter(pair => pair.pushpin);
+                allConfigPins.forEach(({ doc, pushpin }) => {
                     if (!pushpin[Highlight] && this.map_pinHighlighted.get(pushpin)) {
                         this.recolorPin(pushpin);
                         this.map_pinHighlighted.delete(pushpin);
                     }
                 });
-                allPins.forEach(({ doc, pushpin }) => {
+                allConfigPins.forEach(({ doc, pushpin }) => {
                     if (doc[Highlight] && !this.map_pinHighlighted.get(pushpin)) {
                         this.recolorPin(pushpin, 'orange');
                         this.map_pinHighlighted.set(pushpin, true);
@@ -737,30 +742,32 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                     <div>
                         {!this._mapReady
                             ? null
-                            : this.allMapPushpins.map(pushpin => (
-                                  <DocumentView
-                                      {...this.props}
-                                      renderDepth={this.props.renderDepth + 1}
-                                      Document={pushpin}
-                                      DataDoc={undefined}
-                                      PanelWidth={returnOne}
-                                      PanelHeight={returnOne}
-                                      NativeWidth={returnOne}
-                                      NativeHeight={returnOne}
-                                      onKey={undefined}
-                                      onDoubleClick={undefined}
-                                      onBrowseClick={undefined}
-                                      childFilters={returnEmptyFilter}
-                                      childFiltersByRanges={returnEmptyFilter}
-                                      searchFilterDocs={returnEmptyDoclist}
-                                      isDocumentActive={returnFalse}
-                                      isContentActive={returnFalse}
-                                      addDocTab={returnFalse}
-                                      ScreenToLocalTransform={Transform.Identity}
-                                      fitContentsToBox={undefined}
-                                      focus={returnOne}
-                                  />
-                              ))}
+                            : this.allAnnotations
+                                  .filter(anno => !anno.layout_unrendered)
+                                  .map(pushpin => (
+                                      <DocumentView
+                                          {...this.props}
+                                          renderDepth={this.props.renderDepth + 1}
+                                          Document={pushpin}
+                                          DataDoc={undefined}
+                                          PanelWidth={returnOne}
+                                          PanelHeight={returnOne}
+                                          NativeWidth={returnOne}
+                                          NativeHeight={returnOne}
+                                          onKey={undefined}
+                                          onDoubleClick={undefined}
+                                          onBrowseClick={undefined}
+                                          childFilters={returnEmptyFilter}
+                                          childFiltersByRanges={returnEmptyFilter}
+                                          searchFilterDocs={returnEmptyDoclist}
+                                          isDocumentActive={returnFalse}
+                                          isContentActive={returnFalse}
+                                          addDocTab={returnFalse}
+                                          ScreenToLocalTransform={Transform.Identity}
+                                          fitContentsToBox={undefined}
+                                          focus={returnOne}
+                                      />
+                                  ))}
                     </div>
                     {/* <MapBoxInfoWindow
                                     key={Docs.Create.MapMarkerDocument(NumCast(40), NumCast(40), false, [], {})[Id]}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 395fbd1ca..c3027f51f 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -46,7 +46,7 @@ interface IViewerProps extends FieldViewProps {
     sidebarAddDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean;
     loaded?: (nw: number, nh: number, np: number) => void;
     setPdfViewer: (view: PDFViewer) => void;
-    anchorMenuClick?: () => undefined | ((anchor: Doc, summarize?: boolean) => void);
+    anchorMenuClick?: () => undefined | ((anchor: Doc) => void);
     crop: (region: Doc | undefined, addCrop?: boolean) => Doc | undefined;
 }
 
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 7ba4f0e6f..501114157 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1483,14 +1483,14 @@ export namespace Doc {
     // filters document in a container collection:
     // all documents with the specified value for the specified key are included/excluded
     // based on the modifiers :"check", "x", undefined
-    export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers: 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) {
+    export function setDocFilter(container: Opt<Doc>, key: string, value: any, modifiers: 'removeAll' | 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) {
         if (!container) return;
         const filterField = '_' + (fieldPrefix ? fieldPrefix + '_' : '') + 'childFilters';
         const childFilters = StrListCast(container[filterField]);
         runInAction(() => {
             for (let i = 0; i < childFilters.length; i++) {
                 const fields = childFilters[i].split(FilterSep); // split key:value:modifier
-                if (fields[0] === key && (fields[1] === value.toString() || modifiers === 'match' || (fields[2] === 'match' && modifiers === 'remove'))) {
+                if (fields[0] === key && (fields[1] === value.toString() || modifiers === 'match' || modifiers === 'removeAll' || (fields[2] === 'match' && modifiers === 'remove'))) {
                     if (fields[2] === modifiers && modifiers && fields[1] === value.toString()) {
                         if (toggle) modifiers = 'remove';
                         else return;
@@ -1502,7 +1502,7 @@ export namespace Doc {
             }
             if (!childFilters.length && modifiers === 'match' && value === undefined) {
                 container[filterField] = undefined;
-            } else if (modifiers !== 'remove') {
+            } else if (modifiers !== 'remove' && modifiers !== 'removeAll') {
                 !append && (childFilters.length = 0);
                 childFilters.push(key + FilterSep + value + FilterSep + modifiers);
                 container[filterField] = new List<string>(childFilters);
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index e33a17416..8eeb52709 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -1,8 +1,7 @@
-import { makeInterface, createSchema, listSpec } from './Schema';
-import { ScriptField } from './ScriptField';
-import { Doc } from './Doc';
 import { DateField } from './DateField';
-import { SchemaHeaderField } from './SchemaHeaderField';
+import { Doc } from './Doc';
+import { createSchema, listSpec, makeInterface } from './Schema';
+import { ScriptField } from './ScriptField';
 
 export const documentSchema = createSchema({
     // content properties
@@ -26,8 +25,8 @@ export const documentSchema = createSchema({
     z: 'number', // z "coordinate" - non-zero specifies the overlay layer of a freeformview
     zIndex: 'number', // zIndex of a document in a freeform view
     _layout_scrollTop: 'number', // scroll position of a scrollable document (pdf, text, web)
-    lat: 'number',
-    lng: 'number',
+    latitude: 'number',
+    longitude: 'number',
 
     // appearance properties on the layout
     '_backgroundGrid-spacing': 'number', // the size of the grid for collection views
-- 
cgit v1.2.3-70-g09d2

