From 8264ac5484c0c7b5d47cb78ce60f5d6568e736d9 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sat, 4 Jul 2020 17:25:10 -0500
Subject: redesigned editing menu, added link descriptions and popup on created

---
 src/client/views/nodes/DocumentLinksButton.tsx | 52 +++++++++++++++++---------
 1 file changed, 34 insertions(+), 18 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index bfd860f65..5d1a68af5 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -11,6 +11,8 @@ import { DocUtils } from "../../documents/Documents";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { LinkDocPreview } from "./LinkDocPreview";
 import { LinkCreatedBox } from "./LinkCreatedBox";
+import { LinkDescriptionPopup } from "./LinkDescriptionPopup";
+import { LinkManager } from "../../util/LinkManager";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -54,6 +56,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         return false;
     }
 
+
     onLinkButtonDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
             if (doubleTap && this.props.InMenu) {
@@ -87,15 +90,22 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     //     Doc.UnBrushDoc(this.props.View.Document);
                     // });
                 } else {
-                    DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View &&
-                        DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
-
-                    runInAction(() => {
-                        LinkCreatedBox.popupX = e.screenX;
-                        LinkCreatedBox.popupY = e.screenY - 120;
-                        LinkCreatedBox.linkCreated = true;
-                        setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
-                    });
+
+                    if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
+                        const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
+                        LinkManager.currentLink = linkDoc;
+                        runInAction(() => {
+                            LinkCreatedBox.popupX = e.screenX;
+                            LinkCreatedBox.popupY = e.screenY - 33;
+                            LinkCreatedBox.linkCreated = true;
+
+                            LinkDescriptionPopup.popupX = e.screenX;
+                            LinkDescriptionPopup.popupY = e.screenY;
+                            LinkDescriptionPopup.descriptionPopup = true;
+
+                            setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                        });
+                    }
                 }
             }
         }));
@@ -109,15 +119,21 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             //     Doc.UnBrushDoc(this.props.View.Document);
             // });
         } else {
-            DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View &&
-                DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
-
-            runInAction(() => {
-                LinkCreatedBox.popupX = e.screenX;
-                LinkCreatedBox.popupY = e.screenY - 120;
-                LinkCreatedBox.linkCreated = true;
-                setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
-            });
+            if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
+                const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
+                LinkManager.currentLink = linkDoc;
+                runInAction(() => {
+                    LinkCreatedBox.popupX = e.screenX;
+                    LinkCreatedBox.popupY = e.screenY - 33;
+                    LinkCreatedBox.linkCreated = true;
+
+                    LinkDescriptionPopup.popupX = e.screenX;
+                    LinkDescriptionPopup.popupY = e.screenY;
+                    LinkDescriptionPopup.descriptionPopup = true;
+
+                    setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                });
+            }
         }
     }
 
-- 
cgit v1.2.3-70-g09d2


From 45fb8ba4be961f8b0b28cda05ceb5023f84cdb03 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sat, 4 Jul 2020 23:51:30 -0500
Subject: descriptions toggle and UI cleanup

---
 src/client/views/collections/CollectionLinearView.scss | 12 ++++++++++++
 src/client/views/collections/CollectionLinearView.tsx  | 14 ++++++++++++++
 src/client/views/nodes/DocumentLinksButton.tsx         | 14 ++++++++------
 src/client/views/nodes/LinkDescriptionPopup.scss       | 13 ++++++++++---
 src/client/views/nodes/LinkDescriptionPopup.tsx        |  3 +++
 5 files changed, 47 insertions(+), 9 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/collections/CollectionLinearView.scss b/src/client/views/collections/CollectionLinearView.scss
index 5ada79a28..b8b72e756 100644
--- a/src/client/views/collections/CollectionLinearView.scss
+++ b/src/client/views/collections/CollectionLinearView.scss
@@ -35,6 +35,18 @@
             font-size: 12.5px;
         }
 
+        .bottomPopup-descriptions {
+            display: inline;
+            white-space: nowrap;
+            padding-left: 8px;
+            padding-right: 8px;
+            vertical-align: middle;
+            background-color: lightgrey;
+            border-radius: 5.5px;
+            color: black;
+            margin-right: 5px;
+        }
+
         .bottomPopup-exit {
             display: inline;
             white-space: nowrap;
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 7cbe5c19d..35c28406a 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -15,6 +15,7 @@ import { documentSchema } from '../../../fields/documentSchemas';
 import { Id } from '../../../fields/FieldSymbols';
 import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { LinkDescriptionPopup } from '../nodes/LinkDescriptionPopup';
 
 
 type LinearDocument = makeInterface<[typeof documentSchema,]>;
@@ -89,6 +90,16 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
         DocumentLinksButton.StartLink = undefined;
     }
 
