From cc4a500d6d3c941d139e6c07dbf76c4eed9c3280 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 29 Mar 2022 10:58:31 -0400
Subject: added a backlinks property category.  fixed context property category
 to update without using search.  fixed double tap on links button to always
 show linkpivot doc.  fixed dragging docs to a tab to not switch to tab
 dragging mode.

---
 .../views/PropertiesDocBacklinksSelector.tsx       | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 src/client/views/PropertiesDocBacklinksSelector.tsx

(limited to 'src/client/views/PropertiesDocBacklinksSelector.tsx')

diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
new file mode 100644
index 000000000..5ffa93961
--- /dev/null
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -0,0 +1,46 @@
+import { computed } from "mobx";
+import { observer } from "mobx-react";
+import * as React from "react";
+import { Doc, DocListCast } from "../../fields/Doc";
+import { Id } from "../../fields/FieldSymbols";
+import { Cast, NumCast, StrCast } from "../../fields/Types";
+import { LinkManager } from "../util/LinkManager";
+import { CollectionDockingView } from "./collections/CollectionDockingView";
+import { CollectionViewType } from "./collections/CollectionView";
+import './PropertiesDocContextSelector.scss';
+
+type PropertiesDocBacklinksSelectorProps = {
+    Document: Doc,
+    Stack?: any,
+    hideTitle?: boolean,
+    addDocTab(doc: Doc, location: string): void
+};
+
+@observer
+export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDocBacklinksSelectorProps> {
+    @computed get _docs() {
+        const linkSource = this.props.Document;
+        const links = DocListCast(linkSource.links);
+        const collectedLinks = [] as Doc[];
+        links.map(link => {
+            const other = LinkManager.getOppositeAnchor(link, linkSource);
+            const otherdoc = !other ? undefined : other.annotationOn ? Cast(other.annotationOn, Doc, null) : other;
+            if (otherdoc && !collectedLinks.some(d => Doc.AreProtosEqual(d, otherdoc))) {
+                collectedLinks.push(otherdoc);
+            }
+        });
+        return collectedLinks;
+    }
+
+    getOnClick = (col: Doc) => {
+        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+        this.props.addDocTab(col, "add:right");
+    }
+
+    render() {
+        return <div>
+            {this.props.hideTitle ? (null) : <p key="contexts">Contexts:</p>}
+            {this._docs.map(doc => <p key={doc[Id]}><a onClick={() => this.getOnClick(doc)}>{StrCast(doc.title)}</a></p>)}
+        </div>;
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From d5d472521229f006f4a95d5c019276ec0281ac57 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 31 Mar 2022 14:56:03 -0400
Subject: cleaned up addDocTab for properties views to allow toggling of
 targets

---
 src/client/views/DocumentDecorations.tsx            | 16 +++++++++-------
 src/client/views/MainView.tsx                       | 20 ++++++++++++++++----
 src/client/views/PropertiesDocBacklinksSelector.tsx |  4 +---
 src/client/views/PropertiesDocContextSelector.tsx   | 11 +++++++----
 src/client/views/PropertiesView.tsx                 |  7 ++++---
 src/client/views/collections/TabDocView.tsx         |  6 ++----
 6 files changed, 39 insertions(+), 25 deletions(-)

(limited to 'src/client/views/PropertiesDocBacklinksSelector.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 328b8ab88..8cd646935 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -83,16 +83,18 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
         } else if (this._titleControlString.startsWith("#")) {
             const titleFieldKey = this._titleControlString.substring(1);
             UndoManager.RunInBatch(() => titleFieldKey && SelectionManager.Views().forEach(d => {
-                titleFieldKey === "title" && (d.dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-"));
+                if (titleFieldKey === "title") {
+                    d.dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-");
+                    if (StrCast(d.rootDoc.title).startsWith("@") && !this._accumulatedTitle.startsWith("@")) {
+                        Doc.RemoveDocFromList(Doc.UserDoc(), "myPublishedDocs", d.rootDoc);
+                    }
+                    if (!StrCast(d.rootDoc.title).startsWith("@") && this._accumulatedTitle.startsWith("@")) {
+                        Doc.AddDocToList(Doc.UserDoc(), "myPublishedDocs", d.rootDoc);
+                    }
+                }
                 //@ts-ignore
                 const titleField = (+this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle);
-                if (titleFieldKey === "title" && StrCast(d.rootDoc.title).startsWith("@") && !this._accumulatedTitle.startsWith("@")) {
-                    Doc.RemoveDocFromList(Doc.UserDoc(), "myPublishedDocs", SelectionManager.Docs().lastElement());
-                }
                 Doc.SetInPlace(d.rootDoc, titleFieldKey, titleField, true);
-                if (titleFieldKey === "title" && this._accumulatedTitle.startsWith("@")) {
-                    Doc.AddDocToList(Doc.UserDoc(), "myPublishedDocs", SelectionManager.Docs().lastElement());
-                }
 
                 if (d.rootDoc.syncLayoutFieldWithTitle) {
                     const title = titleField.toString();
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7cb40f701..5e68832fc 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -329,9 +329,21 @@ export class MainView extends React.Component {
 
     sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1);
     mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0);
-    addDocTabFunc = (doc: Doc, where: string): boolean => {
-        return where === "close" ? CollectionDockingView.CloseSplit(doc) :
-            doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : CollectionDockingView.AddSplit(doc, "right");
+    addDocTabFunc = (doc: Doc, location: string): boolean => {
+        const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":");
+        const locationParams = locationFields.length > 1 ? locationFields[1] : "";
+        if (doc.dockingConfig) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+        switch (locationFields[0]) {
+            case "dashboard": return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+            case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
+            case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
+            case "lightbox": return LightboxView.AddDocTab(doc, location);
+            case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams);
+            case "inPlace":
+            case "add":
+            default:
+                return CollectionDockingView.AddSplit(doc, locationParams);
+        }
     }
 
 
@@ -440,7 +452,7 @@ export class MainView extends React.Component {
                         <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.colorScheme === ColorScheme.Dark ? Colors.WHITE : Colors.BLACK} size="sm" />
                     </div>
                     <div className="properties-container" style={{ width: this.propertiesWidth() }}>
-                        {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
+                        {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={this.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
                     </div>
                 </div>
             </div>
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index 5ffa93961..ea0d90e04 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -5,8 +5,6 @@ import { Doc, DocListCast } from "../../fields/Doc";
 import { Id } from "../../fields/FieldSymbols";
 import { Cast, NumCast, StrCast } from "../../fields/Types";
 import { LinkManager } from "../util/LinkManager";
-import { CollectionDockingView } from "./collections/CollectionDockingView";
-import { CollectionViewType } from "./collections/CollectionView";
 import './PropertiesDocContextSelector.scss';
 
 type PropertiesDocBacklinksSelectorProps = {
@@ -34,7 +32,7 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
 
     getOnClick = (col: Doc) => {
         col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
-        this.props.addDocTab(col, "add:right");
+        this.props.addDocTab(col, "toggle:right");
     }
 
     render() {
diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx
index 45a8b6bf6..4d803f992 100644
--- a/src/client/views/PropertiesDocContextSelector.tsx
+++ b/src/client/views/PropertiesDocContextSelector.tsx
@@ -6,10 +6,11 @@ import { Id } from "../../fields/FieldSymbols";
 import { Cast, NumCast, StrCast } from "../../fields/Types";
 import { CollectionDockingView } from "./collections/CollectionDockingView";
 import { CollectionViewType } from "./collections/CollectionView";
+import { DocumentView } from "./nodes/DocumentView";
 import './PropertiesDocContextSelector.scss';
 
 type PropertiesDocContextSelectorProps = {
-    Document: Doc,
+    DocView?: DocumentView,
     Stack?: any,
     hideTitle?: boolean,
     addDocTab(doc: Doc, location: string): void
@@ -18,9 +19,11 @@ type PropertiesDocContextSelectorProps = {
 @observer
 export class PropertiesDocContextSelector extends React.Component<PropertiesDocContextSelectorProps> {
     @computed get _docs() {
-        const target = this.props.Document;
+        if (!this.props.DocView) return [];
+        const target = this.props.DocView.props.Document;
+        const targetContext = this.props.DocView.props.ContainingCollectionDoc;
         const aliases = DocListCast(target.aliases);
-        const containerProtos = aliases.filter(alias => alias.context).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set<Doc>());
+        const containerProtos = aliases.filter(alias => alias.context && alias.context instanceof Doc && Cast(alias.context, Doc, null) !== targetContext).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set<Doc>());
         const containerSets = Array.from(containerProtos.keys()).map(container => DocListCast(container.aliases));
         const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>());
         const doclayoutSets = Array.from(containers.keys()).map(dp => DocListCast(dp.aliases));
@@ -34,7 +37,7 @@ export class PropertiesDocContextSelector extends React.Component<PropertiesDocC
             col._panX = NumCast(target.x) + NumCast(target._width) / 2;
             col._panY = NumCast(target.y) + NumCast(target._height) / 2;
         }
-        this.props.addDocTab(col, "add:right");
+        this.props.addDocTab(col, "toggle:right");
     }
 
     render() {
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 8e1e9ea15..91cf83619 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -44,6 +44,7 @@ interface PropertiesViewProps {
     width: number;
     height: number;
     styleProvider?: StyleProviderFunc;
+    addDocTab: (doc: Doc, where: string) => boolean;
 }
 
 @observer
@@ -279,11 +280,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get contexts() {
-        return !this.selectedDoc ? (null) : <PropertiesDocContextSelector Document={this.selectedDoc} hideTitle={true} addDocTab={(doc, where) => CollectionDockingView.AddSplit(doc, "right")} />;
+        return !this.selectedDoc ? (null) : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this.props.addDocTab} />;
     }
 
     @computed get links() {
-        return !this.selectedDoc ? (null) : <PropertiesDocBacklinksSelector Document={this.selectedDoc} hideTitle={true} addDocTab={(doc, where) => CollectionDockingView.AddSplit(doc, "right")} />;
+        return !this.selectedDoc ? (null) : <PropertiesDocBacklinksSelector Document={this.selectedDoc} hideTitle={true} addDocTab={this.props.addDocTab} />;
     }
 
     @computed get layoutPreview() {
@@ -1077,7 +1078,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             <div className="propertiesView-contexts-title"
                 onPointerDown={action(() => this.openContexts = !this.openContexts)}
                 style={{ backgroundColor: this.openContexts ? "black" : "" }}>
-                Contexts
+                Other Contexts
                 <div className="propertiesView-contexts-title-icon">
                     <FontAwesomeIcon icon={this.openContexts ? "caret-down" : "caret-right"} size="lg" color="white" />
                 </div>
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index d52746d11..8b5022593 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -298,10 +298,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
             case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
             case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
-            case "lightbox": {
-                // TabDocView.PinDoc(doc, { hidePresBox: true });
-                return LightboxView.AddDocTab(doc, location);
-            }
+            case "lightbox": return LightboxView.AddDocTab(doc, location);
+            case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack);
             case "inPlace":
             case "add":
             default:
-- 
cgit v1.2.3-70-g09d2


From af8df1fc1af11318cadf1b71373bef776461a5cc Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 6 Apr 2022 10:42:36 -0400
Subject: uses linkMenu in propertiesWindow now.  updated linkMenu api, changed
 layout, made groups collapsible

---
 src/client/views/MainView.tsx                      |  2 +-
 .../views/PropertiesDocBacklinksSelector.scss      |  5 +++++
 .../views/PropertiesDocBacklinksSelector.tsx       | 25 ++++++++++++++--------
 src/client/views/SidebarAnnos.tsx                  |  2 +-
 src/client/views/linking/LinkMenu.scss             |  9 +++++---
 src/client/views/linking/LinkMenu.tsx              | 10 +++++----
 src/client/views/linking/LinkMenuGroup.tsx         | 11 +++++++---
 src/client/views/linking/LinkMenuItem.scss         | 14 ++++++++----
 src/client/views/linking/LinkMenuItem.tsx          | 15 ++++++++-----
 src/client/views/nodes/LinkDocPreview.tsx          |  2 +-
 10 files changed, 64 insertions(+), 31 deletions(-)
 create mode 100644 src/client/views/PropertiesDocBacklinksSelector.scss

(limited to 'src/client/views/PropertiesDocBacklinksSelector.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 5e68832fc..a67cb3014 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -631,7 +631,7 @@ export class MainView extends React.Component {
             <ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
             {this.topbar}
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
-            {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)}
+            {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
             <div style={{ position: "relative", display: LightboxView.LightboxDoc ? "none" : undefined, zIndex: 2001 }} >
                 <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} />
diff --git a/src/client/views/PropertiesDocBacklinksSelector.scss b/src/client/views/PropertiesDocBacklinksSelector.scss
new file mode 100644
index 000000000..4d2a61c3b
--- /dev/null
+++ b/src/client/views/PropertiesDocBacklinksSelector.scss
@@ -0,0 +1,5 @@
+.propertiesView-contexts-content {
+    .linkMenu {
+        position: relative;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index ea0d90e04..082492671 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -2,10 +2,12 @@ import { computed } from "mobx";
 import { observer } from "mobx-react";
 import * as React from "react";
 import { Doc, DocListCast } from "../../fields/Doc";
-import { Id } from "../../fields/FieldSymbols";
-import { Cast, NumCast, StrCast } from "../../fields/Types";
+import { Cast } from "../../fields/Types";
+import { DocumentType } from "../documents/DocumentTypes";
 import { LinkManager } from "../util/LinkManager";
-import './PropertiesDocContextSelector.scss';
+import { SelectionManager } from "../util/SelectionManager";
+import { LinkMenu } from "./linking/LinkMenu";
+import './PropertiesDocBacklinksSelector.scss';
 
 type PropertiesDocBacklinksSelectorProps = {
     Document: Doc,
@@ -22,7 +24,7 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
         const collectedLinks = [] as Doc[];
         links.map(link => {
             const other = LinkManager.getOppositeAnchor(link, linkSource);
-            const otherdoc = !other ? undefined : other.annotationOn ? Cast(other.annotationOn, Doc, null) : other;
+            const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
             if (otherdoc && !collectedLinks.some(d => Doc.AreProtosEqual(d, otherdoc))) {
                 collectedLinks.push(otherdoc);
             }
@@ -30,15 +32,20 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
         return collectedLinks;
     }
 
-    getOnClick = (col: Doc) => {
-        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
-        this.props.addDocTab(col, "toggle:right");
+    getOnClick = (link: Doc) => {
+        const linkSource = this.props.Document;
+        const other = LinkManager.getOppositeAnchor(link, linkSource);
+        const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
+
+        if (otherdoc) {
+            this.props.addDocTab(Doc.IsPrototype(otherdoc) ? Doc.MakeDelegate(otherdoc) : otherdoc, "toggle:right");
+        }
     }
 
     render() {
-        return <div>
+        return !SelectionManager.Views().length ? (null) : <div>
             {this.props.hideTitle ? (null) : <p key="contexts">Contexts:</p>}
-            {this._docs.map(doc => <p key={doc[Id]}><a onClick={() => this.getOnClick(doc)}>{StrCast(doc.title)}</a></p>)}
+            <LinkMenu docView={SelectionManager.Views().lastElement()} itemHandler={this.getOnClick} position={{ x: 0 }} />
         </div>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 62f6e388f..fae385660 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -61,7 +61,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
         FormattedTextBox.SelectOnLoad = target[Id];
         FormattedTextBox.DontSelectInitialText = true;
         this.allMetadata.map(tag => target[tag] = tag);
-        DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline markup", "annotation");
+        DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline markup");
         this.addDocument(target);
         this._stackRef.current?.focusDocument(target);
     }
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index 19c6463d3..77c16a28f 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -45,8 +45,11 @@
     }
 
     .linkMenu-group-name {
-        padding: 10px;
-
+        padding: 1px;
+        padding-left: 5px;
+        font-size: 10px;
+        font-style: italic;
+        font-weight: bold;
 
         &:hover {
             // p {
@@ -64,7 +67,7 @@
 
         p {
             width: 100%;
-            line-height: 12px;
+            line-height: 1;
             border-radius: 5px;
             text-transform: capitalize;
         }
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 53fe3f682..bc922be36 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -12,7 +12,8 @@ import React = require("react");
 
 interface Props {
     docView: DocumentView;
-    changeFlyout: () => void;
+    position?: { x?: number, y?: number };
+    itemHandler?: (doc: Doc) => void;
 }
 
 /**
@@ -25,7 +26,7 @@ export class LinkMenu extends React.Component<Props> {
     @observable _linkMenuRef = React.createRef<HTMLDivElement>();
 
     @computed get position() {
-        return ((dv) => ({ x: dv?.left || 0, y: dv?.top || 0, r: dv?.right || 0, b: dv?.bottom || 0 }))(this.props.docView.getBounds());
+        return this.props.position ?? (dv => ({ x: dv?.left || 0, y: (dv?.bottom || 0) + 15 }))(this.props.docView.getBounds());
     }
 
     componentDidMount() { document.addEventListener("pointerdown", this.onPointerDown); }
@@ -48,19 +49,20 @@ export class LinkMenu extends React.Component<Props> {
         const linkItems = Array.from(groups.entries()).map(group =>
             <LinkMenuGroup
                 key={group[0]}
+                itemHandler={this.props.itemHandler}
                 docView={this.props.docView}
                 sourceDoc={this.props.docView.props.Document}
                 group={group[1]}
                 groupType={group[0]}
                 showEditor={action(linkDoc => this._editingLink = linkDoc)} />);
 
-        return linkItems.length ? linkItems : [<p key="">No links have been created yet. Drag the linking button onto another document to create a link.</p>];
+        return linkItems.length ? linkItems : this.props.position ? [<></>] : [<p key="">No links have been created yet. Drag the linking button onto another document to create a link.</p>];
     }
 
     render() {
         const sourceDoc = this.props.docView.props.Document;
         return <div className="linkMenu" ref={this._linkMenuRef}
-            style={{ left: this.position.x, top: this.props.docView.topMost ? undefined : this.position.b + 15, bottom: this.props.docView.topMost ? 20 : undefined }}
+            style={{ left: this.position.x, top: this.props.docView.topMost ? undefined : this.position.y, bottom: this.props.docView.topMost ? 20 : undefined }}
         >
             {this._editingLink ?
                 <div className="linkMenu-listEditor">
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 03377ad4e..5b1e29e67 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -1,4 +1,5 @@
 import { observer } from "mobx-react";
+import { observable, action } from "mobx";
 import { Doc, StrListCast } from "../../../fields/Doc";
 import { Id } from "../../../fields/FieldSymbols";
 import { Cast } from "../../../fields/Types";
@@ -14,6 +15,7 @@ interface LinkMenuGroupProps {
     groupType: string;
     showEditor: (linkDoc: Doc) => void;
     docView: DocumentView;
+    itemHandler?: (doc: Doc) => void;
 }
 
 @observer
@@ -36,6 +38,8 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
         return color;
     }
 
+    @observable _collapsed = false;
+
     render() {
         const set = new Set<Doc>(this.props.group);
         const groupItems = Array.from(set.keys()).map(linkDoc => {
@@ -43,6 +47,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
                 LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, null).annotationOn === this.props.sourceDoc ? Cast(linkDoc.anchor2, Doc, null) : Cast(linkDoc.anchor1, Doc, null));
             if (destination && this.props.sourceDoc) {
                 return <LinkMenuItem key={linkDoc[Id]}
+                    itemHandler={this.props.itemHandler}
                     groupType={this.props.groupType}
                     docView={this.props.docView}
                     linkDoc={linkDoc}
@@ -55,12 +60,12 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
 
         return (
             <div className="linkMenu-group" ref={this._menuRef}>
-                <div className="linkMenu-group-name" style={{ background: this.getBackgroundColor() }}>
+                <div className="linkMenu-group-name" onClick={action(() => this._collapsed = !this._collapsed)} style={{ background: this.getBackgroundColor() }}>
                     <p className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"}> {this.props.groupType}:</p>
                 </div>
-                <div className="linkMenu-group-wrapper">
+                {this._collapsed ? (null) : <div className="linkMenu-group-wrapper">
                     {groupItems}
-                </div>
+                </div>}
             </div >
         );
     }
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index 90722daf9..8333aa374 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -9,8 +9,8 @@
     padding-left: 6.5px;
     padding-right: 2px;
 
-    padding-top: 6.5px;
-    padding-bottom: 6.5px;
+    padding-top: 1px;
+    padding-bottom: 1px;
 
     background-color: white;
 
@@ -18,10 +18,12 @@
     .linkMenu-name {
         position: relative;
         width: auto;
+        align-items: center;
+        display: flex;
 
         .linkMenu-text {
 
-            padding: 4px 2px;
+            // padding: 4px 2px;
             //display: inline;
 
             .linkMenu-source-title {
@@ -37,6 +39,8 @@
             .linkMenu-title-wrapper {
 
                 display: flex;
+                align-items: center;
+                min-height: 20px;
 
                 .destination-icon-wrapper {
                     //border: 0.5px solid rgb(161, 161, 161);
@@ -56,7 +60,8 @@
                 .linkMenu-destination-title {
                     text-decoration: none;
                     color: #4476F7;
-                    font-size: 16px;
+                    font-size: 13px;
+                    line-height: 0.9;
                     padding-bottom: 2px;
                     padding-right: 4px;
                     margin-right: 4px;
@@ -77,6 +82,7 @@
                 font-style: italic;
                 color: rgb(95, 97, 102);
                 font-size: 9px;
+                line-height: 0.9;
                 margin-left: 20px;
                 max-width: 125px;
                 height: auto;
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 96cc6d600..d6400a6b3 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -1,12 +1,12 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
-import { action, observable, runInAction } from 'mobx';
+import { action, observable } from 'mobx';
 import { observer } from "mobx-react";
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { Cast, StrCast } from '../../../fields/Types';
 import { WebField } from '../../../fields/URLField';
-import { emptyFunction, setupMoveUpEvents, returnFalse } from '../../../Utils';
+import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager } from '../../util/DragManager';
@@ -14,11 +14,10 @@ import { Hypothesis } from '../../util/HypothesisUtils';
 import { LinkManager } from '../../util/LinkManager';
 import { undoBatch } from '../../util/UndoManager';
 import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
-import { DocumentView, DocumentViewSharedProps } from '../nodes/DocumentView';
+import { DocumentView } from '../nodes/DocumentView';
 import { LinkDocPreview } from '../nodes/LinkDocPreview';
 import './LinkMenuItem.scss';
 import React = require("react");
-import { setup } from 'mocha';
 
 
 interface LinkMenuItemProps {
@@ -29,6 +28,7 @@ interface LinkMenuItemProps {
     destinationDoc: Doc;
     showEditor: (linkDoc: Doc) => void;
     menuRef: React.Ref<HTMLDivElement>;
+    itemHandler?: (doc: Doc) => void;
 }
 
 // drag links and drop link targets (aliasing them if needed)
@@ -98,7 +98,12 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
             emptyFunction,
             () => {
                 DocumentLinksButton.ClearLinkEditor();
-                LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false);
+                if (this.props.itemHandler) {
+
+                    this.props.itemHandler?.(this.props.linkDoc);
+                } else {
+                    LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false);
+                }
             });
     }
 
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 7637d39be..f5f773595 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -46,7 +46,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
         if (anchor1 && anchor2) {
             linkTarget = Doc.AreProtosEqual(anchor1, this._linkSrc) || Doc.AreProtosEqual(anchor1?.annotationOn as Doc, this._linkSrc) ? anchor2 : anchor1;
         }
-        if (linkTarget?.annotationOn) {
+        if (linkTarget?.annotationOn && linkTarget?.type !== DocumentType.RTF) { // want to show annotation context document if annotation is not text
             linkTarget && DocCastAsync(linkTarget.annotationOn).then(action(anno => this._targetDoc = anno));
         } else {
             this._targetDoc = linkTarget;
-- 
cgit v1.2.3-70-g09d2


From c6f2dc7f63b76ba0684e24aff8da138e00ae38ec Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 27 Apr 2022 23:39:16 -0400
Subject: unhide documents when viewing them from properties context/backlinks

---
 src/client/views/PropertiesDocBacklinksSelector.tsx | 1 +
 src/client/views/PropertiesDocContextSelector.tsx   | 1 +
 2 files changed, 2 insertions(+)

(limited to 'src/client/views/PropertiesDocBacklinksSelector.tsx')

diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index 082492671..dce3e35e8 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -38,6 +38,7 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
         const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
 
         if (otherdoc) {
+            otherdoc.hidden = false;
             this.props.addDocTab(Doc.IsPrototype(otherdoc) ? Doc.MakeDelegate(otherdoc) : otherdoc, "toggle:right");
         }
     }
diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx
index 015e0c8ee..1af706bb5 100644
--- a/src/client/views/PropertiesDocContextSelector.tsx
+++ b/src/client/views/PropertiesDocContextSelector.tsx
@@ -39,6 +39,7 @@ export class PropertiesDocContextSelector extends React.Component<PropertiesDocC
             col._panX = NumCast(target.x) + NumCast(target._width) / 2;
             col._panY = NumCast(target.y) + NumCast(target._height) / 2;
         }
+        col.hidden = false;
         this.props.addDocTab(col, "toggle:right");
         setTimeout(() => DocFocusOrOpen(Doc.GetProto(this.props.DocView!.props.Document), col), 100);
     }
-- 
cgit v1.2.3-70-g09d2


From 36261eac67ae6f872c9be2c9766d21ac24698f8e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 28 Apr 2022 01:37:27 -0400
Subject: fixed linkEditor to work when invoked from documentButtonsBar and
 properties sidebar is up.

---
 src/client/views/MainView.tsx                       |  2 +-
 src/client/views/PropertiesDocBacklinksSelector.tsx |  3 ++-
 src/client/views/linking/LinkMenu.tsx               | 20 ++++++++++++++------
 src/client/views/linking/LinkMenuGroup.tsx          |  2 ++
 src/client/views/linking/LinkMenuItem.tsx           |  6 +++---
 src/client/views/nodes/DocumentLinksButton.tsx      | 10 ++--------
 6 files changed, 24 insertions(+), 19 deletions(-)

(limited to 'src/client/views/PropertiesDocBacklinksSelector.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b73074899..c794c73db 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -632,7 +632,7 @@ export class MainView extends React.Component {
             <ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
             {this.topbar}
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
-            {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} /> : (null)}
+            {DocumentLinksButton.LinkEditorDocView ? <LinkMenu clearLinkEditor={action(() => DocumentLinksButton.LinkEditorDocView = undefined)} docView={DocumentLinksButton.LinkEditorDocView} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
             <div style={{ position: "relative", display: LightboxView.LightboxDoc ? "none" : undefined, zIndex: 2001 }} >
                 <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} />
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index dce3e35e8..4ead8eaf0 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -3,6 +3,7 @@ import { observer } from "mobx-react";
 import * as React from "react";
 import { Doc, DocListCast } from "../../fields/Doc";
 import { Cast } from "../../fields/Types";
+import { emptyFunction } from "../../Utils";
 import { DocumentType } from "../documents/DocumentTypes";
 import { LinkManager } from "../util/LinkManager";
 import { SelectionManager } from "../util/SelectionManager";
@@ -46,7 +47,7 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
     render() {
         return !SelectionManager.Views().length ? (null) : <div>
             {this.props.hideTitle ? (null) : <p key="contexts">Contexts:</p>}
-            <LinkMenu docView={SelectionManager.Views().lastElement()} itemHandler={this.getOnClick} position={{ x: 0 }} />
+            <LinkMenu docView={SelectionManager.Views().lastElement()} clearLinkEditor={emptyFunction} itemHandler={this.getOnClick} position={{ x: 0 }} />
         </div>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index bc922be36..a564c59d3 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -1,9 +1,10 @@
-import { action, computed, observable } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
 import { observer } from "mobx-react";
 import { Doc } from "../../../fields/Doc";
 import { LinkManager } from "../../util/LinkManager";
+import { SelectionManager } from "../../util/SelectionManager";
 import { DocumentLinksButton } from "../nodes/DocumentLinksButton";
-import { DocumentView, DocumentViewSharedProps } from "../nodes/DocumentView";
+import { DocumentView } from "../nodes/DocumentView";
 import { LinkDocPreview } from "../nodes/LinkDocPreview";
 import { LinkEditor } from "./LinkEditor";
 import './LinkMenu.scss';
@@ -14,6 +15,7 @@ interface Props {
     docView: DocumentView;
     position?: { x?: number, y?: number };
     itemHandler?: (doc: Doc) => void;
+    clearLinkEditor: () => void;
 }
 
 /**
@@ -21,7 +23,7 @@ interface Props {
  */
 @observer
 export class LinkMenu extends React.Component<Props> {
-    private _editorRef = React.createRef<HTMLDivElement>();
+    _editorRef = React.createRef<HTMLDivElement>();
     @observable _editingLink?: Doc;
     @observable _linkMenuRef = React.createRef<HTMLDivElement>();
 
@@ -29,16 +31,21 @@ export class LinkMenu extends React.Component<Props> {
         return this.props.position ?? (dv => ({ x: dv?.left || 0, y: (dv?.bottom || 0) + 15 }))(this.props.docView.getBounds());
     }
 
+    clear = action(() => {
+        this.props.clearLinkEditor();
+        this._editingLink = undefined;
+    });
+
     componentDidMount() { document.addEventListener("pointerdown", this.onPointerDown); }
     componentWillUnmount() { document.removeEventListener("pointerdown", this.onPointerDown); }
 
-    onPointerDown = (e: PointerEvent) => {
+    onPointerDown = action((e: PointerEvent) => {
         LinkDocPreview.Clear();
         if (!this._linkMenuRef.current?.contains(e.target as any) &&
             !this._editorRef.current?.contains(e.target as any)) {
-            DocumentLinksButton.ClearLinkEditor();
+            this.clear();
         }
-    }
+    });
 
     /**
      * maps each link to a JSX element to be rendered
@@ -54,6 +61,7 @@ export class LinkMenu extends React.Component<Props> {
                 sourceDoc={this.props.docView.props.Document}
                 group={group[1]}
                 groupType={group[0]}
+                clearLinkEditor={this.clear}
                 showEditor={action(linkDoc => this._editingLink = linkDoc)} />);
 
         return linkItems.length ? linkItems : this.props.position ? [<></>] : [<p key="">No links have been created yet. Drag the linking button onto another document to create a link.</p>];
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 5b1e29e67..fa6a2f506 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -13,6 +13,7 @@ interface LinkMenuGroupProps {
     sourceDoc: Doc;
     group: Doc[];
     groupType: string;
+    clearLinkEditor: () => void;
     showEditor: (linkDoc: Doc) => void;
     docView: DocumentView;
     itemHandler?: (doc: Doc) => void;
@@ -53,6 +54,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
                     linkDoc={linkDoc}
                     sourceDoc={this.props.sourceDoc}
                     destinationDoc={destination}
+                    clearLinkEditor={this.props.clearLinkEditor}
                     showEditor={this.props.showEditor}
                     menuRef={this._menuRef} />;
             }
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index d6400a6b3..3ddcf803d 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -13,7 +13,6 @@ import { DragManager } from '../../util/DragManager';
 import { Hypothesis } from '../../util/HypothesisUtils';
 import { LinkManager } from '../../util/LinkManager';
 import { undoBatch } from '../../util/UndoManager';
-import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
 import { DocumentView } from '../nodes/DocumentView';
 import { LinkDocPreview } from '../nodes/LinkDocPreview';
 import './LinkMenuItem.scss';
@@ -26,6 +25,7 @@ interface LinkMenuItemProps {
     docView: DocumentView;
     sourceDoc: Doc;
     destinationDoc: Doc;
+    clearLinkEditor: () => void;
     showEditor: (linkDoc: Doc) => void;
     menuRef: React.Ref<HTMLDivElement>;
     itemHandler?: (doc: Doc) => void;
@@ -92,12 +92,12 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 const eleClone: any = this._drag.current!.cloneNode(true);
                 eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`;
                 StartLinkTargetsDrag(eleClone, this.props.docView, e.x, e.y, this.props.sourceDoc, [this.props.linkDoc]);
-                DocumentLinksButton.ClearLinkEditor();
+                this.props.clearLinkEditor();
                 return true;
             },
             emptyFunction,
             () => {
-                DocumentLinksButton.ClearLinkEditor();
+                this.props.clearLinkEditor();
                 if (this.props.itemHandler) {
 
                     this.props.itemHandler?.(this.props.linkDoc);
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 46537df7e..9b79db319 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -1,21 +1,17 @@
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Tooltip } from "@material-ui/core";
-import { action, computed, observable, runInAction, trace } from "mobx";
+import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, Opt } from "../../../fields/Doc";
-import { Id } from "../../../fields/FieldSymbols";
-import { ScriptField } from "../../../fields/ScriptField";
 import { StrCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
 import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../../Utils";
-import { DocServer } from "../../DocServer";
-import { Docs, DocUtils } from "../../documents/Documents";
+import { DocUtils } from "../../documents/Documents";
 import { DragManager } from "../../util/DragManager";
 import { Hypothesis } from "../../util/HypothesisUtils";
 import { LinkManager } from "../../util/LinkManager";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { Colors } from "../global/globalEnums";
-import { LightboxView } from "../LightboxView";
 import './DocumentLinksButton.scss';
 import { DocumentView } from "./DocumentView";
 import { LinkDescriptionPopup } from "./LinkDescriptionPopup";
@@ -46,8 +42,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     @observable public static invisibleWebDoc: Opt<Doc>;
     public static invisibleWebRef = React.createRef<HTMLDivElement>();
 
-    @action public static ClearLinkEditor() { DocumentLinksButton.LinkEditorDocView = undefined; }
-
     @action @undoBatch
     onLinkButtonMoved = (e: PointerEvent) => {
         if (this.props.InMenu && this.props.StartLink) {
-- 
cgit v1.2.3-70-g09d2