+    @action
+    changeDescriptionSetting = () => {
+        if (LinkDescriptionPopup.showDescriptions === "ON") {
+            LinkDescriptionPopup.showDescriptions = "OFF";
+            LinkDescriptionPopup.descriptionPopup = false;
+        } else {
+            LinkDescriptionPopup.showDescriptions = "ON";
+        }
+    }
+
     render() {
         const guid = Utils.GenerateGuid();
         const flexDir: any = StrCast(this.Document.flexDirection);
@@ -155,6 +166,9 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                     onPointerDown={e => e.stopPropagation()} >
                     <span className="bottomPopup-text" >
                         Creating link from: {DocumentLinksButton.StartLink.title} </span>
+                    <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}
+                    > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
+                    </span>
                     <span className="bottomPopup-exit" onClick={this.exitLongLinks}
                     >Exit</span>
 
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 5d1a68af5..544f5fd7f 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -96,11 +96,11 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                         LinkManager.currentLink = linkDoc;
                         runInAction(() => {
                             LinkCreatedBox.popupX = e.screenX;
-                            LinkCreatedBox.popupY = e.screenY - 33;
+                            LinkCreatedBox.popupY = e.screenY - 133;
                             LinkCreatedBox.linkCreated = true;
 
                             LinkDescriptionPopup.popupX = e.screenX;
-                            LinkDescriptionPopup.popupY = e.screenY;
+                            LinkDescriptionPopup.popupY = e.screenY - 100;
                             LinkDescriptionPopup.descriptionPopup = true;
 
                             setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
@@ -124,12 +124,14 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 LinkManager.currentLink = linkDoc;
                 runInAction(() => {
                     LinkCreatedBox.popupX = e.screenX;
-                    LinkCreatedBox.popupY = e.screenY - 33;
+                    LinkCreatedBox.popupY = e.screenY - 133;
                     LinkCreatedBox.linkCreated = true;
 
-                    LinkDescriptionPopup.popupX = e.screenX;
-                    LinkDescriptionPopup.popupY = e.screenY;
-                    LinkDescriptionPopup.descriptionPopup = true;
+                    if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
+                        LinkDescriptionPopup.popupX = e.screenX;
+                        LinkDescriptionPopup.popupY = e.screenY - 100;
+                        LinkDescriptionPopup.descriptionPopup = true;
+                    }
 
                     setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
                 });
diff --git a/src/client/views/nodes/LinkDescriptionPopup.scss b/src/client/views/nodes/LinkDescriptionPopup.scss
index 474bd919b..54002fd1b 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.scss
+++ b/src/client/views/nodes/LinkDescriptionPopup.scss
@@ -2,7 +2,7 @@
 
     display: flex;
 
-    border: 1px solid rgb(100, 100, 100);
+    border: 1px solid rgb(170, 26, 26);
 
     width: auto;
     position: absolute;
@@ -21,13 +21,19 @@
 
     .linkDescriptionPopup-input {
         float: left;
+        background-color: rgba(250, 250, 250, 0.95);
         color: rgb(100, 100, 100);
+        border: none;
+        min-width: 160px;
     }
 
     .linkDescriptionPopup-btn {
 
         float: right;
 
+        justify-content: center;
+        vertical-align: middle;
+
 
         .linkDescriptionPopup-btn-dismiss {
             background-color: white;
@@ -40,7 +46,8 @@
             font-size: 9px;
             text-align: center;
             position: relative;
-            transform: translateY(5px);
+            margin-right: 4px;
+            justify-content: center;
         }
 
         .linkDescriptionPopup-btn-add {
@@ -54,7 +61,7 @@
             font-size: 9px;
             text-align: center;
             position: relative;
-            transform: translateY(5px);
+            justify-content: center;
         }
     }
 
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx
index 078a738e7..3bb52d9fb 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.tsx
+++ b/src/client/views/nodes/LinkDescriptionPopup.tsx
@@ -4,12 +4,14 @@ import "./LinkDescriptionPopup.scss";
 import { observable, action } from "mobx";
 import { EditableView } from "../EditableView";
 import { LinkManager } from "../../util/LinkManager";
+import { LinkCreatedBox } from "./LinkCreatedBox";
 
 
 @observer
 export class LinkDescriptionPopup extends React.Component<{}> {
 
     @observable public static descriptionPopup: boolean = false;
+    @observable public static showDescriptions: string = "ON";
     @observable public static popupX: number = 700;
     @observable public static popupY: number = 350;
     @observable description: string = "";
@@ -37,6 +39,7 @@ export class LinkDescriptionPopup extends React.Component<{}> {
     onClick = (e: PointerEvent) => {
         if (this.popupRef && !!!this.popupRef.current?.contains(e.target as any)) {
             LinkDescriptionPopup.descriptionPopup = false;
+            LinkCreatedBox.linkCreated = false;
         }
     }
 
-- 
cgit v1.2.3-70-g09d2


From e7326c10d2f94c11dedec1d0a280579ba8fa7af0 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Mon, 6 Jul 2020 23:48:44 -0500
Subject: andy's UI changes

---
 src/client/views/linking/LinkMenu.scss         | 4 +++-
 src/client/views/linking/LinkMenuItem.scss     | 7 ++++---
 src/client/views/linking/LinkMenuItem.tsx      | 2 +-
 src/client/views/nodes/DocumentLinksButton.tsx | 8 ++++++--
 4 files changed, 14 insertions(+), 7 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index 4b9f5641a..b0c729cda 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -3,6 +3,7 @@
 .linkMenu {
     width: 100%;
     height: auto;
+    border: 1px solid black;
 
     &:hover {
         width: calc(auto + 26px);
@@ -10,11 +11,12 @@
 }
 
 .linkMenu-list {
+    border: 1px solid black;
     max-height: 200px;
     overflow-y: scroll;
     position: absolute;
     z-index: 10;
-    background: $link-color;
+    background: white;
     min-width: 150px;
     border-radius: 5px;
     padding-top: 6.5px;
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index 7fecc2820..67bf71fb9 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -16,7 +16,7 @@
 
             .linkMenu-destination-title {
                 text-decoration: none;
-                color: rgb(46, 82, 160);
+                color: rgb(85, 120, 196);
                 font-size: 14px;
                 padding-bottom: 2px;
             }
@@ -62,8 +62,9 @@
 
             .linkMenu-destination-title {
                 text-decoration: underline;
-                color: rgb(15, 57, 148);
-                display: inline;
+                color: rgb(60, 90, 156);
+                //display: inline;
+                text-overflow: break;
             }
 
             &.expand-two p {
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 9f6b47375..bd4024902 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -201,7 +201,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
                             <div title="Edit link" className="button" ref={this._editRef} onPointerDown={this.onEdit}>
-                                <FontAwesomeIcon className="fa-icon" icon="pencil-alt" size="sm" /></div>
+                                <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
                             <div title="Delete link" className="button" onPointerDown={this.deleteLink}>
                                 <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
                             {/* <div title="Follow link" className="button" onPointerDown={this.followDefault} onContextMenu={this.onContextMenu}>
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 544f5fd7f..7fb447cab 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -146,10 +146,14 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     @computed
     get linkButton() {
         const links = DocListCast(this.props.View.props.Document.links);
+
+        const title = this.props.InMenu ? "Drag or tap to create links" : "Tap to view links";
+
         return (!links.length || links[0].hidden) && !this.props.AlwaysOn ? (null) :
-            <div title="Drag(create link) Tap(view links)" ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
+            <div title={title} ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
                 <div className={"documentLinksButton"} style={{
-                    backgroundColor: DocumentLinksButton.StartLink ? "transparent" : "",
+                    backgroundColor: DocumentLinksButton.StartLink ? "transparent" : this.props.InMenu ? "black" : "",
+                    color: this.props.InMenu ? "white" : "black",
                     width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px", fontWeight: "bold"
                 }}
                     onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
-- 
cgit v1.2.3-70-g09d2


From 3beca8e7d268dc7b67b20b2c8760ea5e4b6fdb88 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Wed, 8 Jul 2020 18:59:37 -0500
Subject: added dashDragging event

---
 src/client/util/DragManager.ts                     | 48 ++++++++++++++++++++++
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 15 +++++++
 src/client/views/nodes/DocumentLinksButton.tsx     |  2 +-
 3 files changed, 64 insertions(+), 1 deletion(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 2ceafff30..64c3d8458 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -427,6 +427,54 @@ export namespace DragManager {
                 }, dragData.droppedDocuments);
             }
 
+            const target = document.elementFromPoint(e.x, e.y);
+
+            const complete = new DragCompleteEvent(false, dragData);
+
+            if (target) {
+                target.dispatchEvent(
+                    new CustomEvent<React.DragEvent>("dashDragging", {
+                        bubbles: true,
+                        detail: {
+                            shiftKey: e.shiftKey,
+                            altKey: e.altKey,
+                            metaKey: e.metaKey,
+                            ctrlKey: e.ctrlKey,
+                            clientX: e.clientX,
+                            clientY: e.clientY,
+                            dataTransfer: new DataTransfer,
+                            button: e.button,
+                            buttons: e.buttons,
+                            getModifierState: e.getModifierState,
+                            movementX: e.movementX,
+                            movementY: e.movementY,
+                            pageX: e.pageX,
+                            pageY: e.pageY,
+                            relatedTarget: e.relatedTarget,
+                            screenX: e.screenX,
+                            screenY: e.screenY,
+                            detail: e.detail,
+                            view: e.view ? e.view : new Window,
+                            nativeEvent: new DragEvent("dashDragging"),
+                            currentTarget: target,
+                            target: target,
+                            bubbles: true,
+                            cancelable: true,
+                            defaultPrevented: true,
+                            eventPhase: e.eventPhase,
+                            isTrusted: true,
+                            preventDefault: e.preventDefault,
+                            isDefaultPrevented: () => true,
+                            stopPropagation: e.stopPropagation,
+                            isPropagationStopped: () => true,
+                            persist: emptyFunction,
+                            timeStamp: e.timeStamp,
+                            type: "dashDragging"
+                        }
+                    })
+                );
+            }
+
             const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
 
             const moveX = thisX - lastX;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9bf425db2..5a762a85c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1143,10 +1143,19 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         this._layoutComputeReaction = reaction(() => this.doLayoutComputation,
             (elements) => this._layoutElements = elements || [],
             { fireImmediately: true, name: "doLayout" });
+
+        const handler = (e: Event) => this.handleDragging(e, (e as CustomEvent<DragEvent>).detail);
+
+        document.addEventListener("dashDragging", handler);
     }
+
     componentWillUnmount() {
         this._layoutComputeReaction?.();
+
+        const handler = (e: Event) => this.handleDragging(e, (e as CustomEvent<DragEvent>).detail);
+        document.removeEventListener("dashDragging", handler);
     }
+
     @computed get views() { return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); }
     elementFunc = () => this._layoutElements;
 
@@ -1155,6 +1164,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY));
     }
 
+    @action
+    handleDragging = (e: Event, de: DragEvent) => {
+        console.log(de.clientX);
+        console.log(de.clientX);
+    }
+
     promoteCollection = undoBatch(action(() => {
         const childDocs = this.childDocs.slice();
         childDocs.forEach(doc => {
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 7fb447cab..44e72215d 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -152,7 +152,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         return (!links.length || links[0].hidden) && !this.props.AlwaysOn ? (null) :
             <div title={title} ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
                 <div className={"documentLinksButton"} style={{
-                    backgroundColor: DocumentLinksButton.StartLink ? "transparent" : this.props.InMenu ? "black" : "",
+                    backgroundColor: DocumentLinksButton.StartLink && !!!this.props.InMenu ? "transparent" : this.props.InMenu ? "black" : "",
                     color: this.props.InMenu ? "white" : "black",
                     width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px", fontWeight: "bold"
                 }}
-- 
cgit v1.2.3-70-g09d2


From 27b0f32460245539d77bcd435627a68364e0bc0d Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Thu, 9 Jul 2020 12:15:42 -0500
Subject: fixed linking undo issues

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 96 ++++++++++++----------
 src/client/views/nodes/DocumentLinksButton.tsx     |  6 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  2 +
 3 files changed, 57 insertions(+), 47 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a3d3a210d..ffa4be4b9 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1174,47 +1174,55 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @action
     handleDragging = (e: Event, de: DragEvent) => {
 
-        const nw = NumCast(this.Document._nativeWidth, this.props.NativeWidth());
-        const nh = NumCast(this.Document._nativeHeight, this.props.NativeHeight());
-        const hscale = nh ? this.props.PanelHeight() / nh : 1;
-        const wscale = nw ? this.props.PanelWidth() / nw : 1;
+        const top = this.panX();
+        const left = this.panY();
+
+        const size = this.getTransform().transformDirection(this.props.PanelWidth(), this.props.PanelHeight());
+
+        const scale = this.getLocalTransform().inverse().Scale;
 
         if (this._marqueeRef) {
+
             if (this._marqueeRef.current) {
 
+                // console.log("top: " + this._marqueeRef.current.clientTop);
                 // console.log("left: " + this._marqueeRef.current.clientLeft);
                 // console.log("width: " + this._marqueeRef.current.clientWidth);
-                // console.log("client x: " + de.clientX);
-
-                // console.log("top: " + this._marqueeRef.current.clientTop);
                 // console.log("height: " + this._marqueeRef.current.clientHeight);
-                // console.log("client y: " + de.clientY);
+
+                console.log("width: " + this._marqueeRef.current.getBoundingClientRect().width);
+                console.log("height: " + this._marqueeRef.current.getBoundingClientRect().width);
+                console.log("x: " + this._marqueeRef.current.getBoundingClientRect().x);
+                console.log("y: " + this._marqueeRef.current.getBoundingClientRect().y);
+
+                // console.log("mouse x: " + de.screenX);
+                // console.log("mouse y: " + de.screenY);
 
 
                 if (this._marqueeRef.current.clientWidth > 0) {
                     if (de.clientX - 315 - this._marqueeRef.current.clientLeft < 25) {
                         console.log("PAN left ");
-                        if (this.canPanX) {
-                            this.Document._panX = de.clientX - 20 - this._marqueeRef.current.clientLeft;
-                            setTimeout(action(() => {
-                                this.canPanX = true;
-                                this.panX();
-                            }), 2500);
-                            this.canPanX = false;
-                        }
+
+                        // if (this.canPanX) {
+                        //     this.Document._panX = left - 5;
+                        //     setTimeout(action(() => {
+                        //         this.canPanX = true;
+                        //         this.panX();
+                        //     }), 250);
+                        //     this.canPanX = false;
+                        // }
                     } else if (de.clientX - 315 - this._marqueeRef.current.clientLeft -
                         this._marqueeRef.current.clientWidth < 25) {
                         console.log("PAN right ");
-                        if (this.canPanX) {
-                            this.Document._panX = de.clientX - 315 - this._marqueeRef.current.clientLeft -
-                                this._marqueeRef.current.clientWidth;
-
-                            setTimeout(action(() => {
-                                this.panX();
-                                this.canPanX = true;
-                            }), 2500);
-                            this.canPanX = false;
-                        }
+
+                        // if (this.canPanX) {
+                        //     this.Document._panX = left + 5;
+                        //     setTimeout(action(() => {
+                        //         this.panX();
+                        //         this.canPanX = true;
+                        //     }), 250);
+                        //     this.canPanX = false;
+                        // }
 
                     }
                 }
@@ -1222,27 +1230,27 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 if (this._marqueeRef.current.clientHeight > 0) {
                     if (de.clientY - 120 - this._marqueeRef.current.clientTop < 25) {
                         console.log("PAN top ");
-                        if (this.canPanY) {
-                            this.Document._panY = de.clientY - 20 - this._marqueeRef.current.clientTop;
-                            setTimeout(action(() => {
-                                this.canPanY = true;
-                                this.panY();
-                            }), 2500);
-                            this.canPanY = false;
-                        }
+
+                        // if (this.canPanY) {
+                        //     this.Document._panY = top - 5;
+                        //     setTimeout(action(() => {
+                        //         this.canPanY = true;
+                        //         this.panY();
+                        //     }), 250);
+                        //     this.canPanY = false;
+                        // }
                     } else if (de.clientY - 120 - this._marqueeRef.current.clientTop -
                         this._marqueeRef.current.clientHeight < 25) {
                         console.log("PAN bottom ");
-                        if (this.canPanY) {
-                            this.Document._panY = de.clientY - 120 - this._marqueeRef.current.clientTop -
-                                this._marqueeRef.current.clientHeight;
-
-                            setTimeout(action(() => {
-                                this.panY();
-                                this.canPanY = true;
-                            }), 2500);
-                            this.canPanY = false;
-                        }
+
+                        // if (this.canPanY) {
+                        //     this.Document._panY = top + 5;
+                        //     setTimeout(action(() => {
+                        //         this.panY();
+                        //         this.canPanY = true;
+                        //     }), 250);
+                        //     this.canPanY = false;
+                        // }
 
                     }
 
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 44e72215d..ce96eddfe 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
 import { Doc, DocListCast } from "../../../fields/Doc";
 import { emptyFunction, setupMoveUpEvents, returnFalse } from "../../../Utils";
 import { DragManager } from "../../util/DragManager";
-import { UndoManager } from "../../util/UndoManager";
+import { UndoManager, undoBatch } from "../../util/UndoManager";
 import './DocumentLinksButton.scss';
 import { DocumentView } from "./DocumentView";
 import React = require("react");
@@ -29,7 +29,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
     @observable public static StartLink: DocumentView | undefined;
 
-    @action
+    @action @undoBatch
     onLinkButtonMoved = (e: PointerEvent) => {
         if (this._linkButton.current !== null) {
             const linkDrag = UndoManager.StartBatch("Drag Link");
@@ -56,7 +56,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         return false;
     }
 
-
+    @undoBatch
     onLinkButtonDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
             if (doubleTap && this.props.InMenu) {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index fc63dfbf5..30e0738bf 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -944,6 +944,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             frag.forEach(node => nodes.push(marker(node)));
             return Fragment.fromArray(nodes);
         }
+
+
         function addLinkMark(node: Node, title: string, linkId: string) {
             if (!node.isText) {
                 const content = addMarkToFrag(node.content, (node: Node) => addLinkMark(node, title, linkId));
-- 
cgit v1.2.3-70-g09d2


From e0a3e3bb169812bdb742459cd8a26e7a92ecdf63 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Thu, 9 Jul 2020 12:18:35 -0500
Subject: last linking undo fix

---
 src/client/views/nodes/DocumentLinksButton.tsx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index ce96eddfe..1af3318cb 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -69,7 +69,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         }));
     }
 
-    @action
+    @action @undoBatch
     onLinkClick = (e: React.MouseEvent): void => {
         if (this.props.InMenu) {
             DocumentLinksButton.StartLink = this.props.View;
@@ -80,7 +80,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         }
     }
 
-    @action
+    @action @undoBatch
     completeLink = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, returnFalse, emptyFunction, action((e, doubleTap) => {
             if (doubleTap) {
@@ -111,7 +111,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         }));
     }
 
-    @action
+    @action @undoBatch
     finishLinkClick = (e: React.MouseEvent) => {
         if (DocumentLinksButton.StartLink === this.props.View) {
             DocumentLinksButton.StartLink = undefined;
-- 
cgit v1.2.3-70-g09d2


From 5e120375015d916a883232bf1235b1b133d7f9f0 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 10 Jul 2020 00:07:18 -0500
Subject: added tooltips and textboxcomment cleanup and descriptions

---
 src/client/views/linking/LinkMenuItem.tsx          | 21 ++++---
 src/client/views/nodes/DocumentLinksButton.tsx     | 50 +++++++++--------
 .../formattedText/FormattedTextBoxComment.scss     | 65 ++++++++++++++--------
 .../formattedText/FormattedTextBoxComment.tsx      | 60 ++++++++++++++------
 4 files changed, 127 insertions(+), 69 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 05ec10f71..07630c3ff 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -15,6 +15,7 @@ import { setupMoveUpEvents, emptyFunction } from '../../../Utils';
 import { DocumentView } from '../nodes/DocumentView';
 import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
 import { LinkDocPreview } from '../nodes/LinkDocPreview';
+import Tooltip from '@material-ui/core/Tooltip';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash);
 
 
@@ -228,13 +229,19 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}>
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
-                            <div title="Show link" className="button" ref={this._editRef} onPointerDown={emptyFunction}>
-                                <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
-
-                            <div title="Edit link" className="button" ref={this._editRef} onPointerDown={this.onEdit}>
-                                <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
-                            <div title="Delete link" className="button" onPointerDown={this.deleteLink}>
-                                <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
+                            <Tooltip title="Show Link">
+                                <div title="Show link" className="button" ref={this._editRef} onPointerDown={emptyFunction}>
+                                    <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
+                            </Tooltip>
+
+                            <Tooltip title="Edit Link">
+                                <div title="Edit link" className="button" ref={this._editRef} onPointerDown={this.onEdit}>
+                                    <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
+                            </Tooltip>
+                            <Tooltip title="Delete Link">
+                                <div title="Delete link" className="button" onPointerDown={this.deleteLink}>
+                                    <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
+                            </Tooltip>
                             {/* <div title="Follow link" className="button" onPointerDown={this.followDefault} onContextMenu={this.onContextMenu}>
                                 <FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */}
                         </div>
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 1af3318cb..f61ae2dd0 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -13,6 +13,7 @@ import { LinkDocPreview } from "./LinkDocPreview";
 import { LinkCreatedBox } from "./LinkCreatedBox";
 import { LinkDescriptionPopup } from "./LinkDescriptionPopup";
 import { LinkManager } from "../../util/LinkManager";
+import { Tooltip } from "@material-ui/core";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -149,30 +150,33 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
         const title = this.props.InMenu ? "Drag or tap to create links" : "Tap to view links";
 
+        const linkButton = <div title={title} ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
+            <div className={"documentLinksButton"} style={{
+                backgroundColor: DocumentLinksButton.StartLink && !!!this.props.InMenu ? "transparent" : this.props.InMenu ? "black" : "",
+                color: this.props.InMenu ? "white" : "black",
+                width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px", fontWeight: "bold"
+            }}
+                onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
+            // onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)}
+            // onPointerEnter={action(e => links.length && (LinkDocPreview.LinkInfo = {
+            //     addDocTab: this.props.View.props.addDocTab,
+            //     linkSrc: this.props.View.props.Document,
+            //     linkDoc: links[0],
+            //     Location: [e.clientX, e.clientY + 20]
+            // }))} 
+            >
+                {links.length && !!!this.props.InMenu ? links.length : <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />}
+            </div>
+            {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
+                style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }}
+                onPointerDown={this.completeLink} onClick={e => this.finishLinkClick(e)} /> : (null)}
+            {DocumentLinksButton.StartLink === this.props.View ? <div className={"documentLinksButton-startLink"}
+                style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }} /> : (null)}
+        </div>;
         return (!links.length || links[0].hidden) && !this.props.AlwaysOn ? (null) :
-            <div title={title} ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
-                <div className={"documentLinksButton"} style={{
-                    backgroundColor: DocumentLinksButton.StartLink && !!!this.props.InMenu ? "transparent" : this.props.InMenu ? "black" : "",
-                    color: this.props.InMenu ? "white" : "black",
-                    width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px", fontWeight: "bold"
-                }}
-                    onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
-                // onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)}
-                // onPointerEnter={action(e => links.length && (LinkDocPreview.LinkInfo = {
-                //     addDocTab: this.props.View.props.addDocTab,
-                //     linkSrc: this.props.View.props.Document,
-                //     linkDoc: links[0],
-                //     Location: [e.clientX, e.clientY + 20]
-                // }))} 
-                >
-                    {links.length && !!!this.props.InMenu ? links.length : <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />}
-                </div>
-                {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
-                    style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }}
-                    onPointerDown={this.completeLink} onClick={e => this.finishLinkClick(e)} /> : (null)}
-                {DocumentLinksButton.StartLink === this.props.View ? <div className={"documentLinksButton-startLink"}
-                    style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }} /> : (null)}
-            </div>;
+            <Tooltip title={title}>
+                {linkButton}
+            </Tooltip>;
     }
     render() {
         return this.linkButton;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
index 7af209842..83f99122a 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
@@ -10,32 +10,53 @@
     transform: translateX(-50%);
     box-shadow: 3px 3px 1.5px grey;
 
-    .FormattedTextBoxComment-title {
+    .FormattedTextBoxComment {
         background-color: white;
         border: 8px solid white;
 
-        .FormattedTextBoxComment-button {
-            display: inline;
-            padding-left: 6px;
-            padding-right: 6px;
-            padding-top: 2.5px;
-            padding-bottom: 2.5px;
-            width: 20px;
-            height: 20px;
-            margin: 0;
-            margin-right: 6px;
-            border-radius: 50%;
-            pointer-events: auto;
-            background-color: rgb(0, 0, 0);
-            color: rgb(255, 255, 255);
-            transition: transform 0.2s;
-            text-align: center;
-            position: relative;
-            font: 10px;
+        //display: flex;
+        .FormattedTextBoxComment-info {
 
-            &:hover {
-                background-color: rgb(77, 77, 77);
-                cursor: grab;
+            margin-bottom: 9px;
+
+            .FormattedTextBoxComment-title {
+                padding-right: 4px;
+                float: left;
+
+                .FormattedTextBoxComment-description {
+                    text-decoration: none;
+                    font-style: italic;
+                    color: rgb(95, 97, 102);
+                    font-size: 10px;
+                    padding-bottom: 4px;
+                    margin-bottom: 5px;
+
+                }
+            }
+
+            .FormattedTextBoxComment-button {
+                display: inline;
+                padding-left: 6px;
+                padding-right: 6px;
+                padding-top: 2.5px;
+                padding-bottom: 2.5px;
+                width: 17px;
+                height: 17px;
+                margin: 0;
+                margin-right: 3px;
+                border-radius: 50%;
+                pointer-events: auto;
+                background-color: rgb(0, 0, 0);
+                color: rgb(255, 255, 255);
+                transition: transform 0.2s;
+                text-align: center;
+                position: relative;
+                font-size: 12px;
+
+                &:hover {
+                    background-color: rgb(77, 77, 77);
+                    cursor: grab;
+                }
             }
         }
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index a9185be21..acdc7c56b 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -3,7 +3,7 @@ import { EditorState, Plugin } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import * as ReactDOM from 'react-dom';
 import { Doc, DocCastAsync, Opt } from "../../../../fields/Doc";
-import { Cast, FieldValue, NumCast } from "../../../../fields/Types";
+import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types";
 import { emptyFunction, returnEmptyString, returnFalse, Utils, emptyPath, returnZero, returnOne, returnEmptyFilter } from "../../../../Utils";
 import { DocServer } from "../../../DocServer";
 import { DocumentManager } from "../../../util/DocumentManager";
@@ -21,6 +21,7 @@ import { action } from "mobx";
 import { LinkManager } from "../../../util/LinkManager";
 import { LinkDocPreview } from "../LinkDocPreview";
 import { DocumentLinksButton } from "../DocumentLinksButton";
+import Tooltip from "@material-ui/core/Tooltip";
 
 export let formattedTextBoxCommentPlugin = new Plugin({
     view(editorView) { return new FormattedTextBoxComment(editorView); }
@@ -85,13 +86,13 @@ export class FormattedTextBoxComment {
             FormattedTextBoxComment.tooltip.className = "FormattedTextBox-tooltip";
             FormattedTextBoxComment.tooltip.style.pointerEvents = "all";
             FormattedTextBoxComment.tooltip.style.maxWidth = "190px";
-            FormattedTextBoxComment.tooltip.style.maxHeight = "220px";
+            FormattedTextBoxComment.tooltip.style.maxHeight = "235px";
             FormattedTextBoxComment.tooltip.style.width = "100%";
             FormattedTextBoxComment.tooltip.style.height = "100%";
             FormattedTextBoxComment.tooltip.style.overflow = "hidden";
             FormattedTextBoxComment.tooltip.style.display = "none";
             FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipInput);
-            FormattedTextBoxComment.tooltip.onpointerdown = (e: PointerEvent) => {
+            FormattedTextBoxComment.tooltip.onpointerdown = async (e: PointerEvent) => {
                 const keep = e.target && (e.target as any).type === "checkbox" ? true : false;
                 const textBox = FormattedTextBoxComment.textBox;
                 if (FormattedTextBoxComment.linkDoc && !keep && textBox) {
@@ -103,8 +104,22 @@ export class FormattedTextBoxComment {
                             if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) {
                                 textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight");
                             } else {
-                                DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document,
-                                    (doc: Doc, followLinkLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation));
+                                const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(FormattedTextBoxComment.linkDoc.anchor1, Doc)), textBox.dataDoc) ?
+                                    Cast(FormattedTextBoxComment.linkDoc.anchor2, Doc) : (Cast(FormattedTextBoxComment.linkDoc.anchor1, Doc))
+                                    || FormattedTextBoxComment.linkDoc);
+                                const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
+
+                                if (FormattedTextBoxComment.linkDoc.follow) {
+                                    if (FormattedTextBoxComment.linkDoc.follow === "Default") {
+                                        DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "onRight"), false);
+                                    } else if (FormattedTextBoxComment.linkDoc.follow === "Always open in right tab") {
+                                        if (target) { textBox.props.addDocTab(target, "onRight"); }
+                                    } else if (FormattedTextBoxComment.linkDoc.follow === "Always open in new tab") {
+                                        if (target) { textBox.props.addDocTab(target, "inTab"); }
+                                    }
+                                } else {
+                                    DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "onRight"), false);
+                                }
                             }
                         } else {
                             if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) {
@@ -243,19 +258,30 @@ export class FormattedTextBoxComment {
                                 FormattedTextBoxComment.showCommentbox("", view, nbef);
 
 
-                                const docPreview = <div className="FormattedTextBoxComment-title">
-                                    {target.title}
-                                    <div className="wrapper" style={{ float: "right" }}>
-                                        <div title="Delete link" className="FormattedTextBoxComment-button"
-                                            ref={(r) => this._deleteRef = r}>
-                                            <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white"
-                                                size="sm" /></div>
-                                        <div title="Follow link" className="FormattedTextBoxComment-button"
-                                            ref={(r) => this._followRef = r}>
-                                            <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white"
-                                                size="sm" />
+                                const docPreview = <div className="FormattedTextBoxComment">
+                                    <div className="FormattedTextBoxComment-info">
+                                        <div className="FormattedTextBoxComment-title">
+                                            {target.title}
+                                            {FormattedTextBoxComment.linkDoc.description !== "" ? <p className="FormattedTextBoxComment-description">
+                                                {StrCast(FormattedTextBoxComment.linkDoc.description)}</p> : null}
                                         </div>
-                                    </div>
+                                        <div className="wrapper" style={{ float: "right" }}>
+
+                                            <Tooltip title="Delete Link" placement="top">
+                                                <div title="Delete link" className="FormattedTextBoxComment-button"
+                                                    ref={(r) => this._deleteRef = r}>
+                                                    <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white"
+                                                        size="sm" /></div>
+                                            </Tooltip>
+
+                                            <Tooltip title="Follow Link" placement="top">
+                                                <div title="Follow link" className="FormattedTextBoxComment-button"
+                                                    ref={(r) => this._followRef = r}>
+                                                    <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white"
+                                                        size="sm" />
+                                                </div>
+                                            </Tooltip>
+                                        </div> </div>
                                     <div className="FormattedTextBoxComment-preview-wrapper">
                                         <ContentFittingDocumentView
                                             Document={target}
-- 
cgit v1.2.3-70-g09d2


From 20ab61d762e4c92e9ace6eb9b577667a9a8dc1e3 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 10 Jul 2020 12:05:53 -0500
Subject: fixed tooltip error, label styling

---
 src/client/views/linking/LinkMenuItem.scss            |  3 +++
 src/client/views/linking/LinkMenuItem.tsx             | 19 +++++++++++++------
 src/client/views/nodes/DocumentLinksButton.tsx        |  2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx    | 10 ++++++----
 .../nodes/formattedText/FormattedTextBoxComment.tsx   |  6 +++---
 5 files changed, 26 insertions(+), 14 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index f759aef5e..3ecb306f9 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -77,6 +77,9 @@
                 color: rgb(95, 97, 102);
                 font-size: 10px;
                 margin-left: 20px;
+                max-width: 125px;
+                height: auto;
+                white-space: break-spaces;
             }
 
             p {
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index f1a744ff2..f7d189b20 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -15,7 +15,8 @@ import { setupMoveUpEvents, emptyFunction } from '../../../Utils';
 import { DocumentView } from '../nodes/DocumentView';
 import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
 import { LinkDocPreview } from '../nodes/LinkDocPreview';
-import Tooltip from '@material-ui/core/Tooltip';
+import { Tooltip } from '@material-ui/core';
+import { RichTextField } from '../../../fields/RichTextField';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash);
 
 
@@ -203,6 +204,12 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
         console.log(StrCast(this.props.destinationDoc.title).length);
 
+        //  ...
+        // from anika to bob: here's where the text that is specifically linked would show up (linkDoc.storedText)
+        // ...
+        const source = this.props.sourceDoc.type === "rtf" ? this.props.linkDoc.storedText ?
+            "stored text would show up here" : undefined : undefined;
+
         return (
             <div className="linkMenu-item">
                 <div className={canExpand ? "linkMenu-item-content expand-three" : "linkMenu-item-content expand-two"}>
@@ -218,8 +225,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                         onPointerDown={this.onLinkButtonDown}>
 
                         <div className="linkMenu-text">
-                            {this.props.linkDoc.linkedText ? <p className="linkMenu-source-title">
-                                <b>Source: {StrCast(this.props.linkDoc.linkedText)}</b></p> : null}
+                            {source ? <p className="linkMenu-source-title">
+                                <b>Source: {source}</b></p> : null}
                             <div className="linkMenu-title-wrapper">
                                 <div className="destination-icon-wrapper" >
                                     <FontAwesomeIcon className="destination-icon" icon={destinationIcon} size="sm" /></div>
@@ -236,16 +243,16 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
                             <Tooltip title="Show Link">
-                                <div title="Show link" className="button" ref={this._editRef} onPointerDown={emptyFunction}>
+                                <div className="button" ref={this._editRef} onPointerDown={emptyFunction}>
                                     <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
                             </Tooltip>
 
                             <Tooltip title="Edit Link">
-                                <div title="Edit link" className="button" ref={this._editRef} onPointerDown={this.onEdit}>
+                                <div className="button" ref={this._editRef} onPointerDown={this.onEdit}>
                                     <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
                             </Tooltip>
                             <Tooltip title="Delete Link">
-                                <div title="Delete link" className="button" onPointerDown={this.deleteLink}>
+                                <div className="button" onPointerDown={this.deleteLink}>
                                     <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
                             </Tooltip>
                             {/* <div title="Follow link" className="button" onPointerDown={this.followDefault} onContextMenu={this.onContextMenu}>
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index f61ae2dd0..22431117e 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -150,7 +150,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
         const title = this.props.InMenu ? "Drag or tap to create links" : "Tap to view links";
 
-        const linkButton = <div title={title} ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
+        const linkButton = <div ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
             <div className={"documentLinksButton"} style={{
                 backgroundColor: DocumentLinksButton.StartLink && !!!this.props.InMenu ? "transparent" : this.props.InMenu ? "black" : "",
                 color: this.props.InMenu ? "white" : "black",
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 4f6927d3d..e3411ccf5 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -175,8 +175,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
 
     doLinkOnDeselect() {
 
-        console.log("link on deselect");
-
         Array.from(this.linkOnDeselect.entries()).map(entry => {
             const key = entry[0];
             const value = entry[1];
@@ -186,11 +184,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 DocServer.GetRefField(id).then(linkDoc => {
                     this.dataDoc[key] = doc || Docs.Create.FreeformDocument([], { title: value, _width: 500, _height: 500 }, value);
                     DocUtils.Publish(this.dataDoc[key] as Doc, value, this.props.addDocument, this.props.removeDocument);
-                    if (linkDoc) { (linkDoc as Doc).anchor2 = this.dataDoc[key] as Doc; }
-                    else DocUtils.MakeLink({ doc: this.rootDoc }, { doc: this.dataDoc[key] as Doc }, "portal link", "link to named target", id);
+                    if (linkDoc) {
+                        (linkDoc as Doc).anchor2 = this.dataDoc[key] as Doc;
+                    } else {
+                        DocUtils.MakeLink({ doc: this.rootDoc }, { doc: this.dataDoc[key] as Doc }, "portal link", "link to named target", id);
+                    }
                 });
             });
         });
+
         this.linkOnDeselect.clear();
     }
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index f1602bfbc..fa2548cb5 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -21,7 +21,7 @@ import { action } from "mobx";
 import { LinkManager } from "../../../util/LinkManager";
 import { LinkDocPreview } from "../LinkDocPreview";
 import { DocumentLinksButton } from "../DocumentLinksButton";
-import Tooltip from "@material-ui/core/Tooltip";
+import { Tooltip } from "@material-ui/core";
 
 export let formattedTextBoxCommentPlugin = new Plugin({
     view(editorView) { return new FormattedTextBoxComment(editorView); }
@@ -271,14 +271,14 @@ export class FormattedTextBoxComment {
                                         <div className="wrapper" style={{ float: "right" }}>
 
                                             <Tooltip title="Delete Link" placement="top">
-                                                <div title="Delete link" className="FormattedTextBoxComment-button"
+                                                <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._deleteRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white"
                                                         size="sm" /></div>
                                             </Tooltip>
 
                                             <Tooltip title="Follow Link" placement="top">
-                                                <div title="Follow link" className="FormattedTextBoxComment-button"
+                                                <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._followRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white"
                                                         size="sm" />
-- 
cgit v1.2.3-70-g09d2


From 5a70fb56062d6a5ed45cf3cf4453089bc83f3c6b Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 10 Jul 2020 18:11:09 -0500
Subject: added showing individual links with one bug

---
 .../collectionFreeForm/CollectionFreeFormLinkView.tsx  |  4 ++--
 src/client/views/linking/LinkMenuItem.tsx              | 13 ++++++++++---
 src/client/views/nodes/DocumentLinksButton.tsx         |  8 +++++++-
 src/client/views/nodes/DocumentView.tsx                | 18 ++++++++++++++----
 4 files changed, 33 insertions(+), 10 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index a24693c30..ae79c27e0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -110,10 +110,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
         const pt2norm = [pt2vec[0] / pt2len * ptlen, pt2vec[1] / pt2len * ptlen];
         const aActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document);
         const bActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document);
-        const text = StrCast(this.props.A.props.Document.linkRelationship);
+        const text = StrCast(this.props.A.props.Document.description);
         return !a.width || !b.width || ((!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<>
             <text x={(Math.min(pt1[0], pt2[0]) * 2 + Math.max(pt1[0], pt2[0])) / 3} y={(pt1[1] + pt2[1]) / 2}>
-                {text !== "-ungrouped-" ? text : ""}
+                {text}
             </text>
             <path className="collectionfreeformlinkview-linkLine" style={{ opacity: this._opacity, strokeDasharray: "2 2" }}
                 d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} />
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index f7d189b20..8fc1ea12f 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -177,11 +177,16 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         DocumentLinksButton.EditLink = undefined;
     }
 
+    @action
+    showLink = () => {
+        this.props.linkDoc.hidden = !this.props.linkDoc.hidden;
+    }
+
     render() {
         const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType);
         const canExpand = keys ? keys.length > 0 : false;
 
-        const eyeIcon = this.props.linkDoc.shown ? "eye-slash" : "eye";
+        const eyeIcon = this.props.linkDoc.hidden ? "eye-slash" : "eye";
 
         const destinationIcon = this.props.destinationDoc.type === "image" ? "image" :
             this.props.destinationDoc.type === "comparison" ? "columns" :
@@ -208,7 +213,9 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         // from anika to bob: here's where the text that is specifically linked would show up (linkDoc.storedText)
         // ...
         const source = this.props.sourceDoc.type === "rtf" ? this.props.linkDoc.storedText ?
-            "stored text would show up here" : undefined : undefined;
+            StrCast(this.props.linkDoc.storedText).length > 17 ?
+                StrCast(this.props.linkDoc.storedText).substr(0, 18)
+                : this.props.linkDoc.storedText : undefined : undefined;
 
         return (
             <div className="linkMenu-item">
@@ -243,7 +250,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
                             <Tooltip title="Show Link">
-                                <div className="button" ref={this._editRef} onPointerDown={emptyFunction}>
+                                <div className="button" ref={this._editRef} onPointerDown={this.showLink}>
                                     <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
                             </Tooltip>
 
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 22431117e..f07a2ea5a 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -95,6 +95,9 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
                         const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
                         LinkManager.currentLink = linkDoc;
+                        linkDoc ? linkDoc.hidden = true : null;
+                        linkDoc ? linkDoc.linkDisplay = true : null;
+
                         runInAction(() => {
                             LinkCreatedBox.popupX = e.screenX;
                             LinkCreatedBox.popupY = e.screenY - 133;
@@ -123,6 +126,9 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
                 const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
                 LinkManager.currentLink = linkDoc;
+                linkDoc ? linkDoc.hidden = true : null;
+                linkDoc ? linkDoc.linkDisplay = true : null;
+
                 runInAction(() => {
                     LinkCreatedBox.popupX = e.screenX;
                     LinkCreatedBox.popupY = e.screenY - 133;
@@ -173,7 +179,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             {DocumentLinksButton.StartLink === this.props.View ? <div className={"documentLinksButton-startLink"}
                 style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }} /> : (null)}
         </div>;
-        return (!links.length || links[0].hidden) && !this.props.AlwaysOn ? (null) :
+        return (!links.length) && !this.props.AlwaysOn ? (null) :
             <Tooltip title={title}>
                 {linkButton}
             </Tooltip>;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 97e3bc01c..310260832 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -201,6 +201,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         this._mainCont.current && (this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this)));
         // this._mainCont.current && (this.holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this)));
 
+        //this.layoutDoc.showAllLinks = true;
+
         if (!this.props.dontRegisterView) {
             DocumentManager.Instance.DocumentViews.push(this);
         }
@@ -646,6 +648,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
             const linkDoc = DocUtils.MakeLink({ doc: de.complete.annoDragData.annotationDocument }, { doc: this.props.Document }, "link");
             LinkManager.currentLink = linkDoc;
+            linkDoc ? linkDoc.hidden = true : null;
+            linkDoc ? linkDoc.linkDisplay = true : null;
 
             runInAction(() => {
                 LinkCreatedBox.popupX = de.x;
@@ -668,6 +672,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 const linkDoc = DocUtils.MakeLink({ doc: de.complete.linkDragData.linkSourceDocument },
                     { doc: this.props.Document }, `link`);
                 LinkManager.currentLink = linkDoc;
+                linkDoc ? linkDoc.hidden = true : null;
+                linkDoc ? linkDoc.linkDisplay = true : null;
 
                 de.complete.linkDragData.linkSourceDocument !== this.props.Document &&
                     (de.complete.linkDragData.linkDocument = linkDoc); // TODODO this is where in text links get passed
@@ -783,9 +789,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
         const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
         templateDoc && optionItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" });
-        optionItems.push({ description: "Toggle Show Each Link Dot", event: () => this.layoutDoc.showLinks = !this.layoutDoc.showLinks, icon: "eye" });
+        optionItems.push({
+            description: "Toggle Show Each Link Dot", event: () => { this.layoutDoc.showAllLinks = !this.layoutDoc.showAllLinks; }, icon: "eye"
+        });
         !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
 
+
         const existingOnClick = cm.findByDescription("OnClick...");
         const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
         onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
@@ -1084,7 +1093,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 select={this.select}
                 onClick={this.onClickHandler}
                 layoutKey={this.finalLayoutKey} />
-            {this.layoutDoc.showLinks ? this.anchors : (null)}
+            {this.layoutDoc.showAllLinks ? this.allAnchors : null}
             {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : <DocumentLinksButton View={this} Offset={[-15, 0]} />}
         </div>
         );
@@ -1107,7 +1116,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     hideLinkAnchor = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && (doc.hidden = true), true)
     anchorPanelWidth = () => this.props.PanelWidth() || 1;
     anchorPanelHeight = () => this.props.PanelHeight() || 1;
-    @computed get anchors() {
+
+    @computed get allAnchors() {
         TraceMobx();
         return (this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots
             this.layoutDoc.presBox ||  // presentationbox nodes
@@ -1133,7 +1143,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (this.props.treeViewDoc && !this.props.LayoutTemplateString) {  // this happens when the document is a tree view label (but not an anchor dot)
             return <div className="documentView-treeView" style={{ maxWidth: this.props.PanelWidth() || undefined }}>
                 {StrCast(this.props.Document.title)}
-                {this.anchors}
+                {this.allAnchors}
             </div>;
         }
 
-- 
cgit v1.2.3-70-g09d2


From ddad39f43f4b7398bb47f5513ec0d753d0288eca Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 10 Jul 2020 23:21:32 -0500
Subject: menu ui change

---
 src/client/views/linking/LinkMenuItem.scss         |  2 +-
 src/client/views/linking/LinkMenuItem.tsx          |  4 ++-
 src/client/views/nodes/DocumentLinksButton.scss    |  2 +-
 src/client/views/nodes/DocumentLinksButton.tsx     | 39 ++++++++++++----------
 src/client/views/nodes/DocumentView.tsx            | 35 +++++++++++--------
 src/client/views/nodes/LinkDescriptionPopup.scss   |  8 +++++
 .../formattedText/FormattedTextBoxComment.scss     |  2 +-
 7 files changed, 57 insertions(+), 35 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index 3ecb306f9..f70f5a23e 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -162,7 +162,7 @@
 
         &:hover {
             background: $main-accent;
-            cursor: grab;
+            cursor: pointer;
         }
     }
 }
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 8fc1ea12f..9aa142728 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -217,6 +217,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 StrCast(this.props.linkDoc.storedText).substr(0, 18)
                 : this.props.linkDoc.storedText : undefined : undefined;
 
+        const showTitle = this.props.linkDoc.hidden ? "Show link" : "Hide link";
+
         return (
             <div className="linkMenu-item">
                 <div className={canExpand ? "linkMenu-item-content expand-three" : "linkMenu-item-content expand-two"}>
@@ -249,7 +251,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}>
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
-                            <Tooltip title="Show Link">
+                            <Tooltip title={showTitle}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.showLink}>
                                     <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
                             </Tooltip>
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index b58603978..580e86442 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -23,7 +23,7 @@
     &:hover {
         background: deepskyblue;
         transform: scale(1.05);
-        cursor: grab;
+        cursor: pointer;
     }
 }
 .documentLinksButton {
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index f07a2ea5a..03a96ea4a 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -99,15 +99,18 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                         linkDoc ? linkDoc.linkDisplay = true : null;
 
                         runInAction(() => {
-                            LinkCreatedBox.popupX = e.screenX;
-                            LinkCreatedBox.popupY = e.screenY - 133;
-                            LinkCreatedBox.linkCreated = true;
+                            if (linkDoc) {
+                                LinkCreatedBox.popupX = e.screenX;
+                                LinkCreatedBox.popupY = e.screenY - 133;
+                                LinkCreatedBox.linkCreated = true;
 
-                            LinkDescriptionPopup.popupX = e.screenX;
-                            LinkDescriptionPopup.popupY = e.screenY - 100;
-                            LinkDescriptionPopup.descriptionPopup = true;
+                                LinkDescriptionPopup.popupX = e.screenX;
+                                LinkDescriptionPopup.popupY = e.screenY - 100;
+                                LinkDescriptionPopup.descriptionPopup = true;
+
+                                setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                            }
 
-                            setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
                         });
                     }
                 }
@@ -130,17 +133,19 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 linkDoc ? linkDoc.linkDisplay = true : null;
 
                 runInAction(() => {
-                    LinkCreatedBox.popupX = e.screenX;
-                    LinkCreatedBox.popupY = e.screenY - 133;
-                    LinkCreatedBox.linkCreated = true;
-
-                    if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
-                        LinkDescriptionPopup.popupX = e.screenX;
-                        LinkDescriptionPopup.popupY = e.screenY - 100;
-                        LinkDescriptionPopup.descriptionPopup = true;
-                    }
+                    if (linkDoc) {
+                        LinkCreatedBox.popupX = e.screenX;
+                        LinkCreatedBox.popupY = e.screenY - 133;
+                        LinkCreatedBox.linkCreated = true;
 
-                    setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                        if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
+                            LinkDescriptionPopup.popupX = e.screenX;
+                            LinkDescriptionPopup.popupY = e.screenY - 100;
+                            LinkDescriptionPopup.descriptionPopup = true;
+                        }
+
+                        setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                    }
                 });
             }
         }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 310260832..d0305c36c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -652,15 +652,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             linkDoc ? linkDoc.linkDisplay = true : null;
 
             runInAction(() => {
-                LinkCreatedBox.popupX = de.x;
-                LinkCreatedBox.popupY = de.y - 33;
-                LinkCreatedBox.linkCreated = true;
+                if (linkDoc) {
+                    LinkCreatedBox.popupX = de.x;
+                    LinkCreatedBox.popupY = de.y - 33;
+                    LinkCreatedBox.linkCreated = true;
 
-                LinkDescriptionPopup.popupX = de.x;
-                LinkDescriptionPopup.popupY = de.y;
-                LinkDescriptionPopup.descriptionPopup = true;
+                    LinkDescriptionPopup.popupX = de.x;
+                    LinkDescriptionPopup.popupY = de.y;
+                    LinkDescriptionPopup.descriptionPopup = true;
 
-                setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                    setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                }
             });
         }
         if (de.complete.linkDragData) {
@@ -678,15 +680,19 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 de.complete.linkDragData.linkSourceDocument !== this.props.Document &&
                     (de.complete.linkDragData.linkDocument = linkDoc); // TODODO this is where in text links get passed
                 runInAction(() => {
-                    LinkCreatedBox.popupX = de.x;
-                    LinkCreatedBox.popupY = de.y - 33;
-                    LinkCreatedBox.linkCreated = true;
 
-                    LinkDescriptionPopup.popupX = de.x;
-                    LinkDescriptionPopup.popupY = de.y;
-                    LinkDescriptionPopup.descriptionPopup = true;
+                    if (linkDoc) {
+                        LinkCreatedBox.popupX = de.x;
+                        LinkCreatedBox.popupY = de.y - 33;
+                        LinkCreatedBox.linkCreated = true;
+
+                        LinkDescriptionPopup.popupX = de.x;
+                        LinkDescriptionPopup.popupY = de.y;
+                        LinkDescriptionPopup.descriptionPopup = true;
+
+                        setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                    }
 
-                    setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
                 });
             }
 
@@ -1094,6 +1100,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 onClick={this.onClickHandler}
                 layoutKey={this.finalLayoutKey} />
             {this.layoutDoc.showAllLinks ? this.allAnchors : null}
+            {/* {this.allAnchors} */}
             {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : <DocumentLinksButton View={this} Offset={[-15, 0]} />}
         </div>
         );
diff --git a/src/client/views/nodes/LinkDescriptionPopup.scss b/src/client/views/nodes/LinkDescriptionPopup.scss
index 54002fd1b..d92823ccc 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.scss
+++ b/src/client/views/nodes/LinkDescriptionPopup.scss
@@ -48,6 +48,10 @@
             position: relative;
             margin-right: 4px;
             justify-content: center;
+
+            &:hover{
+                cursor: pointer;
+            }
         }
 
         .linkDescriptionPopup-btn-add {
@@ -62,6 +66,10 @@
             text-align: center;
             position: relative;
             justify-content: center;
+
+            &:hover{
+                cursor: pointer;
+            }
         }
     }
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
index 83f99122a..6a403cb17 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss
@@ -55,7 +55,7 @@
 
                 &:hover {
                     background-color: rgb(77, 77, 77);
-                    cursor: grab;
+                    cursor: pointer;
                 }
             }
         }
-- 
cgit v1.2.3-70-g09d2


From c77f890a3ddd817738564a84046e65f0916d8a46 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sun, 12 Jul 2020 12:02:19 -0500
Subject: more tooltips

---
 src/client/views/DocumentButtonBar.tsx             | 87 +++++++++++-----------
 src/client/views/DocumentDecorations.tsx           | 41 +++++-----
 .../views/collections/CollectionLinearView.tsx     | 23 +++---
 src/client/views/nodes/DocumentLinksButton.tsx     |  4 +-
 4 files changed, 85 insertions(+), 70 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 1667b2f65..072648ef0 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -23,6 +23,7 @@ import { TemplateMenu } from "./TemplateMenu";
 import { Template, Templates } from "./Templates";
 import React = require("react");
 import { DocumentLinksButton } from './nodes/DocumentLinksButton';
+import { Tooltip } from '@material-ui/core';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -118,18 +119,18 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <div
-            title={`${published ? "Push" : "Publish"} to Google Docs`}
-            className="documentButtonBar-linker"
-            style={{ animation }}
-            onClick={async () => {
-                await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
-                !published && runInAction(() => this.isAnimatingPulse = true);
-                DocumentButtonBar.hasPushedHack = false;
-                targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
-            }}>
-            <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} />
-        </div>;
+        return !targetDoc ? (null) : <Tooltip title={`${published ? "Push" : "Publish"} to Google Docs`}>
+            <div
+                className="documentButtonBar-linker"
+                style={{ animation }}
+                onClick={async () => {
+                    await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
+                    !published && runInAction(() => this.isAnimatingPulse = true);
+                    DocumentButtonBar.hasPushedHack = false;
+                    targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
+                }}>
+                <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} />
+            </div></Tooltip>;
     }
 
     @computed
@@ -137,7 +138,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const dataDoc = targetDoc && Doc.GetProto(targetDoc);
         const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
-        return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <div className="documentButtonBar-linker"
+        return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
             title={(() => {
                 switch (this.openHover) {
                     default:
@@ -146,6 +147,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                     case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
                 }
             })()}
+        ><div className="documentButtonBar-linker"
             style={{ backgroundColor: this.pullColor }}
             onPointerEnter={action(e => {
                 if (e.altKey) {
@@ -176,43 +178,43 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                     dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
                 }
             }}>
-            <FontAwesomeIcon className="documentdecorations-icon" size="sm"
-                style={{ WebkitAnimation: animation, MozAnimation: animation }}
-                icon={(() => {
-                    switch (this.openHover) {
-                        default:
-                        case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
-                        case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
-                        case UtilityButtonState.OpenExternally: return "share";
-                    }
-                })()}
-            />
-        </div>;
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm"
+                    style={{ WebkitAnimation: animation, MozAnimation: animation }}
+                    icon={(() => {
+                        switch (this.openHover) {
+                            default:
+                            case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
+                            case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
+                            case UtilityButtonState.OpenExternally: return "share";
+                        }
+                    })()}
+                />
+            </div></Tooltip>;
     }
     @computed
     get pinButton() {
         const targetDoc = this.view0?.props.Document;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
-        return !targetDoc ? (null) : <div className="documentButtonBar-linker"
-            title={Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}
-            style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
-            onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
-            <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
-            />
-        </div>;
+        return !targetDoc ? (null) : <Tooltip title={Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}>
+            <div className="documentButtonBar-linker"
+                style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
+                onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
+                />
+            </div></Tooltip>;
     }
 
     @computed
     get metadataButton() {
         const view0 = this.view0;
-        return !view0 ? (null) : <div title="Show metadata panel" className="documentButtonBar-linkFlyout">
+        return !view0 ? (null) : <Tooltip title="Show metadata panel"><div className="documentButtonBar-linkFlyout">
             <Flyout anchorPoint={anchorPoints.LEFT_TOP}
                 content={<MetadataEntryMenu docs={() => this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
                 <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
                     {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
                 </div>
             </Flyout>
-        </div>;
+        </div></Tooltip>;
     }
 
     @computed
@@ -253,14 +255,15 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         Array.from(Object.values(Templates.TemplateList)).map(template =>
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !view0 ? (null) :
-            <div title="Tap: Customize layout.  Drag: Create alias" className="documentButtonBar-linkFlyout" ref={this._dragRef}>
-                <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
-                    content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
-                    <div className={"documentButtonBar-linkButton-empty"} ref={this._dragRef} onPointerDown={this.onAliasButtonDown} >
-                        {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
-                    </div>
-                </Flyout>
-            </div>;
+            <Tooltip title="Tap: Customize layout.  Drag: Create alias" >
+                <div className="documentButtonBar-linkFlyout" ref={this._dragRef}>
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
+                        content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
+                        <div className={"documentButtonBar-linkButton-empty"} ref={this._dragRef} onPointerDown={this.onAliasButtonDown} >
+                            {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
+                        </div>
+                    </Flyout>
+                </div></Tooltip>;
     }
 
     render() {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 0bf4814e7..d7324e1a6 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -25,6 +25,7 @@ import { HtmlField } from '../../fields/HtmlField';
 import { InkData, InkField, InkTool } from "../../fields/InkField";
 import { update } from 'serializr';
 import { Transform } from "../util/Transform";
+import { Tooltip } from '@material-ui/core';
 
 library.add(faCaretUp);
 library.add(faObjectGroup);
@@ -546,13 +547,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
         const minimal = bounds.r - bounds.x < 100 ? true : false;
         const maximizeIcon = minimal ? (
-            <div className="documentDecorations-contextMenu" title="Show context menu" onPointerDown={this.onSettingsDown}>
-                <FontAwesomeIcon size="lg" icon="cog" />
-            </div>) : (
-                <div className="documentDecorations-minimizeButton" title="Iconify" onClick={this.onCloseClick}>
-                    {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
-                    <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
-                </div>);
+            <Tooltip title="Show context menu" placement="top">
+                <div className="documentDecorations-contextMenu" onPointerDown={this.onSettingsDown}>
+                    <FontAwesomeIcon size="lg" icon="cog" />
+                </div></Tooltip>) : (
+                <Tooltip title="Iconify" placement="top">
+                    <div className="documentDecorations-minimizeButton" onClick={this.onCloseClick}>
+                        {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
+                        <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
+                    </div></Tooltip>);
 
         const titleArea = this._edtingTitle ?
             <>
@@ -572,9 +575,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 </div>}
             </> :
             <>
-                {minimal ? (null) : <div className="documentDecorations-contextMenu" key="menu" title="Show context menu" onPointerDown={this.onSettingsDown}>
+                {minimal ? (null) : <Tooltip title="Show context menu" placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
-                </div>}
+                </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
                     <span style={{ width: "100%", display: "inline-block" }}>{`${this.selectionTitle}`}</span>
                 </div>
@@ -611,12 +614,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     {maximizeIcon}
                     {titleArea}
                     {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
-                        <div className="documentDecorations-iconifyButton" title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} onPointerDown={this.onIconifyDown}>
-                            {"_"}
-                        </div>}
-                    <div className="documentDecorations-closeButton" title="Open Document in Tab" onPointerDown={this.onMaximizeDown}>
+                        <Tooltip title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} placement="top">
+                            <div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
+                                {"_"}
+                            </div></Tooltip>}
+                    <Tooltip title="Open Document in Tab" placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
                         {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
-                    </div>
+                    </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
                         onPointerDown={this.onRotateDown}> ⟲ </div>
                     <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer"
@@ -637,10 +641,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer"
                         onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                     {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
-                        <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
-                            title="tap to select containing document" onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
-                            <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
-                        </div>}
+                        <Tooltip title="tap to select containing document" placement="top">
+                            <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
+                                onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
+                                <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
+                            </div></Tooltip>}
                     <div id="documentDecorations-borderRadius" className="documentDecorations-radius"
                         onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}></div>
 
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 2dd48aa27..4c68cc949 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -111,17 +111,22 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
         const flexDir: any = StrCast(this.Document.flexDirection);
         const backgroundColor = StrCast(this.props.Document.backgroundColor, "black");
         const color = StrCast(this.props.Document.color, "white");
+
+        const menuOpener = <label htmlFor={`${guid}`} style={{
+            background: backgroundColor === color ? "black" : backgroundColor,
+            // width: "18px", height: "18px", fontSize: "12.5px",
+            // transition: this.props.Document.linearViewIsExpanded ? "transform 0.2s" : "transform 0.5s",
+            // transform: this.props.Document.linearViewIsExpanded ? "" : "rotate(45deg)"
+        }}
+            onPointerDown={e => e.stopPropagation()} >
+            <p>+</p>
+        </label>;
+
         return <div className="collectionLinearView-outer">
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
-                <label htmlFor={`${guid}`} title="Close Menu" style={{
-                    background: backgroundColor === color ? "black" : backgroundColor,
-                    // width: "18px", height: "18px", fontSize: "12.5px",
-                    // transition: this.props.Document.linearViewIsExpanded ? "transform 0.2s" : "transform 0.5s",
-                    // transform: this.props.Document.linearViewIsExpanded ? "" : "rotate(45deg)"
-                }}
-                    onPointerDown={e => e.stopPropagation()} >
-                    <p>+</p>
-                </label>
+                <Tooltip title={BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"} placement="top">
+                    {menuOpener}
+                </Tooltip>
                 <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
                     onChange={action((e: any) => this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
 
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 03a96ea4a..1c15b31de 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -64,6 +64,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 //action(() => Doc.BrushDoc(this.props.View.Document));
                 DocumentLinksButton.StartLink = this.props.View;
             } else if (!!!this.props.InMenu) {
+                console.log("editing");
+                this.props.View ? console.log("view") : null;
                 DocumentLinksButton.EditLink = this.props.View;
                 DocumentLinksButton.EditLinkLoc = [e.clientX + 10, e.clientY];
             }
@@ -159,7 +161,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     get linkButton() {
         const links = DocListCast(this.props.View.props.Document.links);
 
-        const title = this.props.InMenu ? "Drag or tap to create links" : "Tap to view links";
+        const title = this.props.InMenu ? "Drag or tap to create links" : DocumentLinksButton.StartLink ? "Tap to finish link" : "Tap to view links";
 
         const linkButton = <div ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
             <div className={"documentLinksButton"} style={{
-- 
cgit v1.2.3-70-g09d2


From f159aa5378b433111d15d08ffe37d1e342958466 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 12 Jul 2020 13:42:03 -0400
Subject: fixed display of linkMenu

---
 src/client/views/GestureOverlay.scss           |  2 +-
 src/client/views/GestureOverlay.tsx            |  2 +-
 src/client/views/MainView.tsx                  | 10 +++++-----
 src/client/views/linking/LinkMenu.scss         |  2 +-
 src/client/views/linking/LinkMenu.tsx          | 18 ++++++++++--------
 src/client/views/nodes/DocumentLinksButton.tsx |  4 ++--
 6 files changed, 20 insertions(+), 18 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/GestureOverlay.scss b/src/client/views/GestureOverlay.scss
index f61f4a05e..c9d78890e 100644
--- a/src/client/views/GestureOverlay.scss
+++ b/src/client/views/GestureOverlay.scss
@@ -1,7 +1,7 @@
 .gestureOverlay-cont {
     width: 100vw;
     height: 100vh;
-    position: fixed;
+    position: relative;
     top: 0;
     left: 0;
     touch-action: none;
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 768057c22..a48b7b673 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -845,7 +845,7 @@ export default class GestureOverlay extends Touchable {
 
     render() {
         return (
-            <div className="gestureOverlay-cont" style={{ position: "relative" }} ref={this._overlayRef}
+            <div className="gestureOverlay-cont" ref={this._overlayRef}
                 onPointerDown={this.onPointerDown} onTouchStart={this.onReactTouchStart}>
                 {this.showMobileInkOverlay ? <MobileInkOverlay /> : <></>}
                 {this.elements}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b9ee58d5d..92f1dfec0 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -612,16 +612,16 @@ export class MainView extends React.Component {
             <InkOptionsMenu />
             <FormatShapePane />
             <RichTextMenu key="rich" />
-            <GestureOverlay >
-                {this.mainContent}
-            </GestureOverlay>
-            <PreviewCursor />
-            <LinkCreatedBox />
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
             {DocumentLinksButton.EditLink ? <LinkMenu location={DocumentLinksButton.EditLinkLoc} docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} backgroundColor={this.defaultBackgroundColors}
                 linkDoc={LinkDocPreview.LinkInfo.linkDoc} linkSrc={LinkDocPreview.LinkInfo.linkSrc} href={LinkDocPreview.LinkInfo.href}
                 addDocTab={LinkDocPreview.LinkInfo.addDocTab} /> : (null)}
+            <GestureOverlay >
+                {this.mainContent}
+            </GestureOverlay>
+            <PreviewCursor />
+            <LinkCreatedBox />
             <ContextMenu />
             <FormatShapePane />
             <RadialMenu />
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index 1fa185150..3fb0ff517 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -3,7 +3,7 @@
 .linkMenu {
     width: auto;
     height: auto;
-
+    position: absolute;
 
     .linkMenu-list {
 
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 234cd5e07..2d151e9bc 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -44,8 +44,8 @@ export class LinkMenu extends React.Component<Props> {
         LinkDocPreview.LinkInfo = undefined;
 
 
-        if (this._linkMenuRef && !!!this._linkMenuRef.current?.contains(e.target as any)) {
-            if (this._editorRef && !!!this._editorRef.current?.contains(e.target as any)) {
+        if (this._linkMenuRef && !this._linkMenuRef.current?.contains(e.target as any)) {
+            if (this._editorRef && !this._editorRef.current?.contains(e.target as any)) {
                 console.log("outside click");
                 DocumentLinksButton.EditLink = undefined;
             }
@@ -90,14 +90,16 @@ export class LinkMenu extends React.Component<Props> {
         const sourceDoc = this.props.docView.props.Document;
         const groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc);
         return <div className="linkMenu" ref={this._linkMenuRef} >
-             {!this._editingLink ? <div className="linkMenu-list" style={{
-                  left: this.props.location[0], top: this.props.location[1] }}>
-              {this.renderAllGroups(groups)} 
-              </div> : <div className="linkMenu-listEditor" style={{
-                  left: this.props.location[0], top: this.props.location[1]}}>
+            {!this._editingLink ? <div className="linkMenu-list" style={{
+                left: this.props.location[0], top: this.props.location[1]
+            }}>
+                {this.renderAllGroups(groups)}
+            </div> : <div className="linkMenu-listEditor" style={{
+                left: this.props.location[0], top: this.props.location[1]
+            }}>
                     <LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink}
                         showLinks={action(() => this._editingLink = undefined)} />
-                </div> 
+                </div>
             }
 
         </div>;
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 1c15b31de..e6e4aa6c2 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -63,7 +63,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             if (doubleTap && this.props.InMenu) {
                 //action(() => Doc.BrushDoc(this.props.View.Document));
                 DocumentLinksButton.StartLink = this.props.View;
-            } else if (!!!this.props.InMenu) {
+            } else if (!this.props.InMenu) {
                 console.log("editing");
                 this.props.View ? console.log("view") : null;
                 DocumentLinksButton.EditLink = this.props.View;
@@ -77,7 +77,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         if (this.props.InMenu) {
             DocumentLinksButton.StartLink = this.props.View;
             //action(() => Doc.BrushDoc(this.props.View.Document));
-        } else if (!!!this.props.InMenu) {
+        } else if (!this.props.InMenu) {
             DocumentLinksButton.EditLink = this.props.View;
             DocumentLinksButton.EditLinkLoc = [e.clientX + 10, e.clientY];
         }
-- 
cgit v1.2.3-70-g09d2


From c4ec1a6a5baff6574fe8236ad52386b7ea11057f Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sun, 12 Jul 2020 16:19:50 -0500
Subject: norm's changes

---
 deploy/assets/endLink.png                          | Bin 0 -> 10322 bytes
 deploy/assets/link.png                             | Bin 0 -> 8790 bytes
 deploy/assets/startLink.png                        | Bin 0 -> 10538 bytes
 src/client/views/DocumentButtonBar.tsx             |   5 +-
 src/client/views/MainView.tsx                      |   4 +-
 .../views/collections/CollectionLinearView.tsx     |   2 +-
 src/client/views/nodes/DocumentLinksButton.scss    |  19 ++-
 src/client/views/nodes/DocumentLinksButton.tsx     | 129 +++++++++++++--------
 8 files changed, 101 insertions(+), 58 deletions(-)
 create mode 100644 deploy/assets/endLink.png
 create mode 100644 deploy/assets/link.png
 create mode 100644 deploy/assets/startLink.png

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/deploy/assets/endLink.png b/deploy/assets/endLink.png
new file mode 100644
index 000000000..abadc9550
Binary files /dev/null and b/deploy/assets/endLink.png differ
diff --git a/deploy/assets/link.png b/deploy/assets/link.png
new file mode 100644
index 000000000..2dbcd61ce
Binary files /dev/null and b/deploy/assets/link.png differ
diff --git a/deploy/assets/startLink.png b/deploy/assets/startLink.png
new file mode 100644
index 000000000..8f3825682
Binary files /dev/null and b/deploy/assets/startLink.png differ
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 072648ef0..a3d24b3b6 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -274,7 +274,10 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const considerPush = isText && this.considerGoogleDocsPush;
         return <div className="documentButtonBar">
             <div className="documentButtonBar-button">
-                <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} />
+                <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} />
+            </div>
+            <div className="documentButtonBar-button">
+                <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} />
             </div>
             <div className="documentButtonBar-button">
                 {this.templateButton}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 92f1dfec0..2ed528836 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -6,7 +6,7 @@ import {
     faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
     faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTimesCircle,
     faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
-    faHeading, faRulerCombined, faFillDrip
+    faHeading, faRulerCombined, faFillDrip, faUnlink
 } from '@fortawesome/free-solid-svg-icons';
 import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -147,7 +147,7 @@ export class MainView extends React.Component {
             faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
             faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
             faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
-            faHeading, faRulerCombined, faFillDrip);
+            faHeading, faRulerCombined, faFillDrip, faUnlink);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 4c68cc949..dd4df20c9 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -186,7 +186,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
 
                     <Tooltip title="Exit link clicking mode" placement="top">
                         <span className="bottomPopup-exit" onClick={this.exitLongLinks}
-                        >Exit</span>
+                        >Clear</span>
                     </Tooltip>
 
                     {/* <FontAwesomeIcon icon="times-circle" size="lg" style={{ color: "red" }}
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 580e86442..35d99d44b 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -20,18 +20,27 @@
     justify-content: center;
     align-items: center;
 
-    &:hover {
-        background: deepskyblue;
-        transform: scale(1.05);
-        cursor: pointer;
-    }
+    // &:hover {
+    //     background: deepskyblue;
+    //     transform: scale(1.05);
+    //     cursor: pointer;
+    // }
 }
+
 .documentLinksButton {
     background-color: $link-color;
 }
+
 .documentLinksButton-endLink {
     border: red solid 2px;
+
+    &:hover {
+        background: deepskyblue;
+        transform: scale(1.05);
+        cursor: pointer;
+    }
 }
+
 .documentLinksButton-startLink {
     border: red solid 2px;
     background-color: rgba(255, 192, 203, 0.5);
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index e6e4aa6c2..83710cfbf 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -23,6 +23,7 @@ interface DocumentLinksButtonProps {
     Offset?: number[];
     AlwaysOn?: boolean;
     InMenu?: boolean;
+    StartLink?: boolean;
 }
 @observer
 export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> {
@@ -32,27 +33,30 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
     @action @undoBatch
     onLinkButtonMoved = (e: PointerEvent) => {
-        if (this._linkButton.current !== null) {
-            const linkDrag = UndoManager.StartBatch("Drag Link");
-            this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, e.pageX, e.pageY, {
-                dragComplete: dropEv => {
-                    const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
-                    if (this.props.View && linkDoc) {
-                        !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink");
-
-                        // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks)
-                        // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures
-                        // however, the dropped document isn't so accessible.  What we do is set the newly created link document on the documentView
-                        // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it.
-                        dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData);
-                        runInAction(() => this.props.View._link = linkDoc);
-                        setTimeout(action(() => this.props.View._link = undefined), 0);
-                    }
-                    linkDrag?.end();
-                },
-                hideSource: false
-            });
-            return true;
+        if (this.props.InMenu && this.props.StartLink) {
+            if (this._linkButton.current !== null) {
+                const linkDrag = UndoManager.StartBatch("Drag Link");
+                this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, e.pageX, e.pageY, {
+                    dragComplete: dropEv => {
+                        const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
+                        if (this.props.View && linkDoc) {
+                            !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink");
+
+                            // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks)
+                            // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures
+                            // however, the dropped document isn't so accessible.  What we do is set the newly created link document on the documentView
+                            // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it.
+                            dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData);
+                            runInAction(() => this.props.View._link = linkDoc);
+                            setTimeout(action(() => this.props.View._link = undefined), 0);
+                        }
+                        linkDrag?.end();
+                    },
+                    hideSource: false
+                });
+                return true;
+            }
+            return false;
         }
         return false;
     }
@@ -60,7 +64,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     @undoBatch
     onLinkButtonDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
-            if (doubleTap && this.props.InMenu) {
+            if (doubleTap && this.props.InMenu && this.props.StartLink) {
                 //action(() => Doc.BrushDoc(this.props.View.Document));
                 DocumentLinksButton.StartLink = this.props.View;
             } else if (!this.props.InMenu) {
@@ -74,7 +78,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
     @action @undoBatch
     onLinkClick = (e: React.MouseEvent): void => {
-        if (this.props.InMenu) {
+        if (this.props.InMenu && this.props.StartLink) {
             DocumentLinksButton.StartLink = this.props.View;
             //action(() => Doc.BrushDoc(this.props.View.Document));
         } else if (!this.props.InMenu) {
@@ -86,7 +90,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     @action @undoBatch
     completeLink = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, returnFalse, emptyFunction, action((e, doubleTap) => {
-            if (doubleTap) {
+            if (doubleTap && this.props.InMenu && !!!this.props.StartLink) {
                 if (DocumentLinksButton.StartLink === this.props.View) {
                     DocumentLinksButton.StartLink = undefined;
                     // action((e: React.PointerEvent<HTMLDivElement>) => {
@@ -128,27 +132,29 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             //     Doc.UnBrushDoc(this.props.View.Document);
             // });
         } else {
-            if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
-                const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
-                LinkManager.currentLink = linkDoc;
-                linkDoc ? linkDoc.hidden = true : null;
-                linkDoc ? linkDoc.linkDisplay = true : null;
-
-                runInAction(() => {
-                    if (linkDoc) {
-                        LinkCreatedBox.popupX = e.screenX;
-                        LinkCreatedBox.popupY = e.screenY - 133;
-                        LinkCreatedBox.linkCreated = true;
-
-                        if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
-                            LinkDescriptionPopup.popupX = e.screenX;
-                            LinkDescriptionPopup.popupY = e.screenY - 100;
-                            LinkDescriptionPopup.descriptionPopup = true;
-                        }
+            if (this.props.InMenu && !!!this.props.StartLink) {
+                if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
+                    const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
+                    LinkManager.currentLink = linkDoc;
+                    linkDoc ? linkDoc.hidden = true : null;
+                    linkDoc ? linkDoc.linkDisplay = true : null;
+
+                    runInAction(() => {
+                        if (linkDoc) {
+                            LinkCreatedBox.popupX = e.screenX;
+                            LinkCreatedBox.popupY = e.screenY - 133;
+                            LinkCreatedBox.linkCreated = true;
+
+                            if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
+                                LinkDescriptionPopup.popupX = e.screenX;
+                                LinkDescriptionPopup.popupY = e.screenY - 100;
+                                LinkDescriptionPopup.descriptionPopup = true;
+                            }
 
-                        setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
-                    }
-                });
+                            setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500);
+                        }
+                    });
+                }
             }
         }
     }
@@ -161,11 +167,29 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
     get linkButton() {
         const links = DocListCast(this.props.View.props.Document.links);
 
-        const title = this.props.InMenu ? "Drag or tap to create links" : DocumentLinksButton.StartLink ? "Tap to finish link" : "Tap to view links";
+        const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link";
+
+        const title = this.props.InMenu ? menuTitle : "Tap to view links";
+
+
+        const startLink = <img
+            style={{ width: "11px", height: "11px" }}
+            id={"startLink-icon"}
+            src={`/assets/${"startLink.png"}`} />;
+
+        const endLink = <img
+            style={{ width: "14px", height: "9px" }}
+            id={"endLink-icon"}
+            src={`/assets/${"endLink.png"}`} />;
+
+        const link = <img
+            style={{ width: "22px", height: "16px" }}
+            id={"link-icon"}
+            src={`/assets/${"link.png"}`} />;
 
         const linkButton = <div ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
             <div className={"documentLinksButton"} style={{
-                backgroundColor: DocumentLinksButton.StartLink && !!!this.props.InMenu ? "transparent" : this.props.InMenu ? "black" : "",
+                backgroundColor: this.props.InMenu ? "black" : "",
                 color: this.props.InMenu ? "white" : "black",
                 width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px", fontWeight: "bold"
             }}
@@ -178,12 +202,19 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             //     Location: [e.clientX, e.clientY + 20]
             // }))} 
             >
-                {links.length && !!!this.props.InMenu ? links.length : <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />}
+                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
+                    <FontAwesomeIcon className="documentdecorations-icon" icon="unlink" size="sm" /> : links.length} */}
+
+                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
+                    link : links.length} */}
+
+                {this.props.InMenu ? this.props.StartLink ? startLink :
+                    endLink : links.length}
             </div>
-            {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
+            {DocumentLinksButton.StartLink && this.props.InMenu && !!!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
                 style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }}
                 onPointerDown={this.completeLink} onClick={e => this.finishLinkClick(e)} /> : (null)}
-            {DocumentLinksButton.StartLink === this.props.View ? <div className={"documentLinksButton-startLink"}
+            {DocumentLinksButton.StartLink === this.props.View && this.props.InMenu && this.props.StartLink ? <div className={"documentLinksButton-startLink"}
                 style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }} /> : (null)}
         </div>;
         return (!links.length) && !this.props.AlwaysOn ? (null) :
-- 
cgit v1.2.3-70-g09d2


From 0dafe85b7d0c826340299a7e6b51190a6eaa7004 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Mon, 13 Jul 2020 17:56:46 -0500
Subject: fixed preview backgrounds, text size, tooltip size, adding labels,
 conditional end link btn, tooltips size

---
 src/client/views/DocumentButtonBar.tsx             | 106 +++++++++++----------
 src/client/views/DocumentDecorations.tsx           |  12 +--
 src/client/views/MainView.tsx                      |   4 +-
 .../views/collections/CollectionLinearView.tsx     |   9 +-
 src/client/views/linking/LinkEditor.scss           |  24 ++++-
 src/client/views/linking/LinkEditor.tsx            |  27 ++++--
 src/client/views/linking/LinkMenuItem.scss         |   1 +
 src/client/views/linking/LinkMenuItem.tsx          |   6 +-
 src/client/views/nodes/DocumentLinksButton.scss    |  12 +--
 src/client/views/nodes/DocumentLinksButton.tsx     |  24 ++---
 src/client/views/nodes/LinkDocPreview.tsx          |   3 +-
 .../formattedText/FormattedTextBoxComment.tsx      |   4 +-
 12 files changed, 135 insertions(+), 97 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index a3d24b3b6..c132eb5bb 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -119,7 +119,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <Tooltip title={`${published ? "Push" : "Publish"} to Google Docs`}>
+        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${published ? "Push" : "Publish"} to Google Docs`}</div></React.Fragment>}>
             <div
                 className="documentButtonBar-linker"
                 style={{ animation }}
@@ -138,46 +138,49 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const dataDoc = targetDoc && Doc.GetProto(targetDoc);
         const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
+
+        const title = (() => {
+            switch (this.openHover) {
+                default:
+                case UtilityButtonState.Default: return `${!dataDoc?.unchanged ? "Pull from" : "Fetch"} Google Docs`;
+                case UtilityButtonState.OpenRight: return "Open in Right Split";
+                case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
+            }
+        })();
+
         return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
-            title={(() => {
-                switch (this.openHover) {
-                    default:
-                    case UtilityButtonState.Default: return `${!dataDoc.unchanged ? "Pull from" : "Fetch"} Google Docs`;
-                    case UtilityButtonState.OpenRight: return "Open in Right Split";
-                    case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
-                }
-            })()}
-        ><div className="documentButtonBar-linker"
-            style={{ backgroundColor: this.pullColor }}
-            onPointerEnter={action(e => {
-                if (e.altKey) {
-                    this.openHover = UtilityButtonState.OpenExternally;
-                } else if (e.shiftKey) {
-                    this.openHover = UtilityButtonState.OpenRight;
-                }
-            })}
-            onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)}
-            onClick={async e => {
-                const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`;
-                if (e.shiftKey) {
-                    e.preventDefault();
-                    let googleDoc = await Cast(dataDoc.googleDoc, Doc);
-                    if (!googleDoc) {
-                        const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false };
-                        googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
-                        dataDoc.googleDoc = googleDoc;
+            title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+            <div className="documentButtonBar-linker"
+                style={{ backgroundColor: this.pullColor }}
+                onPointerEnter={action(e => {
+                    if (e.altKey) {
+                        this.openHover = UtilityButtonState.OpenExternally;
+                    } else if (e.shiftKey) {
+                        this.openHover = UtilityButtonState.OpenRight;
+                    }
+                })}
+                onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)}
+                onClick={async e => {
+                    const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`;
+                    if (e.shiftKey) {
+                        e.preventDefault();
+                        let googleDoc = await Cast(dataDoc.googleDoc, Doc);
+                        if (!googleDoc) {
+                            const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false };
+                            googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
+                            dataDoc.googleDoc = googleDoc;
+                        }
+                        CollectionDockingView.AddRightSplit(googleDoc);
+                    } else if (e.altKey) {
+                        e.preventDefault();
+                        window.open(googleDocUrl);
+                    } else {
+                        this.clearPullColor();
+                        DocumentButtonBar.hasPulledHack = false;
+                        targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
+                        dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
                     }
-                    CollectionDockingView.AddRightSplit(googleDoc);
-                } else if (e.altKey) {
-                    e.preventDefault();
-                    window.open(googleDocUrl);
-                } else {
-                    this.clearPullColor();
-                    DocumentButtonBar.hasPulledHack = false;
-                    targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
-                    dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
-                }
-            }}>
+                }}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm"
                     style={{ WebkitAnimation: animation, MozAnimation: animation }}
                     icon={(() => {
@@ -195,7 +198,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get pinButton() {
         const targetDoc = this.view0?.props.Document;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
-        return !targetDoc ? (null) : <Tooltip title={Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}>
+        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></React.Fragment>}>
             <div className="documentButtonBar-linker"
                 style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
@@ -207,14 +210,15 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     @computed
     get metadataButton() {
         const view0 = this.view0;
-        return !view0 ? (null) : <Tooltip title="Show metadata panel"><div className="documentButtonBar-linkFlyout">
-            <Flyout anchorPoint={anchorPoints.LEFT_TOP}
-                content={<MetadataEntryMenu docs={() => this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
-                <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
-                    {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
-                </div>
-            </Flyout>
-        </div></Tooltip>;
+        return !view0 ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show metadata panel</div></React.Fragment>}>
+            <div className="documentButtonBar-linkFlyout">
+                <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                    content={<MetadataEntryMenu docs={() => this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
+                    <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                        {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
+                    </div>
+                </Flyout>
+            </div></Tooltip>;
     }
 
     @computed
@@ -255,7 +259,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         Array.from(Object.values(Templates.TemplateList)).map(template =>
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !view0 ? (null) :
-            <Tooltip title="Tap: Customize layout.  Drag: Create alias" >
+            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Tap: Customize layout.  Drag: Create alias</div></React.Fragment>}>
                 <div className="documentButtonBar-linkFlyout" ref={this._dragRef}>
                     <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
                         content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
@@ -276,9 +280,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             <div className="documentButtonBar-button">
                 <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} />
             </div>
-            <div className="documentButtonBar-button">
+            {DocumentLinksButton.StartLink ? <div className="documentButtonBar-button">
                 <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} />
-            </div>
+            </div> : null}
             <div className="documentButtonBar-button">
                 {this.templateButton}
             </div>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index d7324e1a6..2e3c63cf2 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -547,11 +547,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
         const minimal = bounds.r - bounds.x < 100 ? true : false;
         const maximizeIcon = minimal ? (
-            <Tooltip title="Show context menu" placement="top">
+            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top">
                 <div className="documentDecorations-contextMenu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>) : (
-                <Tooltip title="Iconify" placement="top">
+                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Iconify</div></React.Fragment>} placement="top">
                     <div className="documentDecorations-minimizeButton" onClick={this.onCloseClick}>
                         {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
                         <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
@@ -575,7 +575,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 </div>}
             </> :
             <>
-                {minimal ? (null) : <Tooltip title="Show context menu" placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
+                {minimal ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
@@ -614,11 +614,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     {maximizeIcon}
                     {titleArea}
                     {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
-                        <Tooltip title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} placement="top">
+                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div></React.Fragment>} placement="top">
                             <div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
                                 {"_"}
                             </div></Tooltip>}
-                    <Tooltip title="Open Document in Tab" placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Open Document In Tab</div></React.Fragment>} placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
                         {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
                     </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
@@ -641,7 +641,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer"
                         onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                     {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
-                        <Tooltip title="tap to select containing document" placement="top">
+                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>tap to select containing document</div></React.Fragment>} placement="top">
                             <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
                                 onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
                                 <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 2ed528836..a54973489 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -6,7 +6,7 @@ import {
     faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
     faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTimesCircle,
     faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
-    faHeading, faRulerCombined, faFillDrip, faUnlink
+    faHeading, faRulerCombined, faFillDrip, faUnlink, faHandPaper
 } from '@fortawesome/free-solid-svg-icons';
 import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -147,7 +147,7 @@ export class MainView extends React.Component {
             faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
             faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
             faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
-            faHeading, faRulerCombined, faFillDrip, faUnlink);
+            faHeading, faRulerCombined, faFillDrip, faUnlink, faHandPaper);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index dd4df20c9..319cca70f 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -124,7 +124,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
 
         return <div className="collectionLinearView-outer">
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
-                <Tooltip title={BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"} placement="top">
+                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></React.Fragment>} placement="top">
                     {menuOpener}
                 </Tooltip>
                 <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
@@ -177,14 +177,15 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                     onPointerDown={e => e.stopPropagation()} >
                     <span className="bottomPopup-text" >
                         Creating link from: {DocumentLinksButton.StartLink.title} </span>
-                    <Tooltip title={LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
-                        "Turn on description pop-up"} placement="top">
+
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
+                        "Turn on description pop-up"} </div></React.Fragment>} placement="top">
                         <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}
                         > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
                         </span>
                     </Tooltip>
 
-                    <Tooltip title="Exit link clicking mode" placement="top">
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Exit link clicking mode </div></React.Fragment>} placement="top">
                         <span className="bottomPopup-exit" onClick={this.exitLongLinks}
                         >Clear</span>
                     </Tooltip>
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
index 87afc99eb..d26b7920a 100644
--- a/src/client/views/linking/LinkEditor.scss
+++ b/src/client/views/linking/LinkEditor.scss
@@ -13,6 +13,10 @@
     width: 18px;
     height: 18px;
     padding: 0;
+
+    &:hover {
+        cursor: pointer;
+    }
 }
 
 .linkEditor-info {
@@ -28,7 +32,13 @@
     .linkEditor-linkedTo {
         width: calc(100% - 26px);
         padding-left: 5px;
-        padding-right: 5px
+        padding-right: 5px;
+
+        .linkEditor-downArrow {
+            &:hover {
+                cursor: pointer;
+            }
+        }
     }
 }
 
@@ -43,6 +53,10 @@
 
     .button {
         color: black;
+
+        &:hover {
+            cursor: pointer;
+        }
     }
 }
 
@@ -83,6 +97,10 @@
             padding-right: 8px;
             height: 80%;
             color: white;
+
+            &:hover {
+                cursor: pointer;
+            }
         }
     }
 }
@@ -92,6 +110,10 @@
     padding-right: 6.5px;
     padding-bottom: 6px;
 
+    &:hover {
+        cursor: pointer;
+    }
+
     .linkEditor-followingDropdown-label {
         color: black;
     }
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index a26685318..1cc981d42 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -13,6 +13,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { DocumentLinksButton } from "../nodes/DocumentLinksButton";
 import { EditableView } from "../EditableView";
 import { RefObject } from "react";
+import { Tooltip } from "@material-ui/core";
 
 library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus);
 
@@ -285,15 +286,12 @@ interface LinkEditorProps {
 @observer
 export class LinkEditor extends React.Component<LinkEditorProps> {
 
-
     @observable description = StrCast(LinkManager.currentLink?.description);
     @observable openDropdown: boolean = false;
-
     @observable followBehavior = this.props.linkDoc.follow ? this.props.linkDoc.follow : "Default";
-
     @observable showInfo: boolean = false;
-
     @computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; }
+    @observable private buttonColor: string = "black";
 
 
     //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION";
@@ -308,6 +306,10 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
     setDescripValue = (value: string) => {
         if (LinkManager.currentLink) {
             LinkManager.currentLink.description = value;
+            this.buttonColor = "rgb(62, 133, 55)";
+            setTimeout(action(() => {
+                this.buttonColor = "black";
+            }), 750);
             return true;
         }
     }
@@ -349,7 +351,8 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
                     ></input>
                 </div>
                 <div className="linkEditor-description-add-button"
-                    onPointerDown={this.onDown}>Add</div>
+                    style={{ backgroundColor: this.buttonColor }}
+                    onPointerDown={this.onDown}>Set</div>
             </div></div>;
     }
 
@@ -413,15 +416,19 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
         return !destination ? (null) : (
             <div className="linkEditor">
                 <div className="linkEditor-info">
-                    <button className="linkEditor-button-back"
-                        style={{ display: this.props.hideback ? "none" : "" }}
-                        onClick={this.props.showLinks}>
-                        <FontAwesomeIcon icon="arrow-left" size="sm" /> </button>
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Return to link menu</div></React.Fragment>} placement="top">
+                        <button className="linkEditor-button-back"
+                            style={{ display: this.props.hideback ? "none" : "" }}
+                            onClick={this.props.showLinks}>
+                            <FontAwesomeIcon icon="arrow-left" size="sm" /> </button>
+                    </Tooltip>
                     <p className="linkEditor-linkedTo">Editing Link to: <b>{
                         destination.proto?.title ?? destination.title ?? "untitled"}</b></p>
                     {/* <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link">
                         <FontAwesomeIcon icon="trash" size="sm" /></button> */}
-                    <FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} />
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show more link information</div></React.Fragment>} placement="top">
+                        <div className="linkEditor-downArrow"><FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} /></div>
+                    </Tooltip>
                 </div>
                 {this.showInfo ? <div className="linkEditor-moreInfo">
                     <div>{this.props.linkDoc.author ? <div> <b>Author:</b> {this.props.linkDoc.author}</div> : null}</div>
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index f70f5a23e..4e13ef8c8 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -67,6 +67,7 @@
                         color: rgb(60, 90, 156);
                         //display: inline;
                         text-overflow: break;
+                        cursor: pointer;
                     }
                 }
             }
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index b451f0168..ff9401696 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -253,16 +253,16 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}>
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
-                            <Tooltip title={showTitle}>
+                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{showTitle}</div></React.Fragment>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.showLink}>
                                     <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
                             </Tooltip>
 
-                            <Tooltip title="Edit Link">
+                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Edit Link</div></React.Fragment>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.onEdit}>
                                     <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
                             </Tooltip>
-                            <Tooltip title="Delete Link">
+                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>}>
                                 <div className="button" onPointerDown={this.deleteLink}>
                                     <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
                             </Tooltip>
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 35d99d44b..97e714cd5 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -13,18 +13,18 @@
     color: black;
     text-transform: uppercase;
     letter-spacing: 2px;
-    font-size: 75%;
+    font-size: 10px;
     transition: transform 0.2s;
     text-align: center;
     display: flex;
     justify-content: center;
     align-items: center;
 
-    // &:hover {
-    //     background: deepskyblue;
-    //     transform: scale(1.05);
-    //     cursor: pointer;
-    // }
+    &:hover {
+        // background: deepskyblue;
+        // transform: scale(1.05);
+        cursor: pointer;
+    }
 }
 
 .documentLinksButton {
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 83710cfbf..96ff0157e 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -168,8 +168,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         const links = DocListCast(this.props.View.props.Document.links);
 
         const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link";
-
-        const title = this.props.InMenu ? menuTitle : "Tap to view links";
+        const buttonTitle = "Tap to view links";
+        const title = this.props.InMenu ? menuTitle : buttonTitle;
 
 
         const startLink = <img
@@ -202,14 +202,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             //     Location: [e.clientX, e.clientY + 20]
             // }))} 
             >
-                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="unlink" size="sm" /> : links.length} */}
 
-                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
-                    link : links.length} */}
+                {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
+                    <FontAwesomeIcon className="documentdecorations-icon" icon="hand-paper" size="sm" /> : links.length}
 
-                {this.props.InMenu ? this.props.StartLink ? startLink :
-                    endLink : links.length}
             </div>
             {DocumentLinksButton.StartLink && this.props.InMenu && !!!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
                 style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }}
@@ -217,10 +213,16 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             {DocumentLinksButton.StartLink === this.props.View && this.props.InMenu && this.props.StartLink ? <div className={"documentLinksButton-startLink"}
                 style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }} /> : (null)}
         </div>;
+
         return (!links.length) && !this.props.AlwaysOn ? (null) :
-            <Tooltip title={title}>
-                {linkButton}
-            </Tooltip>;
+            this.props.InMenu ?
+                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                    {linkButton}
+                </Tooltip> : !!!DocumentLinksButton.EditLink ?
+                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                        {linkButton}
+                    </Tooltip> :
+                    linkButton;
     }
     render() {
         return this.linkButton;
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 079920f56..1caa82380 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -123,7 +123,8 @@ export class LinkDocPreview extends React.Component<Props> {
                 bringToFront={returnFalse}
                 ContentScaling={returnOne}
                 NativeWidth={returnZero}
-                NativeHeight={returnZero} />;
+                NativeHeight={returnZero}
+                backgroundColor={this.props.backgroundColor} />;
     }
 
     render() {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index fa2548cb5..c98b5eac1 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -270,14 +270,14 @@ export class FormattedTextBoxComment {
                                         </div>
                                         <div className="wrapper" style={{ float: "right" }}>
 
-                                            <Tooltip title="Delete Link" placement="top">
+                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._deleteRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white"
                                                         size="sm" /></div>
                                             </Tooltip>
 
-                                            <Tooltip title="Follow Link" placement="top">
+                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Follow Link</div></React.Fragment>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._followRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white"
-- 
cgit v1.2.3-70-g09d2


From 866561aa20aff0f570d31edf64eae36cd2d35279 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 14 Jul 2020 17:27:19 -0400
Subject: fixed onClickHandler stuff to use functions properly.  fixed several
 linking to annotations/pushpins problems.

---
 src/client/documents/Documents.ts                  |  8 +-
 src/client/util/DocumentManager.ts                 |  4 +-
 src/client/util/LinkManager.ts                     | 11 ++-
 src/client/util/SettingsManager.tsx                |  4 +-
 src/client/views/DocumentButtonBar.tsx             |  2 +-
 src/client/views/MetadataEntryMenu.tsx             | 96 ++++++----------------
 src/client/views/collections/CollectionView.tsx    |  7 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 10 +--
 .../collectionFreeForm/FormatShapePane.tsx         |  2 +-
 .../collectionFreeForm/InkOptionsMenu.tsx          |  2 +-
 .../collectionGrid/CollectionGridView.tsx          |  2 +-
 .../CollectionMulticolumnView.tsx                  |  5 +-
 .../CollectionMultirowView.tsx                     |  4 +-
 src/client/views/linking/LinkMenuGroup.tsx         |  4 +-
 src/client/views/linking/LinkMenuItem.tsx          |  5 +-
 src/client/views/nodes/DocumentLinksButton.tsx     |  3 -
 src/client/views/nodes/DocumentView.tsx            | 17 ++--
 src/client/views/nodes/FieldView.tsx               |  2 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     |  2 +-
 src/fields/documentSchemas.ts                      |  3 +
 20 files changed, 78 insertions(+), 115 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 90cef31d9..1fd533b62 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -102,6 +102,8 @@ export interface DocumentOptions {
     childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view)
     childLayoutString?: string; // template string for collection to use to render its children
     hideFilterView?: boolean; // whether to hide the filter popout on collections
+    hideLinkButton?: boolean; // whether the blue link counter button should be hidden
+    hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden
     _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden
     isTemplateForField?: string; // the field key for which the containing document is a rendering template
     isTemplateDoc?: boolean;
@@ -137,7 +139,7 @@ export interface DocumentOptions {
     lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document.  see PresBox.
     "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form
     "onChildDoubleClick-rawScript"?: string; // onChildDoubleClick script in raw text form
-    "onChildClick-rawScript"?: string // on ChildClick script in raw text form
+    "onChildClick-rawScript"?: string; // on ChildClick script in raw text form
     "onClick-rawScript"?: string; // onClick script in raw text form
     "onCheckedClick-rawScript"?: string; // onChecked script in raw text form
     "onCheckedClick-params"?: List<string>; // parameter list for onChecked treeview functions
@@ -779,7 +781,7 @@ export namespace Docs {
 
 
         export function FontIconDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { ...(options || {}) });
+            return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { hideLinkButton: true, ...(options || {}) });
         }
 
         export function PresElementBoxDocument(options?: DocumentOptions) {
@@ -912,6 +914,8 @@ export namespace DocUtils {
         if (target.doc === Doc.UserDoc()) return undefined;
 
         const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView", description }, id);
+        linkDoc.linkDisplay = true;
+        linkDoc.hideAnhors = true;
         linkDoc.layout_linkView = Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null);
         Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1?.title +" (" + (self.linkRelationship||"to") +") "  + self.anchor2?.title');
 
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 1fa5faeb3..b66e7fdc4 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -146,7 +146,7 @@ export class DocumentManager {
         };
         const docView = getFirstDocView(targetDoc, originatingDoc);
         let annotatedDoc = await Cast(targetDoc.annotationOn, Doc);
-        if (annotatedDoc && !linkDoc?.isPushpin) {
+        if (annotatedDoc && !targetDoc?.isPushpin) {
             const first = getFirstDocView(annotatedDoc);
             if (first) {
                 annotatedDoc = first.props.Document;
@@ -156,7 +156,7 @@ export class DocumentManager {
             }
         }
         if (docView) {  // we have a docView already and aren't forced to create a new one ... just focus on the document.  TODO move into view if necessary otherwise just highlight?
-            if (linkDoc?.isPushpin) docView.props.Document.hidden = !docView.props.Document.hidden;
+            if (originatingDoc?.isPushpin) docView.props.Document.hidden = !docView.props.Document.hidden;
             else {
                 docView.props.Document.hidden && (docView.props.Document.hidden = undefined);
                 docView.props.focus(docView.props.Document, willZoom, undefined, focusAndFinish);
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 50f3fc1d6..974744344 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -63,12 +63,17 @@ export class LinkManager {
     }
 
     // finds all links that contain the given anchor
-    public getAllRelatedLinks(anchor: Doc): Doc[] {
+    public getAllDirectLinks(anchor: Doc): Doc[] {
         const related = LinkManager.Instance.getAllLinks().filter(link => {
             const protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, null));
             const protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null));
             return protomatch1 || protomatch2 || Doc.AreProtosEqual(link, anchor);
         });
+        return related;
+    }
+    // finds all links that contain the given anchor
+    public getAllRelatedLinks(anchor: Doc): Doc[] {
+        const related = LinkManager.Instance.getAllDirectLinks(anchor);
         DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).map(anno => {
             related.push(...LinkManager.Instance.getAllRelatedLinks(anno));
         });
@@ -208,4 +213,6 @@ export class LinkManager {
 }
 
 Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
-    "creates a link to inputted document", "(doc: any)");
\ No newline at end of file
+    "returns all the links to the document or its annotations", "(doc: any)");
+Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); },
+    "returns all the links directly to the document", "(doc: any)");
\ No newline at end of file
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index f7ca3942b..981ee698d 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -87,11 +87,11 @@ export default class SettingsManager extends React.Component<{}> {
     }
     @action
     googleAuthorize = (event: any) => {
-        GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true)
+        GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true);
     }
     @action
     hypothesisAuthorize = (event: any) => {
-        HypothesisAuthenticationManager.Instance.fetchAccessToken(true)
+        HypothesisAuthenticationManager.Instance.fetchAccessToken(true);
     }
 
     private get settingsInterface() {
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index c188618f4..927c192cd 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -208,7 +208,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const view0 = this.view0;
         return !view0 ? (null) : <Tooltip title="Show metadata panel"><div className="documentButtonBar-linkFlyout">
             <Flyout anchorPoint={anchorPoints.LEFT_TOP}
-                content={<MetadataEntryMenu docs={() => this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
+                content={<MetadataEntryMenu docs={this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
                 <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
                     {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
                 </div>
diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx
index b0752ffb2..ca8a6e1d7 100644
--- a/src/client/views/MetadataEntryMenu.tsx
+++ b/src/client/views/MetadataEntryMenu.tsx
@@ -3,14 +3,14 @@ import "./MetadataEntryMenu.scss";
 import { observer } from 'mobx-react';
 import { observable, action, runInAction, trace, computed, IReactionDisposer, reaction } from 'mobx';
 import { KeyValueBox } from './nodes/KeyValueBox';
-import { Doc, Field, DocListCastAsync } from '../../fields/Doc';
+import { Doc, Field, DocListCastAsync, DocListCast } from '../../fields/Doc';
 import * as Autosuggest from 'react-autosuggest';
-import { undoBatch } from '../util/UndoManager';
+import { undoBatch, UndoManager } from '../util/UndoManager';
 import { emptyFunction, emptyPath } from '../../Utils';
 
 export type DocLike = Doc | Doc[] | Promise<Doc> | Promise<Doc[]>;
 export interface MetadataEntryProps {
-    docs: DocLike | (() => DocLike);
+    docs: Doc[];
     onError?: () => boolean;
     suggestWithFunction?: boolean;
 }
@@ -39,26 +39,13 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
         let onProto: boolean = false;
         let value: string | undefined = undefined;
         let docs = this.props.docs;
-        if (typeof docs === "function") {
-            if (this.props.suggestWithFunction) {
-                docs = docs();
-            } else {
-                return;
-            }
-        }
-        docs = await docs;
-        if (docs instanceof Doc) {
-            await docs[this._currentKey];
-            value = Field.toKeyValueString(docs, this._currentKey);
-        } else {
-            for (const doc of docs) {
-                const v = await doc[this._currentKey];
-                onProto = onProto || !Object.keys(doc).includes(this._currentKey);
-                if (field === null) {
-                    field = v;
-                } else if (v !== field) {
-                    value = "multiple values";
-                }
+        for (const doc of docs) {
+            const v = await doc[this._currentKey];
+            onProto = onProto || !Object.keys(doc).includes(this._currentKey);
+            if (field === null) {
+                field = v;
+            } else if (v !== field) {
+                value = "multiple values";
             }
         }
         if (value === undefined) {
@@ -86,27 +73,16 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
             const script = KeyValueBox.CompileKVPScript(this._currentValue);
             if (!script) return;
 
-            let doc = this.props.docs;
-            if (typeof doc === "function") {
-                doc = doc();
-            }
-            doc = await doc;
-
-            let success: boolean;
-            if (doc instanceof Doc) {
-                success = KeyValueBox.ApplyKVPScript(doc, this._currentKey, script);
-            } else {
-                let childSuccess = true;
-                if (this._addChildren) {
-                    for (const document of doc) {
-                        const collectionChildren = await DocListCastAsync(document.data);
-                        if (collectionChildren) {
-                            childSuccess = collectionChildren.every(c => KeyValueBox.ApplyKVPScript(c, this._currentKey, script));
-                        }
+            let childSuccess = true;
+            if (this._addChildren) {
+                for (const document of this.props.docs) {
+                    const collectionChildren = DocListCast(document.data);
+                    if (collectionChildren) {
+                        childSuccess = collectionChildren.every(c => KeyValueBox.ApplyKVPScript(c, this._currentKey, script));
                     }
                 }
-                success = doc.every(d => KeyValueBox.ApplyKVPScript(d, this._currentKey, script)) && childSuccess;
             }
+            const success = this.props.docs.every(d => KeyValueBox.ApplyKVPScript(d, this._currentKey, script)) && childSuccess;
             if (!success) {
                 if (this.props.onError) {
                     if (this.props.onError()) {
@@ -132,24 +108,12 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
         }
     }
 
-    getKeySuggestions = async (value: string): Promise<string[]> => {
+    getKeySuggestions = (value: string) => {
         value = value.toLowerCase();
         let docs = this.props.docs;
-        if (typeof docs === "function") {
-            if (this.props.suggestWithFunction) {
-                docs = docs();
-            } else {
-                return [];
-            }
-        }
-        docs = await docs;
-        if (docs instanceof Doc) {
-            return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value));
-        } else {
-            const keys = new Set<string>();
-            docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
-            return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
-        }
+        const keys = new Set<string>();
+        docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
+        return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
     }
     getSuggestionValue = (suggestion: string) => suggestion;
 
@@ -157,9 +121,8 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
         return (null);
     }
     componentDidMount() {
-
         this._suggestionDispser = reaction(() => this._currentKey,
-            () => this.getKeySuggestions(this._currentKey).then(action((s: string[]) => this._allSuggestions = s)),
+            () => this._allSuggestions = this.getKeySuggestions(this._currentKey),
             { fireImmediately: true });
     }
     componentWillUnmount() {
@@ -171,19 +134,8 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
     }
 
     private get considerChildOptions() {
-        let docSource = this.props.docs;
-        if (typeof docSource === "function") {
-            docSource = docSource();
-        }
-        docSource = docSource as Doc[] | Doc;
-        if (docSource instanceof Doc) {
-            if (docSource._viewType === undefined) {
-                return (null);
-            }
-        } else if (Array.isArray(docSource)) {
-            if (!docSource.every(doc => doc._viewType !== undefined)) {
-                return null;
-            }
+        if (!this.props.docs.every(doc => doc._viewType !== undefined)) {
+            return null;
         }
         return (
             <div style={{ display: "flex" }}>
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 5165a8f11..6ab4645ea 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -140,17 +140,18 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             } else {
                 added.map(doc => {
                     const context = Cast(doc.context, Doc, null);
-                    if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG) &&
-                        !DocListCast(doc.links).some(d => d.isPushpin)) {
+                    if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
                         const pushpin = Docs.Create.FontIconDocument({
                             icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
                             _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null)
                         });
+                        pushpin.isPushpin = true;
+                        Doc.GetProto(pushpin).annotationOn = doc.annotationOn;
+                        Doc.SetInPlace(doc, "annotationOn", undefined, true);
                         Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin);
                         const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
                         const first = DocListCast(pushpin.links).find(d => d instanceof Doc);
                         first && (first.hidden = true);
-                        pushpinLink && (Doc.GetProto(pushpinLink).isPushpin = true);
                         doc.displayTimecode = undefined;
                     }
                     doc.context = this.props.Document;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f33b5371f..994f4ce6e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -939,9 +939,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     }
 
     @computed get libraryPath() { return this.props.LibraryPath ? [...this.props.LibraryPath, this.props.Document] : []; }
-    @computed get onChildClickHandler() { return () => (this.props.childClickScript || ScriptCast(this.Document.onChildClick)); }
-    @computed get onChildDoubleClickHandler() { return () => (this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick)); }
     @computed get backgroundActive() { return this.layoutDoc.isBackground && (this.props.ContainingCollectionView?.active() || this.props.active()); }
+    onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick);
+    onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
     backgroundHalo = () => BoolCast(this.Document.useClusters);
     parentActive = (outsideReaction: boolean) => this.props.active(outsideReaction) || this.backgroundActive ? true : false;
     getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps {
@@ -1186,8 +1186,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             const dragY = e.detail.clientY;
             const bounds = this._marqueeRef.current?.getBoundingClientRect();
 
-            let deltaX = dragX - bounds.left < 25 ? -2 : bounds.right - dragX < 25 ? 2 : 0;
-            let deltaY = dragY - bounds.top < 25 ? -2 : bounds.bottom - dragY < 25 ? 2 : 0;
+            const deltaX = dragX - bounds.left < 25 ? -2 : bounds.right - dragX < 25 ? 2 : 0;
+            const deltaY = dragY - bounds.top < 25 ? -2 : bounds.bottom - dragY < 25 ? 2 : 0;
             (deltaX !== 0 || deltaY !== 0) && this.continuePan(deltaX, deltaY);
         }
         e.stopPropagation();
@@ -1198,7 +1198,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             const dragY = this._lastClientY;
             const dragX = this._lastClientX;
             if (dragY !== undefined && dragX !== undefined && this._marqueeRef.current) {
-                const bounds = this._marqueeRef.current.getBoundingClientRect()!;
+                const bounds = this._marqueeRef.current.getBoundingClientRect();
                 this.Document._panY = NumCast(this.Document._panY) + deltaY;
                 this.Document._panX = NumCast(this.Document._panX) + deltaX;
                 if (dragY - bounds.top < 25 || bounds.bottom - dragY < 25 || dragX - bounds.left < 25 || bounds.right - dragX < 25) {
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index 9d9ce7f36..4e328d838 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -31,7 +31,7 @@ export default class FormatShapePane extends AntimodeMenu {
 
     getField(key: string) {
         return this.selectedInk?.reduce((p, i) =>
-            (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt<string>)
+            (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt<string>);
     }
 
     @computed get selectedInk() {
diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
index 15707ad9e..5d115df69 100644
--- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
@@ -128,7 +128,7 @@ export default class InkOptionsMenu extends AntimodeMenu {
                         // doc.strokeBezier === 300 ? doc.strokeBezier = 0 : doc.strokeBezier = 300;
                         break;
                     case "dash":
-                        doc.strokeDash = Number(value);
+                        doc.strokeDash = value;
                     default:
                         break;
                 }
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
index b2e506dfa..73d0ae374 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
@@ -31,7 +31,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) {
     @observable private _rowHeight: Opt<number>; // temporary store of row height to make change undoable
     @observable private _scroll: number = 0; // required to make sure the decorations box container updates on scroll
 
-    @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); }
+    onChildClickHandler = () => ScriptCast(this.Document.onChildClick);
 
     @computed get numCols() { return NumCast(this.props.Document.gridNumCols, 10); }
     @computed get rowHeight() { return this._rowHeight === undefined ? NumCast(this.props.Document.gridRowHeight, 100) : this._rowHeight; }
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 402e7563d..21d283547 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -202,9 +202,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
     }
 
 
-    @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); }
-    @computed get onChildDoubleClickHandler() { return () => ScriptCast(this.Document.onChildDoubleClick); }
-
+    onChildClickHandler = () => ScriptCast(this.Document.onChildClick);
+    onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick);
 
     addDocTab = (doc: Doc, where: string) => {
         if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) {
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index e4ef9b436..d02088a6c 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -202,8 +202,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
     }
 
 
-    @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); }
-    @computed get onChildDoubleClickHandler() { return () => ScriptCast(this.Document.onChildDoubleClick); }
+    onChildClickHandler = () => ScriptCast(this.Document.onChildClick);
+    onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick);
 
     addDocTab = (doc: Doc, where: string) => {
         if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) {
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 2f6b75437..2ae87ac13 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -11,6 +11,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import './LinkMenu.scss';
 import { LinkMenuItem, StartLinkTargetsDrag } from "./LinkMenuItem";
 import React = require("react");
+import { Cast } from "../../../fields/Types";
 
 interface LinkMenuGroupProps {
     sourceDoc: Doc;
@@ -66,7 +67,8 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
 
     render() {
         const groupItems = this.props.group.map(linkDoc => {
-            const destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
+            const destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc) ||
+                LinkManager.Instance.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={destination[Id] + this.props.sourceDoc[Id]}
                     groupType={this.props.groupType}
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index b451f0168..b92da6644 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -1,6 +1,6 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faArrowRight, faChevronDown, faChevronUp, faEdit, faEye, faTimes, faPencilAlt, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { FontAwesomeIcon, FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
 import { action, observable } from 'mobx';
 import { observer } from "mobx-react";
 import { Doc, DocListCast } from '../../../fields/Doc';
@@ -189,7 +189,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
         const eyeIcon = this.props.linkDoc.hidden ? "eye-slash" : "eye";
 
-        let destinationIcon: string = "";;
+        let destinationIcon: FontAwesomeIconProps["icon"] = "question";
         switch (this.props.destinationDoc.type) {
             case DocumentType.IMG: destinationIcon = "image"; break;
             case DocumentType.COMPARISON: destinationIcon = "columns"; break;
@@ -205,7 +205,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
             case DocumentType.SCRIPTING: destinationIcon = "terminal"; break;
             case DocumentType.IMPORT: destinationIcon = "cloud-upload-alt"; break;
             case DocumentType.DOCHOLDER: destinationIcon = "expand"; break;
-            default: "question";
         }
 
         const title = StrCast(this.props.destinationDoc.title).length > 18 ?
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 83710cfbf..823e25471 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -101,8 +101,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
                         const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
                         LinkManager.currentLink = linkDoc;
-                        linkDoc ? linkDoc.hidden = true : null;
-                        linkDoc ? linkDoc.linkDisplay = true : null;
 
                         runInAction(() => {
                             if (linkDoc) {
@@ -137,7 +135,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
                     LinkManager.currentLink = linkDoc;
                     linkDoc ? linkDoc.hidden = true : null;
-                    linkDoc ? linkDoc.linkDisplay = true : null;
 
                     runInAction(() => {
                         if (linkDoc) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7d9c4da87..a6771443a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -128,9 +128,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @computed get nativeWidth() { return NumCast(this.layoutDoc._nativeWidth, this.props.NativeWidth() || (this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0)); }
     @computed get nativeHeight() { return NumCast(this.layoutDoc._nativeHeight, this.props.NativeHeight() || (this.freezeDimensions ? this.layoutDoc[HeightSym]() : 0)); }
     @computed get onClickHandler() { return this.props.onClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); }
-    @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() || (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) || this.Document.onDoubleClick); }
-    @computed get onPointerDownHandler() { return this.props.onPointerDown?.() || ScriptCast(this.Document.onPointerDown) }
-    @computed get onPointerUpHandler() { return this.props.onPointerUp?.() || ScriptCast(this.Document.onPointerUp); }
+    @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() ?? (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) ?? this.Document.onDoubleClick); }
+    @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); }
+    @computed get onPointerUpHandler() { return this.props.onPointerUp?.() ?? ScriptCast(this.Document.onPointerUp); }
     NativeWidth = () => this.nativeWidth;
     NativeHeight = () => this.nativeHeight;
     onClickFunc = () => this.onClickHandler;
@@ -298,7 +298,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
                 if (!(e.nativeEvent as any).formattedHandled) {
                     if (this.onDoubleClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself
-                        const func = () => this.onDoubleClickHandler?.script.run({
+                        const func = () => this.onDoubleClickHandler.script.run({
                             this: this.layoutDoc,
                             self: this.rootDoc,
                             thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey
@@ -320,7 +320,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 }
             } else if (this.onClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself
                 //SelectionManager.DeselectAll();
-                const func = () => this.onClickHandler?.script.run({
+                const func = () => this.onClickHandler.script.run({
                     this: this.layoutDoc,
                     self: this.rootDoc,
                     thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey
@@ -556,7 +556,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         this.cleanUpInteractions();
 
         if (this.onPointerUpHandler?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
-            this.onPointerUpHandler?.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log);
+            this.onPointerUpHandler.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log);
             document.removeEventListener("pointerup", this.onPointerUp);
             return;
         }
@@ -644,7 +644,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const makeLink = action((linkDoc: Doc) => {
             LinkManager.currentLink = linkDoc;
             linkDoc.hidden = true;
-            linkDoc.linkDisplay = true;
 
             LinkCreatedBox.popupX = de.x;
             LinkCreatedBox.popupY = de.y - 33;
@@ -1076,7 +1075,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 layoutKey={this.finalLayoutKey} />
             {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors}
             {/* {this.allAnchors} */}
-            {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : <DocumentLinksButton View={this} Offset={[-15, 0]} />}
+            {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.layoutDoc.hideLinkButton || this.props.dontRegisterView ? (null) : <DocumentLinksButton View={this} Offset={[-15, 0]} />}
         </div>
         );
     }
@@ -1105,7 +1104,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         return (this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots
             this.layoutDoc.presBox ||  // presentationbox nodes
             this.props.dontRegisterView ? (null) : // view that are not registered
-            DocUtils.FilterDocs(DocListCast(this.Document.links), this.props.docFilters(), []).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
+            DocUtils.FilterDocs(LinkManager.Instance.getAllDirectLinks(this.Document), this.props.docFilters(), []).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
                 <DocumentView {...this.props} key={i + 1}
                     Document={d}
                     ContainingCollectionView={this.props.ContainingCollectionView}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index c57738361..48e1f6ce3 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -25,7 +25,7 @@ export interface FieldViewProps {
     Document: Doc;
     DataDoc?: Doc;
     LibraryPath: Doc[];
-    onClick?: ScriptField;
+    onClick?: () => ScriptField;
     dropAction: dropActionType;
     backgroundHalo?: () => boolean;
     docFilters: () => string[];
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 8da1f99b5..c8798d757 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -431,7 +431,7 @@ export default class RichTextMenu extends AntimodeMenu {
         const nextIsOL = this.view.state.selection.$from.nodeAfter?.type === schema.nodes.ordered_list;
         let inList: any = undefined;
         let fromList = -1;
-        let path: any = Array.from((this.view.state.selection.$from as any).path);
+        const path: any = Array.from((this.view.state.selection.$from as any).path);
         for (let i = 0; i < path.length; i++) {
             if (path[i]?.type === schema.nodes.ordered_list) {
                 inList = path[i];
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index 9dda644f3..ddffb56c3 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -65,6 +65,7 @@ export const documentSchema = createSchema({
     color: "string",            // foreground color of document
     fitToBox: "boolean",        // whether freeform view contents should be zoomed/panned to fill the area of the document view
     fontSize: "string",
+    hidden: "boolean",          // whether a document should not be displayed
     isInkMask: "boolean",       // is the document a mask (ie, sits on top of other documents, has an unbounded width/height that is dark, and content uses 'hard-light' mix-blend-mode to let other documents pop through)
     layout: "string",           // this is the native layout string for the document.  templates can be added using other fields and setting layoutKey below
     layoutKey: "string",        // holds the field key for the field that actually holds the current lyoat
@@ -87,6 +88,8 @@ export const documentSchema = createSchema({
     onPointerUp: ScriptField,   // script to run when document is clicked (can be overriden by an onClick prop)
     onDragStart: ScriptField,   // script to run when document is dragged (without being selected).  the script should return the Doc to be dropped.
     followLinkLocation: "string",// flag for where to place content when following a click interaction (e.g., onRight, inPlace, inTab, ) 
+    hideLinkButton: "boolean",  // whether the blue link counter button should be hidden
+    hideAllLinks: "boolean",    // whether all individual blue anchor dots should be hidden
     isInPlaceContainer: "boolean",// whether the marked object will display addDocTab() calls that target "inPlace" destinations
     isLinkButton: "boolean",    // whether document functions as a link follow button to follow the first link on the document when clicked   
     isBackground: "boolean",    // whether document is a background element and ignores input events (can only select with marquee)
-- 
cgit v1.2.3-70-g09d2


From 3fdee81100954e66f54c73661cb11967993ff467 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 15 Jul 2020 15:24:53 -0400
Subject: fixed tooltips to share a csss style.  added tooltips for richtext.

---
 src/client/documents/Documents.ts                  |  2 +-
 src/client/views/DocumentButtonBar.tsx             | 10 ++---
 src/client/views/DocumentDecorations.tsx           | 15 +++----
 src/client/views/MainView.scss                     |  4 ++
 .../views/collections/CollectionLinearView.tsx     | 20 +++++----
 src/client/views/collections/CollectionMenu.tsx    | 13 +++---
 src/client/views/collections/CollectionView.tsx    |  3 +-
 .../CollectionFreeFormLinkView.tsx                 | 12 +++---
 src/client/views/linking/LinkEditor.tsx            | 14 +++----
 src/client/views/linking/LinkMenuItem.tsx          | 19 +++------
 src/client/views/nodes/DocumentLinksButton.tsx     |  5 +--
 src/client/views/nodes/DocumentView.tsx            | 25 +++--------
 .../formattedText/FormattedTextBoxComment.tsx      |  4 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     | 49 +++++++++++++---------
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 15 files changed, 94 insertions(+), 103 deletions(-)

(limited to 'src/client/views/nodes/DocumentLinksButton.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1fd533b62..b57f4c6c7 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -915,7 +915,7 @@ export namespace DocUtils {
 
         const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView", description }, id);
         linkDoc.linkDisplay = true;
-        linkDoc.hideAnhors = true;
+        linkDoc.hidden = true;
         linkDoc.layout_linkView = Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null);
         Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1?.title +" (" + (self.linkRelationship||"to") +") "  + self.anchor2?.title');
 
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 05538a28e..45f4c7393 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -118,7 +118,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${published ? "Push" : "Publish"} to Google Docs`}</div></React.Fragment>}>
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>}>
             <div
                 className="documentButtonBar-linker"
                 style={{ animation }}
@@ -148,7 +148,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         })();
 
         return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
-            title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+            title={<><div className="dash-tooltip">{title}</div></>}>
             <div className="documentButtonBar-linker"
                 style={{ backgroundColor: this.pullColor }}
                 onPointerEnter={action(e => {
@@ -197,7 +197,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get pinButton() {
         const targetDoc = this.view0?.props.Document;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
-        return !targetDoc ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></React.Fragment>}>
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="documentButtonBar-linker"
                 style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
@@ -209,7 +209,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     @computed
     get metadataButton() {
         const view0 = this.view0;
-        return !view0 ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show metadata panel</div></React.Fragment>}>
+        return !view0 ? (null) : <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}>
             <div className="documentButtonBar-linkFlyout">
                 <Flyout anchorPoint={anchorPoints.LEFT_TOP}
                     content={<MetadataEntryMenu docs={this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
@@ -258,7 +258,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         Array.from(Object.values(Templates.TemplateList)).map(template =>
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !view0 ? (null) :
-            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Tap: Customize layout.  Drag: Create alias</div></React.Fragment>}>
+            <Tooltip title={<><div className="dash-tooltip">Tap: Customize layout.  Drag: Create alias</div></>}>
                 <div className="documentButtonBar-linkFlyout" ref={this._dragRef}>
                     <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
                         content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 2fd017f7b..376b1d46b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -81,6 +81,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
             if (documentView.props.renderDepth === 0 ||
                 documentView.props.treeViewDoc ||
+                !documentView.ContentDiv ||
                 Doc.AreProtosEqual(documentView.props.Document, Doc.UserDoc())) {
                 return bounds;
             }
@@ -88,7 +89,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             var [sptX, sptY] = transform.transformPoint(0, 0);
             let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight());
             if (documentView.props.Document.type === DocumentType.LINK) {
-                const docuBox = documentView.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
+                const docuBox = documentView.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
                 if (docuBox.length) {
                     const rect = docuBox[0].getBoundingClientRect();
                     sptX = rect.left;
@@ -544,11 +545,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
         const minimal = bounds.r - bounds.x < 100 ? true : false;
         const maximizeIcon = minimal ? (
-            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top">
+            <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top">
                 <div className="documentDecorations-contextMenu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>) : (
-                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Iconify</div></React.Fragment>} placement="top">
+                <Tooltip title={<><div className="dash-tooltip">Iconify</div></>} placement="top">
                     <div className="documentDecorations-minimizeButton" onClick={this.onCloseClick}>
                         {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/}
                         <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" />
@@ -572,7 +573,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 </div>}
             </> :
             <>
-                {minimal ? (null) : <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show context menu</div></React.Fragment>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
+                {minimal ? (null) : <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
                     <FontAwesomeIcon size="lg" icon="cog" />
                 </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
@@ -611,11 +612,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     {maximizeIcon}
                     {titleArea}
                     {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
-                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div></React.Fragment>} placement="top">
+                        <Tooltip title={<><div className="dash-tooltip">{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div></>} placement="top">
                             <div className="documentDecorations-iconifyButton" onPointerDown={this.onIconifyDown}>
                                 {"_"}
                             </div></Tooltip>}
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Open Document In Tab</div></React.Fragment>} placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
+                    <Tooltip title={<><div className="dash-tooltip">Open Document In Tab</div></>} placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
                         {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
                     </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
@@ -638,7 +639,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer"
                         onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                     {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) :
-                        <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>tap to select containing document</div></React.Fragment>} placement="top">
+                        <Tooltip title={<><div className="dash-tooltip">tap to select containing document</div></>} placement="top">
                             <div id="documentDecorations-levelSelector" className="documentDecorations-selector"
                                 onPointerDown={this.onSelectorUp} onContextMenu={e => e.preventDefault()}>
                                 <FontAwesomeIcon className="documentdecorations-times" icon={faArrowAltCircleUp} size="lg" />
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 5b142ffda..e1ddbc533 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -1,6 +1,10 @@
 @import "globalCssVariables";
 @import "nodeModuleOverrides";
 
+.dash-tooltip {
+    font-size: 11px;
+    padding: 2px;
+}
 
 .mainView-tabButtons {
     position: relative;
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 319cca70f..407524353 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -124,7 +124,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
 
         return <div className="collectionLinearView-outer">
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
-                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></React.Fragment>} placement="top">
+                <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></>} placement="top">
                     {menuOpener}
                 </Tooltip>
                 <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
@@ -176,18 +176,20 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                 }}
                     onPointerDown={e => e.stopPropagation()} >
                     <span className="bottomPopup-text" >
-                        Creating link from: {DocumentLinksButton.StartLink.title} </span>
+                        Creating link from: {DocumentLinksButton.StartLink.title}
+                    </span>
 
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
-                        "Turn on description pop-up"} </div></React.Fragment>} placement="top">
-                        <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}
-                        > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
+                    <Tooltip title={<><div className="dash-tooltip">{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" :
+                        "Turn on description pop-up"} </div></>} placement="top">
+                        <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}>
+                            Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
                         </span>
                     </Tooltip>
 
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Exit link clicking mode </div></React.Fragment>} placement="top">
-                        <span className="bottomPopup-exit" onClick={this.exitLongLinks}
-                        >Clear</span>
+                    <Tooltip title={<><div className="dash-tooltip">Exit link clicking mode </div></>} placement="top">
+                        <span className="bottomPopup-exit" onClick={this.exitLongLinks}>
+                            Clear
+                        </span>
                     </Tooltip>
 
                     {/* <FontAwesomeIcon icon="times-circle" size="lg" style={{ color: "red" }}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 827c3e299..0696b93db 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -38,12 +38,13 @@ export default class CollectionMenu extends AntimodeMenu {
     }
 
     render() {
-        return this.getElement([
-            !this.SelectedCollection ? <></> : <CollectionViewBaseChrome CollectionView={this.SelectedCollection} type={StrCast(this.SelectedCollection.props.Document._viewType) as CollectionViewType} />,
-            <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}>
-                <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
-            </button>
-        ]);
+        const button = <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}>
+            <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
+        </button>;
+
+        return this.getElement(!this.SelectedCollection ? [button] :
+            [<CollectionViewBaseChrome key="chrome" CollectionView={this.SelectedCollection} type={StrCast(this.SelectedCollection.props.Document._viewType) as CollectionViewType} />,
+            button]);
     }
 }
 
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c1a6b5b0d..c1da23470 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -142,6 +142,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                     const context = Cast(doc.context, Doc, null);
                     if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
                         const pushpin = Docs.Create.FontIconDocument({
+                            title: "pushpin",
                             icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
                             _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null)
                         });
@@ -150,8 +151,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                         Doc.SetInPlace(doc, "annotationOn", undefined, true);
                         Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin);
                         const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
-                        const first = DocListCast(pushpin.links).find(d => d instanceof Doc);
-                        first && (first.hidden = true);
                         doc.displayTimecode = undefined;
                     }
                     doc.context = this.props.Document;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index dea936113..0933d525a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -29,13 +29,13 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
     componentDidMount() {
         this._anchorDisposer = reaction(() => [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform(), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document)],
             action(() => {
-                if (SnappingManager.GetIsDragging()) return;
+                if (SnappingManager.GetIsDragging() || !this.props.A.ContentDiv || !this.props.B.ContentDiv) return;
                 setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render()
                 setTimeout(action(() => (!this.props.LinkDocs.length || !this.props.LinkDocs[0].linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line.
-                const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : [];
-                const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("linkAnchorBox-cont") : [];
-                const adiv = (acont.length ? acont[0] : this.props.A.ContentDiv!);
-                const bdiv = (bcont.length ? bcont[0] : this.props.B.ContentDiv!);
+                const acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : [];
+                const bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : [];
+                const adiv = (acont.length ? acont[0] : this.props.A.ContentDiv);
+                const bdiv = (bcont.length ? bcont[0] : this.props.B.ContentDiv);
                 const a = adiv.getBoundingClientRect();
                 const b = bdiv.getBoundingClientRect();
                 const abounds = adiv.parentElement!.getBoundingClientRect();
@@ -103,7 +103,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
 
 
     render() {
-        if (SnappingManager.GetIsDragging() || !this.props.LinkDocs.length) return null;
+        if (SnappingManager.GetIsDragging() || !this.props.A.ContentDiv || !this.props.B.ContentDiv || !this.props.LinkDocs.length) return (null);
         this.props.A.props.ScreenToLocalTransform().transform(this.props.B.props.ScreenToLocalTransform());
         const acont = this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
         const bcont = this.props.B.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index 1cc981d42..ed2bea722 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -288,7 +288,6 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
 
     @observable description = StrCast(LinkManager.currentLink?.description);
     @observable openDropdown: boolean = false;
-    @observable followBehavior = this.props.linkDoc.follow ? this.props.linkDoc.follow : "Default";
     @observable showInfo: boolean = false;
     @computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; }
     @observable private buttonColor: string = "black";
@@ -364,8 +363,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
     @action
     changeFollowBehavior = (follow: string) => {
         this.openDropdown = false;
-        this.followBehavior = follow;
-        this.props.linkDoc.follow = follow;
+        Doc.GetProto(this.props.linkDoc).followLinkLocation = follow;
     }
 
     @computed
@@ -376,7 +374,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
             <div className="linkEditor-followingDropdown-dropdown">
                 <div className="linkEditor-followingDropdown-header"
                     onPointerDown={this.changeDropdown}>
-                    {this.followBehavior}
+                    {StrCast(this.props.linkDoc.followLinkLocation, "Default")}
                     <FontAwesomeIcon className="linkEditor-followingDropdown-icon"
                         icon={this.openDropdown ? "chevron-up" : "chevron-down"}
                         size={"lg"} />
@@ -388,11 +386,11 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
                         Default
                         </div>
                     <div className="linkEditor-followingDropdown-option"
-                        onPointerDown={() => this.changeFollowBehavior("Always open in right tab")}>
+                        onPointerDown={() => this.changeFollowBehavior("onRight")}>
                         Always open in right tab
                         </div>
                     <div className="linkEditor-followingDropdown-option"
-                        onPointerDown={() => this.changeFollowBehavior("Always open in new tab")}>
+                        onPointerDown={() => this.changeFollowBehavior("inTab")}>
                         Always open in new tab
                         </div>
                 </div>
@@ -416,7 +414,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
         return !destination ? (null) : (
             <div className="linkEditor">
                 <div className="linkEditor-info">
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Return to link menu</div></React.Fragment>} placement="top">
+                    <Tooltip title={<><div className="dash-tooltip">Return to link menu</div></>} placement="top">
                         <button className="linkEditor-button-back"
                             style={{ display: this.props.hideback ? "none" : "" }}
                             onClick={this.props.showLinks}>
@@ -426,7 +424,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
                         destination.proto?.title ?? destination.title ?? "untitled"}</b></p>
                     {/* <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link">
                         <FontAwesomeIcon icon="trash" size="sm" /></button> */}
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Show more link information</div></React.Fragment>} placement="top">
+                    <Tooltip title={<><div className="dash-tooltip">Show more link information</div></>} placement="top">
                         <div className="linkEditor-downArrow"><FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} /></div>
                     </Tooltip>
                 </div>
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 6782f625b..0e847632b 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -16,7 +16,6 @@ import { DocumentView } from '../nodes/DocumentView';
 import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
 import { LinkDocPreview } from '../nodes/LinkDocPreview';
 import { Tooltip } from '@material-ui/core';
-import { RichTextField } from '../../../fields/RichTextField';
 import { DocumentType } from '../../documents/DocumentTypes';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash);
 
@@ -157,14 +156,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         DocumentLinksButton.EditLink = undefined;
         LinkDocPreview.LinkInfo = undefined;
 
-        if (this.props.linkDoc.follow) {
-            if (this.props.linkDoc.follow === "Default") {
-                DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false);
-            } else if (this.props.linkDoc.follow === "Always open in right tab") {
-                this.props.addDocTab(this.props.destinationDoc, "onRight");
-            } else if (this.props.linkDoc.follow === "Always open in new tab") {
-                this.props.addDocTab(this.props.destinationDoc, "inTab");
-            }
+        if (this.props.linkDoc.followLinkLocation && this.props.linkDoc.followLinkLocation !== "Default") {
+            this.props.addDocTab(this.props.destinationDoc, StrCast(this.props.linkDoc.followLinkLocation));
         } else {
             DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false);
         }
@@ -221,8 +214,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 StrCast(this.props.linkDoc.storedText).substr(0, 18)
                 : this.props.linkDoc.storedText : undefined : undefined;
 
-        const showTitle = this.props.linkDoc.hidden ? "Show link" : "Hide link";
-
         return (
             <div className="linkMenu-item">
                 <div className={canExpand ? "linkMenu-item-content expand-three" : "linkMenu-item-content expand-two"}>
@@ -255,16 +246,16 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}>
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
 
-                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{showTitle}</div></React.Fragment>}>
+                            <Tooltip title={<><div className="dash-tooltip">{this.props.linkDoc.hidden ? "Show link" : "Hide link"}</div></>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.showLink}>
                                     <FontAwesomeIcon className="fa-icon" icon={eyeIcon} size="sm" /></div>
                             </Tooltip>
 
-                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Edit Link</div></React.Fragment>}>
+                            <Tooltip title={<><div className="dash-tooltip">Edit Link</div></>}>
                                 <div className="button" ref={this._editRef} onPointerDown={this.onEdit}>
                                     <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
                             </Tooltip>
-                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>}>
+                            <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>}>
                                 <div className="button" onPointerDown={this.deleteLink}>
                                     <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div>
                             </Tooltip>
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 01c068966..bbef48e44 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -134,7 +134,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
                     const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
                     LinkManager.currentLink = linkDoc;
-                    linkDoc ? linkDoc.hidden = true : null;
 
                     runInAction(() => {
                         if (linkDoc) {
@@ -213,10 +212,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
         return (!links.length) && !this.props.AlwaysOn ? (null) :
             this.props.InMenu ?
-                <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                <Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
                     {linkButton}
                 </Tooltip> : !!!DocumentLinksButton.EditLink ?
-                    <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>{title}</div></React.Fragment>}>
+                    <Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
                         {linkButton}
                     </Tooltip> :
                     linkButton;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a6771443a..c0a8b3a59 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -589,16 +589,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch
     toggleLinkButtonBehavior = (): void => {
+        this.Document.ignoreClick = false;
         if (this.Document.isLinkButton || this.onClickHandler || this.Document.ignoreClick) {
             this.Document.isLinkButton = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = false);
-            this.Document.ignoreClick = false;
             this.Document.onClick = this.layoutDoc.onClick = undefined;
         } else {
             this.Document.isLinkButton = true;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = true);
             this.Document.followLinkZoom = false;
             this.Document.followLinkLocation = undefined;
         }
@@ -606,14 +602,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch
     toggleFollowInPlace = (): void => {
+        this.Document.ignoreClick = false;
+        this.Document.isLinkButton = !this.Document.isLinkButton;
         if (this.Document.isLinkButton) {
-            this.Document.isLinkButton = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = false);
-        } else {
-            this.Document.isLinkButton = true;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = true);
             this.Document.followLinkZoom = true;
             this.Document.followLinkLocation = "inPlace";
         }
@@ -621,15 +612,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch
     toggleFollowOnRight = (): void => {
+        this.Document.ignoreClick = false;
+        this.Document.isLinkButton = !this.Document.isLinkButton;
         if (this.Document.isLinkButton) {
-            this.Document.isLinkButton = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = false);
-        } else {
-            this.Document.isLinkButton = true;
             this.Document.followLinkZoom = false;
-            const first = DocListCast(this.Document.links).find(d => d instanceof Doc);
-            first && (first.hidden = true);
             this.Document.followLinkLocation = "onRight";
         }
     }
@@ -643,7 +629,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
         const makeLink = action((linkDoc: Doc) => {
             LinkManager.currentLink = linkDoc;
-            linkDoc.hidden = true;
 
             LinkCreatedBox.popupX = de.x;
             LinkCreatedBox.popupY = de.y - 33;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index c98b5eac1..3687d5513 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -270,14 +270,14 @@ export class FormattedTextBoxComment {
                                         </div>
                                         <div className="wrapper" style={{ float: "right" }}>
 
-                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Delete Link</div></React.Fragment>} placement="top">
+                                            <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._deleteRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="trash" color="white"
                                                         size="sm" /></div>
                                             </Tooltip>
 
-                                            <Tooltip title={<React.Fragment><div style={{ fontSize: "11px", padding: "2px" }}>Follow Link</div></React.Fragment>} placement="top">
+                                            <Tooltip title={<><div className="dash-tooltip">Follow Link</div></>} placement="top">
                                                 <div className="FormattedTextBoxComment-button"
                                                     ref={(r) => this._followRef = r}>
                                                     <FontAwesomeIcon className="FormattedTextBoxComment-fa-icon" icon="arrow-right" color="white"
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index d0e6f3b37..63f6fdc54 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -24,6 +24,7 @@ import "./RichTextMenu.scss";
 import { schema } from "./schema_rts";
 import { TraceMobx } from "../../../../fields/util";
 import { UndoManager } from "../../../util/UndoManager";
+import { Tooltip } from "@material-ui/core";
 const { toggleMark } = require("prosemirror-commands");
 
 library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faOutdent, faIndent, faHandPointLeft, faHandPointRight, faEyeDropper, faCaretDown, faPalette, faHighlighter, faLink, faPaintRoller);
@@ -357,9 +358,11 @@ export default class RichTextMenu extends AntimodeMenu {
         }
 
         return (
-            <button className={"antimodeMenu-button" + (isActive ? " active" : "")} key={title} title={title} onPointerDown={onClick}>
-                <FontAwesomeIcon icon={faIcon as IconProp} size="lg" />
-            </button>
+            <Tooltip title={<div className="dash-tooltip">{title}</div>} key={title} placement="bottom">
+                <button className={"antimodeMenu-button" + (isActive ? " active" : "")} onPointerDown={onClick}>
+                    <FontAwesomeIcon icon={faIcon as IconProp} size="lg" />
+                </button>
+            </Tooltip>
         );
     }
 
@@ -388,7 +391,9 @@ export default class RichTextMenu extends AntimodeMenu {
                 }
             });
         }
-        return <select onChange={onChange} value={activeOption} key={key}>{items}</select>;
+        return <Tooltip key={key} title={<div className="dash-tooltip">{key}</div>} placement="bottom">
+            <select onChange={onChange} value={activeOption}>{items}</select>
+        </Tooltip>;
     }
 
     createNodesDropdown(activeMap: string, options: { node: NodeType | any | null, title: string, label: string, command: (node: NodeType | any) => void, hidden?: boolean, style?: {} }[], key: string, setter: (val: string) => {}): JSX.Element {
@@ -412,7 +417,10 @@ export default class RichTextMenu extends AntimodeMenu {
                 }
             });
         }
-        return <select value={activeOption} onChange={e => onChange(e.target.value)} key={key}>{items}</select>;
+
+        return <Tooltip key={key} title={<div className="dash-tooltip">{key}</div>} placement="bottom">
+            <select value={activeOption} onChange={e => onChange(e.target.value)}>{items}</select>
+        </Tooltip>;
     }
 
     changeFontSize = (mark: Mark, view: EditorView) => {
@@ -595,10 +603,11 @@ export default class RichTextMenu extends AntimodeMenu {
             label = "No marks are currently stored";
         }
 
-        const button =
-            <button className="antimodeMenu-button" title="" onPointerDown={onBrushClick} style={this.brushMarks?.size > 0 ? { backgroundColor: "121212" } : {}}>
+        const button = <Tooltip title={<div className="dash-tooltip">style brush</div>} placement="bottom">
+            <button className="antimodeMenu-button" onPointerDown={onBrushClick} style={this.brushMarks?.size > 0 ? { backgroundColor: "121212" } : {}}>
                 <FontAwesomeIcon icon="paint-roller" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.brushMarks?.size > 0 ? 45 : 0}deg)` }} />
-            </button>;
+            </button>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown">
@@ -667,11 +676,12 @@ export default class RichTextMenu extends AntimodeMenu {
             self.TextView.EditorView!.focus();
         }
 
-        const button =
-            <button className="antimodeMenu-button color-preview-button" title="" onPointerDown={onColorClick}>
+        const button = <Tooltip title={<div className="dash-tooltip">set font color</div>} placement="bottom">
+            <button className="antimodeMenu-button color-preview-button" onPointerDown={onColorClick}>
                 <FontAwesomeIcon icon="palette" size="lg" />
                 <div className="color-preview" style={{ backgroundColor: this.activeFontColor }}></div>
-            </button>;
+            </button>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown" >
@@ -720,11 +730,12 @@ export default class RichTextMenu extends AntimodeMenu {
             UndoManager.RunInBatch(() => self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch), "rt highlighter");
         }
 
-        const button =
-            <button className="antimodeMenu-button color-preview-button" title="" key="highilghter-button" onPointerDown={onHighlightClick}>
+        const button = <Tooltip title={<div className="dash-tooltip">set highlight color</div>} placement="bottom">
+            <button className="antimodeMenu-button color-preview-button" key="highilghter-button" onPointerDown={onHighlightClick}>
                 <FontAwesomeIcon icon="highlighter" size="lg" />
                 <div className="color-preview" style={{ backgroundColor: this.activeHighlightColor }}></div>
-            </button>;
+            </button>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown">
@@ -763,7 +774,9 @@ export default class RichTextMenu extends AntimodeMenu {
 
         const link = this.currentLink ? this.currentLink : "";
 
-        const button = <FontAwesomeIcon icon="link" size="lg" />;
+        const button = <Tooltip title={<div className="dash-tooltip">set hyperlink</div>} placement="bottom">
+            <div><FontAwesomeIcon icon="link" size="lg" /> </div>
+        </Tooltip>;
 
         const dropdownContent =
             <div className="dropdown link-menu">
@@ -774,9 +787,7 @@ export default class RichTextMenu extends AntimodeMenu {
                 <button className="remove-button" onPointerDown={e => this.deleteLink()}>Remove link</button>
             </div>;
 
-        return (
-            <ButtonDropdown view={this.view} key={"link button"} button={button} dropdownContent={dropdownContent} openDropdownOnButton={true} />
-        );
+        return <ButtonDropdown view={this.view} key={"link button"} button={button} dropdownContent={dropdownContent} openDropdownOnButton={true} />;
     }
 
     async getTextLinkTargetTitle() {
@@ -935,7 +946,7 @@ export default class RichTextMenu extends AntimodeMenu {
                 {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => this.activeFontSize = val)),
                 this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family", action((val: string) => this.activeFontFamily = val)),
                 <div className="richTextMenu-divider" key="divider 4" />,
-                this.createNodesDropdown(this.activeListType, this.listTypeOptions, "nodes", action((val: string) => this.activeListType = val)),
+                this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", action((val: string) => this.activeListType = val)),
                 this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer),
                 this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote),
                 this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule),
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 4e5fdbfbb..56212a773 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -637,7 +637,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
 
     @action
     onZoomWheel = (e: React.WheelEvent) => {
-        if (this.active()) {
+        if (this.active(true)) {
             e.stopPropagation();
             if (e.ctrlKey) {
                 const curScale = Number(this._pdfViewer.currentScaleValue);
-- 
cgit v1.2.3-70-g09d2

