From 0759b23448de29158367f344342e939dfa6eaf48 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Wed, 21 Aug 2019 11:00:08 -0400
Subject: moved links to own folder

---
 src/client/views/linking/LinkMenuItem.tsx | 282 ++++++++++++++++++++++++++++++
 1 file changed, 282 insertions(+)
 create mode 100644 src/client/views/linking/LinkMenuItem.tsx

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
new file mode 100644
index 000000000..7dc0a9fcd
--- /dev/null
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -0,0 +1,282 @@
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { observer } from "mobx-react";
+import { DocumentManager } from "../../util/DocumentManager";
+import { undoBatch } from "../../util/UndoManager";
+import './LinkMenu.scss';
+import React = require("react");
+import { Doc, DocListCastAsync } from '../../../new_fields/Doc';
+import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types';
+import { observable, action } from 'mobx';
+import { LinkManager } from '../../util/LinkManager';
+import { DragLinkAsDocument } from '../../util/DragManager';
+import { CollectionDockingView } from '../collections/CollectionDockingView';
+import { SelectionManager } from '../../util/SelectionManager';
+import { CollectionViewType } from '../collections/CollectionBaseView';
+import { DocumentView } from '../nodes/DocumentView';
+library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp);
+
+
+interface LinkMenuItemProps {
+    groupType: string;
+    linkDoc: Doc;
+    sourceDoc: Doc;
+    destinationDoc: Doc;
+    showEditor: (linkDoc: Doc) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+}
+
+@observer
+export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
+    private _drag = React.createRef<HTMLDivElement>();
+    @observable private _showMore: boolean = false;
+    @action toggleShowMore() { this._showMore = !this._showMore; }
+
+
+    unhighlight = () => {
+        Doc.UnhighlightAll();
+        document.removeEventListener("pointerdown", this.unhighlight);
+    }
+
+    @action
+    highlightDoc = () => {
+        document.removeEventListener("pointerdown", this.unhighlight);
+        Doc.HighlightDoc(this.props.destinationDoc);
+        window.setTimeout(() => {
+            document.addEventListener("pointerdown", this.unhighlight);
+        }, 10000);
+    }
+
+    // NOT TESTED
+    // col = collection the doc is in
+    // target = the document to center on
+    @undoBatch
+    openLinkColRight = ({ col, target }: { col: Doc, target: Doc }) => {
+        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+            const newPanX = NumCast(target.x) + NumCast(target.width) / NumCast(target.zoomBasis, 1) / 2;
+            const newPanY = NumCast(target.y) + NumCast(target.height) / NumCast(target.zoomBasis, 1) / 2;
+            col.panX = newPanX;
+            col.panY = newPanY;
+        }
+        CollectionDockingView.Instance.AddRightSplit(col, undefined);
+    }
+
+    // DONE
+    // this opens the linked doc in a right split, NOT in its collection
+    @undoBatch
+    openLinkRight = () => {
+        this.highlightDoc();
+        let alias = Doc.MakeAlias(this.props.destinationDoc);
+        CollectionDockingView.Instance.AddRightSplit(alias, undefined);
+        SelectionManager.DeselectAll();
+    }
+
+    // DONE
+    // this is the standard "follow link" (jump to document)
+    // taken from follow link
+    @undoBatch
+    jumpToLink = async (shouldZoom: boolean) => {
+        //there is an issue right now so this will be false automatically
+        shouldZoom = false;
+        this.highlightDoc();
+        let jumpToDoc = this.props.destinationDoc;
+        let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc));
+        if (pdfDoc) {
+            jumpToDoc = pdfDoc;
+        }
+        let proto = Doc.GetProto(this.props.linkDoc);
+        let targetContext = await Cast(proto.targetContext, Doc);
+        let sourceContext = await Cast(proto.sourceContext, Doc);
+        let self = this;
+
+        let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
+
+        if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext);
+        }
+        else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!));
+        }
+        else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page)));
+
+        }
+        else {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, dockingFunc);
+        }
+    }
+
+    // DONE
+    // opens link in new tab (not in a collection)
+    // this opens it full screen, do we need a separate full screen option?
+    @undoBatch
+    openLinkTab = () => {
+        this.highlightDoc();
+        let fullScreenAlias = Doc.MakeAlias(this.props.destinationDoc);
+        this.props.addDocTab(fullScreenAlias, undefined, "inTab");
+        SelectionManager.DeselectAll();
+    }
+
+    // NOT TESTED
+    // opens link in new tab in collection
+    // col = collection the doc is in
+    // target = the document to center on
+    @undoBatch
+    openLinkColTab = ({ col, target }: { col: Doc, target: Doc }) => {
+        this.highlightDoc();
+        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+            const newPanX = NumCast(target.x) + NumCast(target.width) / NumCast(target.zoomBasis, 1) / 2;
+            const newPanY = NumCast(target.y) + NumCast(target.height) / NumCast(target.zoomBasis, 1) / 2;
+            col.panX = newPanX;
+            col.panY = newPanY;
+        }
+        // CollectionDockingView.Instance.AddRightSplit(col, undefined);
+        this.props.addDocTab(col, undefined, "inTab");
+        SelectionManager.DeselectAll();
+    }
+
+    // this will open a link next to the source doc
+    @undoBatch
+    openLinkInPlace = () => {
+        this.highlightDoc();
+
+        let alias = Doc.MakeAlias(this.props.destinationDoc);
+        let y = this.props.sourceDoc.y;
+        let x = this.props.sourceDoc.x;
+        let parentView: any = undefined;
+        let parentDoc: Doc = this.props.sourceDoc;
+
+        SelectionManager.SelectedDocuments().map(dv => {
+            if (dv.props.Document === this.props.sourceDoc) {
+                parentView = dv.props.ContainingCollectionView;
+            }
+        });
+
+        if (parentView) {
+            // console.log(parentDoc)
+            console.log(parentView.props.addDocument);
+        }
+    }
+
+    //set this to be the default link behavior, can be any of the above
+    private defaultLinkBehavior: any = this.openLinkInPlace;
+
+    onEdit = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        this.props.showEditor(this.props.linkDoc);
+        SelectionManager.DeselectAll();
+    }
+
+    renderMetadata = (): JSX.Element => {
+        let groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc);
+        let index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase());
+        let groupDoc = index > -1 ? groups[index] : undefined;
+
+        let mdRows: Array<JSX.Element> = [];
+        if (groupDoc) {
+            let mdDoc = Cast(groupDoc.metadata, Doc, null);
+            if (mdDoc) {
+                let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType);
+                mdRows = keys.map(key => {
+                    return (<div key={key} className="link-metadata-row"><b>{key}</b>: {StrCast(mdDoc[key])}</div>);
+                });
+            }
+        }
+
+        return (<div className="link-metadata">{mdRows}</div>);
+    }
+
+    onLinkButtonDown = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        document.removeEventListener("pointermove", this.onLinkButtonMoved);
+        document.addEventListener("pointermove", this.onLinkButtonMoved);
+        document.removeEventListener("pointerup", this.onLinkButtonUp);
+        document.addEventListener("pointerup", this.onLinkButtonUp);
+    }
+
+    onLinkButtonUp = (e: PointerEvent): void => {
+        document.removeEventListener("pointermove", this.onLinkButtonMoved);
+        document.removeEventListener("pointerup", this.onLinkButtonUp);
+        e.stopPropagation();
+    }
+
+    onLinkButtonMoved = async (e: PointerEvent) => {
+        if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) {
+            document.removeEventListener("pointermove", this.onLinkButtonMoved);
+            document.removeEventListener("pointerup", this.onLinkButtonUp);
+
+            DragLinkAsDocument(this._drag.current, e.x, e.y, this.props.linkDoc, this.props.sourceDoc);
+        }
+        e.stopPropagation();
+    }
+
+    render() {
+
+        let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType);
+        let canExpand = keys ? keys.length > 0 : false;
+
+        return (
+            <div className="linkMenu-item">
+                <div className={canExpand ? "linkMenu-item-content expand-three" : "linkMenu-item-content expand-two"}>
+                    <div className="link-name">
+                        <p ref={this._drag} onPointerDown={this.onLinkButtonDown}>{StrCast(this.props.destinationDoc.title)}</p>
+                        <div className="linkMenu-item-buttons">
+                            {canExpand ? <div title="Show more" className="button" onPointerDown={() => this.toggleShowMore()}>
+                                <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
+                            <div title="Edit link" className="button" onPointerDown={this.onEdit}><FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
+                            {/* Original */}
+                            {/* <div title="Follow link" className="button" onPointerDown={this.onFollowLink}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */}
+                            {/* New */}
+                            <div title="Follow link" className="button" onPointerDown={this.defaultLinkBehavior}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
+                        </div>
+                    </div>
+                    {this._showMore ? this.renderMetadata() : <></>}
+                </div>
+
+            </div >
+        );
+    }
+}
+
+    // @undoBatch
+    // onFollowLink = async (e: React.PointerEvent): Promise<void> => {
+    //     e.stopPropagation();
+    //     e.persist();
+    //     let jumpToDoc = this.props.destinationDoc;
+    //     let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc));
+    //     if (pdfDoc) {
+    //         jumpToDoc = pdfDoc;
+    //     }
+    //     let proto = Doc.GetProto(this.props.linkDoc);
+    //     let targetContext = await Cast(proto.targetContext, Doc);
+    //     let sourceContext = await Cast(proto.sourceContext, Doc);
+    //     let self = this;
+
+
+    //     let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
+    //     if (e.ctrlKey) {
+    //         dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined);
+    //     }
+
+    //     if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) {
+    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, async document => dockingFunc(document), undefined, targetContext!);
+    //         console.log("1")
+    //     }
+    //     else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) {
+    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!));
+    //         console.log("2")
+    //     }
+    //     else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
+    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page)));
+    //         console.log("3")
+
+    //     }
+    //     else {
+    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc);
+    //         console.log("4")
+
+    //     }
+    // }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 11d2743b553da47da88e77de1ac758e16e09b3e0 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Wed, 21 Aug 2019 13:55:46 -0400
Subject: adding docs works

---
 src/client/views/linking/LinkFollowBox.tsx  |  3 ++-
 src/client/views/linking/LinkMenuItem.tsx   | 26 ++++++++++++++------------
 src/client/views/nodes/FormattedTextBox.tsx |  2 +-
 3 files changed, 17 insertions(+), 14 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 487281d50..061a4fa93 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -1,9 +1,10 @@
 import { observable, computed, action, trace } from "mobx";
 import React = require("react");
 import { observer } from "mobx-react";
-import { FieldViewProps } from "../nodes/FieldView";
+import { FieldViewProps, FieldView } from "../nodes/FieldView";
 
 @observer
 export class LinkFollowBox extends React.Component<FieldViewProps> {
 
+    public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); }
 }
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 7dc0a9fcd..65516b374 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -1,12 +1,12 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
+import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp, faGlobeAsia } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { observer } from "mobx-react";
 import { DocumentManager } from "../../util/DocumentManager";
 import { undoBatch } from "../../util/UndoManager";
 import './LinkMenu.scss';
 import React = require("react");
-import { Doc, DocListCastAsync } from '../../../new_fields/Doc';
+import { Doc, DocListCastAsync, WidthSym } from '../../../new_fields/Doc';
 import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types';
 import { observable, action } from 'mobx';
 import { LinkManager } from '../../util/LinkManager';
@@ -138,27 +138,29 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         SelectionManager.DeselectAll();
     }
 
+    // DONE
     // this will open a link next to the source doc
     @undoBatch
     openLinkInPlace = () => {
         this.highlightDoc();
 
         let alias = Doc.MakeAlias(this.props.destinationDoc);
-        let y = this.props.sourceDoc.y;
-        let x = this.props.sourceDoc.x;
-        let parentView: any = undefined;
-        let parentDoc: Doc = this.props.sourceDoc;
+        let y = NumCast(this.props.sourceDoc.y);
+        let x = NumCast(this.props.sourceDoc.x);
+
+        let width = NumCast(this.props.sourceDoc.width);
+        let height = NumCast(this.props.sourceDoc.height);
+
+        alias.x = x + width + 30;
+        alias.y = y;
+        alias.width = width;
+        alias.height = height;
 
         SelectionManager.SelectedDocuments().map(dv => {
             if (dv.props.Document === this.props.sourceDoc) {
-                parentView = dv.props.ContainingCollectionView;
+                dv.props.addDocument && dv.props.addDocument(alias, false);
             }
         });
-
-        if (parentView) {
-            // console.log(parentDoc)
-            console.log(parentView.props.addDocument);
-        }
     }
 
     //set this to be the default link behavior, can be any of the above
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9ae092bad..9652a3a78 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -739,7 +739,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     @action
     tryUpdateHeight() {
         if (this.props.Document.autoHeight && this._ref.current!.scrollHeight !== 0) {
-            console.log("DT = " + this.props.Document.title + " " + this._ref.current!.clientHeight + " " + this._ref.current!.scrollHeight + " " + this._ref.current!.textContent);
+            // console.log("DT = " + this.props.Document.title + " " + this._ref.current!.clientHeight + " " + this._ref.current!.scrollHeight + " " + this._ref.current!.textContent);
             let xf = this._ref.current!.getBoundingClientRect();
             let scrBounds = this.props.ScreenToLocalTransform().transformBounds(0, 0, xf.width, this._ref.current!.textContent === "" ? 35 : this._ref.current!.scrollHeight);
             let nh = this.props.Document.isTemplate ? 0 : NumCast(this.dataDoc.nativeHeight, 0);
-- 
cgit v1.2.3-70-g09d2


From 5c9f40006aa157c58ec40828ebd4845c16daa8af Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Wed, 21 Aug 2019 15:08:39 -0400
Subject: start of making link follow

---
 src/client/documents/DocumentTypes.ts           |   1 +
 src/client/documents/Documents.ts               |   4 +
 src/client/views/MainView.tsx                   |  11 ++
 src/client/views/linking/LinkFollowBox.scss     |   6 +
 src/client/views/linking/LinkFollowBox.tsx      | 148 ++++++++++++++++++++++++
 src/client/views/linking/LinkMenuItem.tsx       |  12 +-
 src/client/views/nodes/DocumentContentsView.tsx |   4 +-
 7 files changed, 179 insertions(+), 7 deletions(-)
 create mode 100644 src/client/views/linking/LinkFollowBox.scss

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 1578e49fe..381981e1b 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -19,4 +19,5 @@ export enum DocumentType {
     YOUTUBE = "youtube",
     DRAGBOX = "dragbox",
     PRES = "presentation",
+    LINKFOLLOW = "linkfollow",
 }
\ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 47df17329..cd612aaa9 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -45,6 +45,7 @@ import { PresBox } from "../views/nodes/PresBox";
 import { ComputedField } from "../../new_fields/ScriptField";
 import { ProxyField } from "../../new_fields/Proxy";
 import { DocumentType } from "./DocumentTypes";
+import { LinkFollowBox } from "../views/linking/LinkFollowBox";
 //import { PresBox } from "../views/nodes/PresBox";
 //import { PresField } from "../../new_fields/PresField";
 var requestImageSize = require('../util/request-image-size');
@@ -169,6 +170,9 @@ export namespace Docs {
             [DocumentType.DRAGBOX, {
                 layout: { view: DragBox },
                 options: { width: 40, height: 40 },
+            }],
+            [DocumentType.LINKFOLLOW, {
+                layout: { view: LinkFollowBox }
             }]
         ]);
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f28844009..f3c8a176c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -40,6 +40,7 @@ import { PreviewCursor } from './PreviewCursor';
 import { FilterBox } from './search/FilterBox';
 import PresModeMenu from './presentationview/PresentationModeMenu';
 import { PresBox } from './nodes/PresBox';
+import { LinkFollowBox } from './linking/LinkFollowBox';
 
 @observer
 export class MainView extends React.Component {
@@ -55,6 +56,8 @@ export class MainView extends React.Component {
 
     public overlayTimeout: NodeJS.Timeout | undefined;
 
+    @observable private _linkFollowBox = false;
+
     public initiateDictationFade = () => {
         let duration = DictationManager.Commands.dictationFadeDuration;
         this.overlayTimeout = setTimeout(() => {
@@ -498,6 +501,12 @@ export class MainView extends React.Component {
         this._colorPickerDisplay = close ? false : !this._colorPickerDisplay;
     }
 
+    @action
+    toggleLinkFollowBox = () => {
+        console.log("toggling link editor")
+        this._linkFollowBox = !this._linkFollowBox;
+    }
+
     /* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */
     @computed
     get miscButtons() {
@@ -506,6 +515,7 @@ export class MainView extends React.Component {
         return [
             this.isSearchVisible ? <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <FilterBox /> </div> : null,
             <div className="main-buttonDiv" key="logout" style={{ bottom: '0px', right: '1px', position: 'absolute' }} ref={logoutRef}>
+                <button onClick={this.toggleLinkFollowBox}>Open Link Editor</button>
                 <button onClick={() => window.location.assign(Utils.prepend(RouteStore.logout))}>Log Out</button></div>
         ];
 
@@ -564,6 +574,7 @@ export class MainView extends React.Component {
                 <PDFMenu />
                 <MainOverlayTextBox firstinstance={true} />
                 <OverlayView />
+                {/* <LinkFollowBox /> */}
             </div >
         );
     }
diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss
new file mode 100644
index 000000000..c764b002f
--- /dev/null
+++ b/src/client/views/linking/LinkFollowBox.scss
@@ -0,0 +1,6 @@
+@import "../globalCssVariables";
+
+.linkFollowBox-main {
+    position: absolute;
+    background: $main-accent;
+}
\ No newline at end of file
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 061a4fa93..7fc4449d3 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -2,9 +2,157 @@ import { observable, computed, action, trace } from "mobx";
 import React = require("react");
 import { observer } from "mobx-react";
 import { FieldViewProps, FieldView } from "../nodes/FieldView";
+import { Doc } from "../../../new_fields/Doc";
+import { undoBatch } from "../../util/UndoManager";
+import { NumCast, FieldValue, Cast } from "../../../new_fields/Types";
+import { CollectionViewType } from "../collections/CollectionBaseView";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { SelectionManager } from "../../util/SelectionManager";
+import { DocumentManager } from "../../util/DocumentManager";
 
 @observer
 export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); }
+    public static Instance: LinkFollowBox;
+    //set this to be the default link behavior, can be any of the above
+
+    unhighlight = () => {
+        Doc.UnhighlightAll();
+        document.removeEventListener("pointerdown", this.unhighlight);
+    }
+
+    @action
+    highlightDoc = (destinationDoc: Doc) => {
+        document.removeEventListener("pointerdown", this.unhighlight);
+        Doc.HighlightDoc(destinationDoc);
+        window.setTimeout(() => {
+            document.addEventListener("pointerdown", this.unhighlight);
+        }, 10000);
+    }
+
+    // NOT TESTED
+    // col = collection the doc is in
+    // target = the document to center on
+    @undoBatch
+    openLinkColRight = (destinationDoc: Doc, col: Doc) => {
+        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+            const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+            const newPanY = NumCast(destinationDoc.y) + NumCast(destinationDoc.height) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+            col.panX = newPanX;
+            col.panY = newPanY;
+        }
+        CollectionDockingView.Instance.AddRightSplit(col, undefined);
+    }
+
+    // DONE
+    // this opens the linked doc in a right split, NOT in its collection
+    @undoBatch
+    openLinkRight = (destinationDoc: Doc) => {
+        this.highlightDoc(destinationDoc);
+        let alias = Doc.MakeAlias(destinationDoc);
+        CollectionDockingView.Instance.AddRightSplit(alias, undefined);
+        SelectionManager.DeselectAll();
+    }
+
+    // DONE
+    // this is the standard "follow link" (jump to document)
+    // taken from follow link
+    @undoBatch
+    jumpToLink = async (destinationDoc: Doc, shouldZoom: boolean, linkDoc: Doc) => {
+        //there is an issue right now so this will be false automatically
+        shouldZoom = false;
+        this.highlightDoc(destinationDoc);
+        let jumpToDoc = destinationDoc;
+        let pdfDoc = FieldValue(Cast(destinationDoc, Doc));
+        if (pdfDoc) {
+            jumpToDoc = pdfDoc;
+        }
+        let proto = Doc.GetProto(linkDoc);
+        let targetContext = await Cast(proto.targetContext, Doc);
+        let sourceContext = await Cast(proto.sourceContext, Doc);
+
+        let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
+
+        if (destinationDoc === linkDoc.anchor2 && targetContext) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext);
+        }
+        else if (destinationDoc === linkDoc.anchor1 && sourceContext) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!));
+        }
+        else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, undefined, undefined, NumCast((destinationDoc === linkDoc.anchor2 ? linkDoc.anchor2Page : linkDoc.anchor1Page)));
+
+        }
+        else {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, dockingFunc);
+        }
+    }
+
+    // DONE
+    // opens link in new tab (not in a collection)
+    // this opens it full screen, do we need a separate full screen option?
+    @undoBatch
+    openLinkTab = (destinationDoc: Doc) => {
+        this.highlightDoc(destinationDoc);
+        let fullScreenAlias = Doc.MakeAlias(destinationDoc);
+        this.props.addDocTab(fullScreenAlias, undefined, "inTab");
+        SelectionManager.DeselectAll();
+    }
+
+    // NOT TESTED
+    // opens link in new tab in collection
+    // col = collection the doc is in
+    // target = the document to center on
+    @undoBatch
+    openLinkColTab = (destinationDoc: Doc, col: Doc) => {
+        this.highlightDoc(destinationDoc);
+        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
+        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+            const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+            const newPanY = NumCast(destinationDoc.y) + NumCast(destinationDoc.height) / NumCast(destinationDoc.zoomBasis, 1) / 2;
+            col.panX = newPanX;
+            col.panY = newPanY;
+        }
+        // CollectionDockingView.Instance.AddRightSplit(col, undefined);
+        this.props.addDocTab(col, undefined, "inTab");
+        SelectionManager.DeselectAll();
+    }
+
+    // DONE
+    // this will open a link next to the source doc
+    @undoBatch
+    openLinkInPlace = (destinationDoc: Doc, sourceDoc: Doc) => {
+        this.highlightDoc(destinationDoc);
+
+        let alias = Doc.MakeAlias(destinationDoc);
+        let y = NumCast(sourceDoc.y);
+        let x = NumCast(sourceDoc.x);
+
+        let width = NumCast(sourceDoc.width);
+        let height = NumCast(sourceDoc.height);
+
+        alias.x = x + width + 30;
+        alias.y = y;
+        alias.width = width;
+        alias.height = height;
+
+        SelectionManager.SelectedDocuments().map(dv => {
+            if (dv.props.Document === sourceDoc) {
+                dv.props.addDocument && dv.props.addDocument(alias, false);
+            }
+        });
+    }
+
+    private defaultLinkBehavior: any = this.openLinkInPlace;
+    private currentLinkBehavior: any = this.defaultLinkBehavior;
+
+    render() {
+        return (
+            <div className="linkFollowBox-main">
+
+            </div>
+        );
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 65516b374..41723030d 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -52,11 +52,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     // col = collection the doc is in
     // target = the document to center on
     @undoBatch
-    openLinkColRight = ({ col, target }: { col: Doc, target: Doc }) => {
+    openLinkColRight = (col: Doc) => {
         col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
         if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
-            const newPanX = NumCast(target.x) + NumCast(target.width) / NumCast(target.zoomBasis, 1) / 2;
-            const newPanY = NumCast(target.y) + NumCast(target.height) / NumCast(target.zoomBasis, 1) / 2;
+            const newPanX = NumCast(this.props.destinationDoc.x) + NumCast(this.props.destinationDoc.width) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
+            const newPanY = NumCast(this.props.destinationDoc.y) + NumCast(this.props.destinationDoc.height) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
             col.panX = newPanX;
             col.panY = newPanY;
         }
@@ -124,12 +124,12 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     // col = collection the doc is in
     // target = the document to center on
     @undoBatch
-    openLinkColTab = ({ col, target }: { col: Doc, target: Doc }) => {
+    openLinkColTab = (col: Doc) => {
         this.highlightDoc();
         col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
         if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
-            const newPanX = NumCast(target.x) + NumCast(target.width) / NumCast(target.zoomBasis, 1) / 2;
-            const newPanY = NumCast(target.y) + NumCast(target.height) / NumCast(target.zoomBasis, 1) / 2;
+            const newPanX = NumCast(this.props.destinationDoc.x) + NumCast(this.props.destinationDoc.width) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
+            const newPanY = NumCast(this.props.destinationDoc.y) + NumCast(this.props.destinationDoc.height) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
             col.panX = newPanX;
             col.panY = newPanY;
         }
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index d77662355..d0e117fe4 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -14,6 +14,7 @@ import { ImageBox } from "./ImageBox";
 import { DragBox } from "./DragBox";
 import { ButtonBox } from "./ButtonBox";
 import { PresBox } from "./PresBox";
+import { LinkFollowBox } from "../linking/LinkFollowBox";
 import { IconBox } from "./IconBox";
 import { KeyValueBox } from "./KeyValueBox";
 import { PDFBox } from "./PDFBox";
@@ -30,6 +31,7 @@ import { List } from "../../../new_fields/List";
 import { Doc } from "../../../new_fields/Doc";
 import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox";
 import { ScriptField } from "../../../new_fields/ScriptField";
+import { fromPromise } from "mobx-utils";
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 type BindingProps = Without<FieldViewProps, 'fieldKey'>;
@@ -108,7 +110,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
         return <ObserverJsxParser
             blacklistedAttrs={[]}
-            components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox }}
+            components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox }}
             bindings={this.CreateBindings()}
             jsx={this.finalLayout}
             showWarnings={true}
-- 
cgit v1.2.3-70-g09d2


From 1fb290bcc1c46214cfd553f31c1282d2694530ea Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Thu, 22 Aug 2019 19:42:54 -0400
Subject: making the box come up

---
 src/client/documents/Documents.ts           |  4 ++
 src/client/views/MainView.tsx               |  2 +
 src/client/views/linking/LinkFollowBox.scss |  2 +-
 src/client/views/linking/LinkFollowBox.tsx  | 87 ++++++++++++++++++-----------
 src/client/views/linking/LinkMenuItem.tsx   | 12 +++-
 5 files changed, 73 insertions(+), 34 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index cd612aaa9..b7c8f4c12 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -446,6 +446,10 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.DRAGBOX), undefined, { ...(options || {}) });
         }
 
+        export function LinkFollowBoxDocument(options?: DocumentOptions) {
+            return InstanceFromProto(Prototypes.get(DocumentType.LINKFOLLOW), undefined, { ...(options || {}) });
+        }
+
         export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id);
         }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f3c8a176c..79c44ae72 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -443,6 +443,7 @@ export class MainView extends React.Component {
         let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
 
         let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
+        let addLinkFollowBox = action(() => Docs.Create.LinkFollowBoxDocument({ width: 200, height: 500, title: "Link Follow Document" }));
         let addPresNode = action(() => Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List<Doc>(), { width: 200, height: 500, title: "a presentation trail" }));
         let addWebNode = action(() => Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" }));
         let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" }));
@@ -458,6 +459,7 @@ export class MainView extends React.Component {
             [React.createRef<HTMLDivElement>(), "globe-asia", "Add Website", addWebNode],
             [React.createRef<HTMLDivElement>(), "bolt", "Add Button", addButtonDocument],
             [React.createRef<HTMLDivElement>(), "file", "Add Document Dragger", addDragboxNode],
+            [React.createRef<HTMLDivElement>(), "caret-up", "Open Link Follow Box", addLinkFollowBox],
             [React.createRef<HTMLDivElement>(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode
             //[React.createRef<HTMLDivElement>(), "play", "Add Youtube Searcher", addYoutubeSearcher],
         ];
diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss
index c764b002f..522191792 100644
--- a/src/client/views/linking/LinkFollowBox.scss
+++ b/src/client/views/linking/LinkFollowBox.scss
@@ -2,5 +2,5 @@
 
 .linkFollowBox-main {
     position: absolute;
-    background: $main-accent;
+    background: red;
 }
\ No newline at end of file
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 7fc4449d3..247b67776 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -9,13 +9,22 @@ import { CollectionViewType } from "../collections/CollectionBaseView";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { SelectionManager } from "../../util/SelectionManager";
 import { DocumentManager } from "../../util/DocumentManager";
+import { DocumentView } from "../nodes/DocumentView";
+import "./LinkFollowBox.scss";
+
+export type LinkParamOptions = {
+    container: Doc;
+    context: Doc;
+    sourceDoc: Doc;
+    shoudldZoom: boolean;
+    linkDoc: Doc;
+};
 
 @observer
 export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); }
     public static Instance: LinkFollowBox;
-    //set this to be the default link behavior, can be any of the above
 
     unhighlight = () => {
         Doc.UnhighlightAll();
@@ -31,19 +40,32 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         }, 10000);
     }
 
+    // DONE
+    @undoBatch
+    openFullScreen = (destinationDoc: Doc) => {
+        let view: DocumentView | null = DocumentManager.Instance.getDocumentView(destinationDoc)
+        view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
+    }
+
+    // should container be a doc or documentview or what? This one needs work and is more long term
+    @undoBatch
+    openInContainer = (destinationDoc: Doc, options: { container: Doc }) => {
+
+    }
+
     // NOT TESTED
     // col = collection the doc is in
     // target = the document to center on
     @undoBatch
-    openLinkColRight = (destinationDoc: Doc, col: Doc) => {
-        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
-        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+    openLinkColRight = (destinationDoc: Doc, options: { context: Doc }) => {
+        options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
+        if (NumCast(options.context.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
             const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2;
             const newPanY = NumCast(destinationDoc.y) + NumCast(destinationDoc.height) / NumCast(destinationDoc.zoomBasis, 1) / 2;
-            col.panX = newPanX;
-            col.panY = newPanY;
+            options.context.panX = newPanX;
+            options.context.panY = newPanY;
         }
-        CollectionDockingView.Instance.AddRightSplit(col, undefined);
+        CollectionDockingView.Instance.AddRightSplit(options.context, undefined);
     }
 
     // DONE
@@ -60,39 +82,39 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     // this is the standard "follow link" (jump to document)
     // taken from follow link
     @undoBatch
-    jumpToLink = async (destinationDoc: Doc, shouldZoom: boolean, linkDoc: Doc) => {
+    jumpToLink = async (destinationDoc: Doc, options: { shouldZoom: boolean, linkDoc: Doc }) => {
         //there is an issue right now so this will be false automatically
-        shouldZoom = false;
+        options.shouldZoom = false;
         this.highlightDoc(destinationDoc);
         let jumpToDoc = destinationDoc;
         let pdfDoc = FieldValue(Cast(destinationDoc, Doc));
         if (pdfDoc) {
             jumpToDoc = pdfDoc;
         }
-        let proto = Doc.GetProto(linkDoc);
+        let proto = Doc.GetProto(options.linkDoc);
         let targetContext = await Cast(proto.targetContext, Doc);
         let sourceContext = await Cast(proto.sourceContext, Doc);
 
         let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
 
-        if (destinationDoc === linkDoc.anchor2 && targetContext) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext);
+        if (destinationDoc === options.linkDoc.anchor2 && targetContext) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, options.shouldZoom, false, async document => dockingFunc(document), undefined, targetContext);
         }
-        else if (destinationDoc === linkDoc.anchor1 && sourceContext) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!));
+        else if (destinationDoc === options.linkDoc.anchor1 && sourceContext) {
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, options.shouldZoom, false, document => dockingFunc(sourceContext!));
         }
         else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, undefined, undefined, NumCast((destinationDoc === linkDoc.anchor2 ? linkDoc.anchor2Page : linkDoc.anchor1Page)));
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, options.shouldZoom, undefined, undefined, NumCast((destinationDoc === options.linkDoc.anchor2 ? options.linkDoc.anchor2Page : options.linkDoc.anchor1Page)));
 
         }
         else {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, dockingFunc);
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, options.shouldZoom, false, dockingFunc);
         }
     }
 
     // DONE
     // opens link in new tab (not in a collection)
-    // this opens it full screen, do we need a separate full screen option?
+    // this opens it full screen in new tab
     @undoBatch
     openLinkTab = (destinationDoc: Doc) => {
         this.highlightDoc(destinationDoc);
@@ -106,32 +128,32 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     // col = collection the doc is in
     // target = the document to center on
     @undoBatch
-    openLinkColTab = (destinationDoc: Doc, col: Doc) => {
+    openLinkColTab = (destinationDoc: Doc, options: { context: Doc }) => {
         this.highlightDoc(destinationDoc);
-        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
-        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
+        options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
+        if (NumCast(options.context.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
             const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2;
             const newPanY = NumCast(destinationDoc.y) + NumCast(destinationDoc.height) / NumCast(destinationDoc.zoomBasis, 1) / 2;
-            col.panX = newPanX;
-            col.panY = newPanY;
+            options.context.panX = newPanX;
+            options.context.panY = newPanY;
         }
         // CollectionDockingView.Instance.AddRightSplit(col, undefined);
-        this.props.addDocTab(col, undefined, "inTab");
+        this.props.addDocTab(options.context, undefined, "inTab");
         SelectionManager.DeselectAll();
     }
 
     // DONE
     // this will open a link next to the source doc
     @undoBatch
-    openLinkInPlace = (destinationDoc: Doc, sourceDoc: Doc) => {
+    openLinkInPlace = (destinationDoc: Doc, options: { sourceDoc: Doc }) => {
         this.highlightDoc(destinationDoc);
 
         let alias = Doc.MakeAlias(destinationDoc);
-        let y = NumCast(sourceDoc.y);
-        let x = NumCast(sourceDoc.x);
+        let y = NumCast(options.sourceDoc.y);
+        let x = NumCast(options.sourceDoc.x);
 
-        let width = NumCast(sourceDoc.width);
-        let height = NumCast(sourceDoc.height);
+        let width = NumCast(options.sourceDoc.width);
+        let height = NumCast(options.sourceDoc.height);
 
         alias.x = x + width + 30;
         alias.y = y;
@@ -139,18 +161,19 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         alias.height = height;
 
         SelectionManager.SelectedDocuments().map(dv => {
-            if (dv.props.Document === sourceDoc) {
+            if (dv.props.Document === options.sourceDoc) {
                 dv.props.addDocument && dv.props.addDocument(alias, false);
             }
         });
     }
 
-    private defaultLinkBehavior: any = this.openLinkInPlace;
-    private currentLinkBehavior: any = this.defaultLinkBehavior;
+    //set this to be the default link behavior, can be any of the above
+    private defaultLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.openLinkInPlace;
+    private currentLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.defaultLinkBehavior;
 
     render() {
         return (
-            <div className="linkFollowBox-main">
+            <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document.height), width: NumCast(this.props.Document.width) }}>
 
             </div>
         );
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 41723030d..60f27c664 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -15,6 +15,7 @@ import { CollectionDockingView } from '../collections/CollectionDockingView';
 import { SelectionManager } from '../../util/SelectionManager';
 import { CollectionViewType } from '../collections/CollectionBaseView';
 import { DocumentView } from '../nodes/DocumentView';
+import { SearchUtil } from '../../util/SearchUtil';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp);
 
 
@@ -63,6 +64,13 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         CollectionDockingView.Instance.AddRightSplit(col, undefined);
     }
 
+    // DONE
+    @undoBatch
+    openFullScreen = () => {
+        let view: DocumentView | null = DocumentManager.Instance.getDocumentView(this.props.destinationDoc);
+        view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
+    }
+
     // DONE
     // this opens the linked doc in a right split, NOT in its collection
     @undoBatch
@@ -161,10 +169,12 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 dv.props.addDocument && dv.props.addDocument(alias, false);
             }
         });
+
+        this.jumpToLink(false);
     }
 
     //set this to be the default link behavior, can be any of the above
-    private defaultLinkBehavior: any = this.openLinkInPlace;
+    private defaultLinkBehavior: any = this.openLinkTab;
 
     onEdit = (e: React.PointerEvent): void => {
         e.stopPropagation();
-- 
cgit v1.2.3-70-g09d2


From ed7f9a9cd3255f7b774268cfda35685ddacfe2e9 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Fri, 23 Aug 2019 16:38:27 -0400
Subject: basic menu and setting docs working

---
 src/client/documents/Documents.ts           |   1 +
 src/client/views/MainView.tsx               |   6 +-
 src/client/views/linking/LinkFollowBox.scss |  77 +++++++++-
 src/client/views/linking/LinkFollowBox.tsx  | 213 +++++++++++++++++++++++-----
 src/client/views/linking/LinkMenuItem.tsx   |   5 +-
 5 files changed, 260 insertions(+), 42 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b7c8f4c12..e903d1e06 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -54,6 +54,7 @@ var path = require('path');
 export interface DocumentOptions {
     x?: number;
     y?: number;
+    z?: number;
     type?: string;
     width?: number;
     height?: number;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 79c44ae72..82e3c706a 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,5 +1,5 @@
 import { IconName, library } from '@fortawesome/fontawesome-svg-core';
-import { faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faClone, faCloudUploadAlt, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faUndoAlt, faTv } from '@fortawesome/free-solid-svg-icons';
+import { faLink, faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faClone, faCloudUploadAlt, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faUndoAlt, faTv } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, configure, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
@@ -443,7 +443,7 @@ export class MainView extends React.Component {
         let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
 
         let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
-        let addLinkFollowBox = action(() => Docs.Create.LinkFollowBoxDocument({ width: 200, height: 500, title: "Link Follow Document" }));
+        let addLinkFollowBox = action(() => Docs.Create.LinkFollowBoxDocument({ width: 500, height: 350, title: "Link Follower" }));
         let addPresNode = action(() => Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List<Doc>(), { width: 200, height: 500, title: "a presentation trail" }));
         let addWebNode = action(() => Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" }));
         let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" }));
@@ -459,7 +459,7 @@ export class MainView extends React.Component {
             [React.createRef<HTMLDivElement>(), "globe-asia", "Add Website", addWebNode],
             [React.createRef<HTMLDivElement>(), "bolt", "Add Button", addButtonDocument],
             [React.createRef<HTMLDivElement>(), "file", "Add Document Dragger", addDragboxNode],
-            [React.createRef<HTMLDivElement>(), "caret-up", "Open Link Follow Box", addLinkFollowBox],
+            [React.createRef<HTMLDivElement>(), "link", "Open Link Follow Box", addLinkFollowBox],
             [React.createRef<HTMLDivElement>(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode
             //[React.createRef<HTMLDivElement>(), "play", "Add Youtube Searcher", addYoutubeSearcher],
         ];
diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss
index 522191792..aedbfdea4 100644
--- a/src/client/views/linking/LinkFollowBox.scss
+++ b/src/client/views/linking/LinkFollowBox.scss
@@ -2,5 +2,80 @@
 
 .linkFollowBox-main {
     position: absolute;
-    background: red;
+    background: whitesmoke;
+    color: grey;
+    border-radius: 15px;
+    box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
+    border: solid #BBBBBBBB 5px;
+    pointer-events: all;
+    // overflow: hidden;
+
+    .linkFollowBox-header {
+        height: 30px;
+        text-align: center;
+        text-transform: uppercase;
+        line-height: 30px;
+        letter-spacing: 2px;
+        font-size: 16px;
+    }
+
+    .linkFollowBox-footer {
+        height: 50px;
+        text-align: center;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        button {
+            background-color: $darker-alt-accent;
+            // height: 30px;
+            width: 30%;
+            // font-size: 18px;
+        }
+    }
+
+    .linkFollowBox-content {
+        display: grid;
+        grid-template-columns: 1fr 1fr 1fr;
+        grid-column-gap: 5px;
+        margin-left: 5px;
+        margin-right: 5px;
+
+        .linkFollowBox-item {
+            background-color: $light-color;
+            width: 100%;
+            height: 100%;
+
+            .linkFollowBox-itemContent {
+                padding: 5px;
+                font-size: 12px;
+                // line-height: 40px;
+                overflow: scroll;
+
+
+                input[type=radio] {
+                    border: 0px;
+                    // width: 100%;
+                    // height: 20px;
+                    // width: 20px;
+                    margin-right: 5px;
+                }
+            }
+
+            .title {
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                text-transform: uppercase;
+                color: $light-color;
+                background-color: $lighter-alt-accent;
+                width: 100%;
+                height: 30px;
+                border-bottom: solid $darker-alt-accent 5px;
+                font-size: 12px;
+                text-align: center;
+            }
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 247b67776..8cd26bdec 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -1,10 +1,10 @@
-import { observable, computed, action, trace } from "mobx";
+import { observable, computed, action, trace, ObservableMap } from "mobx";
 import React = require("react");
 import { observer } from "mobx-react";
 import { FieldViewProps, FieldView } from "../nodes/FieldView";
 import { Doc } from "../../../new_fields/Doc";
 import { undoBatch } from "../../util/UndoManager";
-import { NumCast, FieldValue, Cast } from "../../../new_fields/Types";
+import { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types";
 import { CollectionViewType } from "../collections/CollectionBaseView";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { SelectionManager } from "../../util/SelectionManager";
@@ -12,19 +12,41 @@ import { DocumentManager } from "../../util/DocumentManager";
 import { DocumentView } from "../nodes/DocumentView";
 import "./LinkFollowBox.scss";
 
-export type LinkParamOptions = {
-    container: Doc;
-    context: Doc;
-    sourceDoc: Doc;
-    shoudldZoom: boolean;
-    linkDoc: Doc;
-};
+enum FollowModes {
+    OPENTAB = "Open in Tab",
+    OPENRIGHT = "Open in Right Split",
+    OPENFULL = "Open Full Screen",
+    PAN = "Pan to Document",
+    INPLACE = "Open In Place"
+}
+
+enum FollowOptions {
+    ZOOM = "zoom",
+    NOZOOM = "no zoom",
+}
 
 @observer
 export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); }
     public static Instance: LinkFollowBox;
+    @observable static linkDoc: Doc | undefined = undefined;
+    @observable static destinationDoc: Doc | undefined = undefined;
+    @observable static sourceDoc: Doc | undefined = undefined;
+    @observable selectedMode: string = "";
+    @observable selectedOption: string = "";
+
+    constructor(props: FieldViewProps) {
+        super(props);
+        LinkFollowBox.Instance = this;
+    }
+
+    @action
+    setLinkDocs = (linkDoc: Doc, source: Doc, dest: Doc) => {
+        LinkFollowBox.linkDoc = linkDoc;
+        LinkFollowBox.sourceDoc = source;
+        LinkFollowBox.destinationDoc = dest;
+    }
 
     unhighlight = () => {
         Doc.UnhighlightAll();
@@ -40,11 +62,11 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         }, 10000);
     }
 
-    // DONE
     @undoBatch
     openFullScreen = (destinationDoc: Doc) => {
-        let view: DocumentView | null = DocumentManager.Instance.getDocumentView(destinationDoc)
+        let view: DocumentView | null = DocumentManager.Instance.getDocumentView(destinationDoc);
         view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
+        SelectionManager.DeselectAll();
     }
 
     // should container be a doc or documentview or what? This one needs work and is more long term
@@ -54,8 +76,6 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     }
 
     // NOT TESTED
-    // col = collection the doc is in
-    // target = the document to center on
     @undoBatch
     openLinkColRight = (destinationDoc: Doc, options: { context: Doc }) => {
         options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
@@ -66,26 +86,22 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             options.context.panY = newPanY;
         }
         CollectionDockingView.Instance.AddRightSplit(options.context, undefined);
+
+        this.highlightDoc(destinationDoc);
+        SelectionManager.DeselectAll();
     }
 
-    // DONE
-    // this opens the linked doc in a right split, NOT in its collection
     @undoBatch
     openLinkRight = (destinationDoc: Doc) => {
-        this.highlightDoc(destinationDoc);
         let alias = Doc.MakeAlias(destinationDoc);
         CollectionDockingView.Instance.AddRightSplit(alias, undefined);
+        this.highlightDoc(destinationDoc);
         SelectionManager.DeselectAll();
+
     }
 
-    // DONE
-    // this is the standard "follow link" (jump to document)
-    // taken from follow link
     @undoBatch
     jumpToLink = async (destinationDoc: Doc, options: { shouldZoom: boolean, linkDoc: Doc }) => {
-        //there is an issue right now so this will be false automatically
-        options.shouldZoom = false;
-        this.highlightDoc(destinationDoc);
         let jumpToDoc = destinationDoc;
         let pdfDoc = FieldValue(Cast(destinationDoc, Doc));
         if (pdfDoc) {
@@ -110,26 +126,23 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         else {
             DocumentManager.Instance.jumpToDocument(jumpToDoc, options.shouldZoom, false, dockingFunc);
         }
+
+        this.highlightDoc(destinationDoc);
+        SelectionManager.DeselectAll();
     }
 
-    // DONE
-    // opens link in new tab (not in a collection)
-    // this opens it full screen in new tab
     @undoBatch
     openLinkTab = (destinationDoc: Doc) => {
-        this.highlightDoc(destinationDoc);
         let fullScreenAlias = Doc.MakeAlias(destinationDoc);
         this.props.addDocTab(fullScreenAlias, undefined, "inTab");
+
+        this.highlightDoc(destinationDoc);
         SelectionManager.DeselectAll();
     }
 
     // NOT TESTED
-    // opens link in new tab in collection
-    // col = collection the doc is in
-    // target = the document to center on
     @undoBatch
     openLinkColTab = (destinationDoc: Doc, options: { context: Doc }) => {
-        this.highlightDoc(destinationDoc);
         options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
         if (NumCast(options.context.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
             const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2;
@@ -137,16 +150,14 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             options.context.panX = newPanX;
             options.context.panY = newPanY;
         }
-        // CollectionDockingView.Instance.AddRightSplit(col, undefined);
         this.props.addDocTab(options.context, undefined, "inTab");
+
+        this.highlightDoc(destinationDoc);
         SelectionManager.DeselectAll();
     }
 
-    // DONE
-    // this will open a link next to the source doc
     @undoBatch
-    openLinkInPlace = (destinationDoc: Doc, options: { sourceDoc: Doc }) => {
-        this.highlightDoc(destinationDoc);
+    openLinkInPlace = (destinationDoc: Doc, options: { sourceDoc: Doc, linkDoc: Doc }) => {
 
         let alias = Doc.MakeAlias(destinationDoc);
         let y = NumCast(options.sourceDoc.y);
@@ -165,16 +176,146 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
                 dv.props.addDocument && dv.props.addDocument(alias, false);
             }
         });
+
+        this.jumpToLink(destinationDoc, { shouldZoom: false, linkDoc: options.linkDoc });
+
+        this.highlightDoc(destinationDoc);
+        SelectionManager.DeselectAll();
     }
 
     //set this to be the default link behavior, can be any of the above
     private defaultLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.openLinkInPlace;
-    private currentLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.defaultLinkBehavior;
+    // private currentLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.defaultLinkBehavior;
+
+    @computed
+    get LinkFollowTitle(): string {
+        if (LinkFollowBox.linkDoc) {
+            return StrCast(LinkFollowBox.linkDoc.title);
+        }
+        return "No Link Selected";
+    }
+
+    @action
+    currentLinkBehavior = () => {
+        if (this.selectedMode === FollowModes.INPLACE) {
+
+        }
+        else if (this.selectedMode === FollowModes.OPENFULL) {
+
+        }
+        else if (this.selectedMode === FollowModes.OPENRIGHT) {
+
+        }
+        else if (this.selectedMode === FollowModes.OPENTAB) {
+
+        }
+        else if (this.selectedMode === FollowModes.INPLACE) {
+
+        }
+        else if (this.selectedMode === FollowModes.PAN) {
+
+        }
+        else return;
+    }
+
+    @action
+    handleModeChange = (e: React.ChangeEvent) => {
+        let target = e.target as HTMLInputElement;
+        this.selectedMode = target.value;
+    }
+
+    @action
+    handleOptionChange = (e: React.ChangeEvent) => {
+        let target = e.target as HTMLInputElement;
+        this.selectedOption = target.value;
+    }
+
+    @computed
+    get availableModes() {
+        return (
+            <div>
+                <label><input
+                    type="radio"
+                    name="mode"
+                    value={FollowModes.OPENRIGHT}
+                    checked={this.selectedMode === FollowModes.OPENRIGHT}
+                    onChange={this.handleModeChange} />
+                    {FollowModes.OPENRIGHT}
+                </label><br />
+                <label><input
+                    type="radio"
+                    name="mode"
+                    value={FollowModes.OPENTAB}
+                    checked={this.selectedMode === FollowModes.OPENTAB}
+                    onChange={this.handleModeChange} />
+                    {FollowModes.OPENTAB}
+                </label><br />
+                <label><input
+                    type="radio"
+                    name="mode"
+                    value={FollowModes.OPENFULL}
+                    checked={this.selectedMode === FollowModes.OPENFULL}
+                    onChange={this.handleModeChange} />
+                    {FollowModes.OPENFULL}
+                </label><br />
+                <label><input
+                    type="radio"
+                    name="mode"
+                    value={FollowModes.PAN}
+                    checked={this.selectedMode === FollowModes.PAN}
+                    onChange={this.handleModeChange} />
+                    {FollowModes.PAN}
+                </label><br />
+                <label><input
+                    type="radio"
+                    name="mode"
+                    value={FollowModes.INPLACE}
+                    checked={this.selectedMode === FollowModes.INPLACE}
+                    onChange={this.handleModeChange} />
+                    {FollowModes.INPLACE}
+                </label><br />
+            </div>
+        );
+    }
+
+    @computed
+    get contexts() {
+        return (
+            <div>
+
+            </div>
+        );
+    }
 
     render() {
         return (
             <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document.height), width: NumCast(this.props.Document.width) }}>
+                <div className="linkFollowBox-header">{this.LinkFollowTitle}</div>
+                <div className="linkFollowBox-content" style={{ height: NumCast(this.props.Document.height) - 90 }}>
+                    <div className="linkFollowBox-item">
+                        <div className="linkFollowBox-item title">Mode</div>
+                        <div className="linkFollowBox-itemContent">{this.availableModes}</div>
+                    </div>
+                    <div className="linkFollowBox-item">
+                        <div className="linkFollowBox-item title">Context</div>
+                        <div className="linkFollowBox-itemContent">
+
+                        </div>
+                    </div>
+                    <div className="linkFollowBox-item">
+                        <div className="linkFollowBox-item title">Options</div>
+                        <div className="linkFollowBox-itemContent">
 
+                        </div>
+                    </div>
+                </div>
+                <div className="linkFollowBox-footer">
+                    <button
+                        onClick={this.currentLinkBehavior}
+                        disabled={(LinkFollowBox.linkDoc) ? false : true}>
+                        Follow Link
+                    </button>
+                </div>
             </div>
         );
     }
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 60f27c664..406429ebf 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -16,6 +16,7 @@ import { SelectionManager } from '../../util/SelectionManager';
 import { CollectionViewType } from '../collections/CollectionBaseView';
 import { DocumentView } from '../nodes/DocumentView';
 import { SearchUtil } from '../../util/SearchUtil';
+import { LinkFollowBox } from './LinkFollowBox';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp);
 
 
@@ -174,7 +175,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     }
 
     //set this to be the default link behavior, can be any of the above
-    private defaultLinkBehavior: any = this.openLinkTab;
+    // private defaultLinkBehavior: any = LinkFollowBox.computeLinkDocs(this.props.linkDoc);
 
     onEdit = (e: React.PointerEvent): void => {
         e.stopPropagation();
@@ -242,7 +243,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {/* Original */}
                             {/* <div title="Follow link" className="button" onPointerDown={this.onFollowLink}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */}
                             {/* New */}
-                            <div title="Follow link" className="button" onPointerDown={this.defaultLinkBehavior}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
+                            <div title="Follow link" className="button" onClick={() => LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc)}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
                         </div>
                     </div>
                     {this._showMore ? this.renderMetadata() : <></>}
-- 
cgit v1.2.3-70-g09d2


From accfe9900c0b830ef08db3c70fe4940dd3c8c81e Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Mon, 26 Aug 2019 10:43:19 -0400
Subject: open in place working

---
 src/client/views/linking/LinkFollowBox.tsx | 27 ++++++++++++++++++---------
 src/client/views/linking/LinkMenuItem.tsx  |  4 +++-
 2 files changed, 21 insertions(+), 10 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 5cf14cf58..35b4deeac 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -1,4 +1,4 @@
-import { observable, computed, action, trace, ObservableMap, runInAction, reaction } from "mobx";
+import { observable, computed, action, trace, ObservableMap, runInAction, reaction, IReactionDisposer } from "mobx";
 import React = require("react");
 import { observer } from "mobx-react";
 import { FieldViewProps, FieldView } from "../nodes/FieldView";
@@ -43,6 +43,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     @observable sourceView: DocumentView | undefined = undefined;
     @observable canPan: boolean = false;
     @observable shouldUseOnlyParentContext = false;
+    _panDisposer?: IReactionDisposer;
 
     @observable private _docs: { col: Doc, target: Doc }[] = [];
     @observable private _otherDocs: { col: Doc, target: Doc }[] = [];
@@ -55,7 +56,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     componentDidMount = () => {
         this.resetVars();
 
-        reaction(
+        this._panDisposer = reaction(
             () => LinkFollowBox.destinationDoc,
             async newLinkDestination => {
                 if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionView) {
@@ -75,6 +76,10 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         );
     }
 
+    componentWillUnmount = () => {
+        this._panDisposer && this._panDisposer();
+    }
+
     @action
     resetVars = () => {
         this.selectedContext = undefined;
@@ -249,6 +254,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
 
         if (LinkFollowBox.destinationDoc && LinkFollowBox.sourceDoc) {
             let alias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
+            console.log(alias)
             let y = NumCast(LinkFollowBox.sourceDoc.y);
             let x = NumCast(LinkFollowBox.sourceDoc.x);
 
@@ -260,13 +266,11 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             alias.width = width;
             alias.height = height;
 
-            SelectionManager.SelectedDocuments().map(dv => {
-                if (dv.props.Document === LinkFollowBox.sourceDoc) {
-                    dv.props.addDocument && dv.props.addDocument(alias, false);
-                }
-            });
+            if (this.sourceView && this.sourceView.props.addDocument) {
+                this.sourceView.props.addDocument(alias, false);
+            }
 
-            this.jumpToLink({ shouldZoom: false });
+            this.jumpToLink({ shouldZoom: options.shouldZoom });
 
             this.highlightDoc();
             SelectionManager.DeselectAll();
@@ -279,8 +283,13 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     @action
     currentLinkBehavior = () => {
-        if (this.selectedMode === FollowModes.INPLACE) {
+        let shouldZoom: boolean | undefined = this.selectedOption === "" ? undefined :
+            this.selectedOption === FollowOptions.NOZOOM ? false : true;
 
+        if (this.selectedMode === FollowModes.INPLACE) {
+            console.log("hello")
+            console.log(shouldZoom)
+            if (shouldZoom !== undefined) this.openLinkInPlace({ shouldZoom: shouldZoom });
         }
         else if (this.selectedMode === FollowModes.OPENFULL) {
 
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 406429ebf..d2dc3f7ff 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -175,7 +175,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     }
 
     //set this to be the default link behavior, can be any of the above
-    // private defaultLinkBehavior: any = LinkFollowBox.computeLinkDocs(this.props.linkDoc);
+    private defaultLinkBehavior: any = this.openLinkInPlace;
 
     onEdit = (e: React.PointerEvent): void => {
         e.stopPropagation();
@@ -244,6 +244,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {/* <div title="Follow link" className="button" onPointerDown={this.onFollowLink}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */}
                             {/* New */}
                             <div title="Follow link" className="button" onClick={() => LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc)}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
+                            {/* <div title="Follow link" className="button" onClick={this.defaultLinkBehavior}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */}
+
                         </div>
                     </div>
                     {this._showMore ? this.renderMetadata() : <></>}
-- 
cgit v1.2.3-70-g09d2


From 9c116867bb73b7d84654d9e56688ebd8a982462e Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 27 Aug 2019 17:45:20 -0400
Subject: about to make big changes

---
 src/client/views/MainView.tsx               |  19 ++-
 src/client/views/linking/LinkFollowBox.scss |  23 +++
 src/client/views/linking/LinkFollowBox.tsx  |  28 +++-
 src/client/views/linking/LinkMenuItem.tsx   | 214 ++++------------------------
 4 files changed, 77 insertions(+), 207 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b49274e7e..d580925d6 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -57,8 +57,6 @@ export class MainView extends React.Component {
 
     public overlayTimeout: NodeJS.Timeout | undefined;
 
-    @observable private _linkFollowBox = false;
-
     public initiateDictationFade = () => {
         let duration = DictationManager.Commands.dictationFadeDuration;
         this.overlayTimeout = setTimeout(() => {
@@ -437,17 +435,16 @@ export class MainView extends React.Component {
         }
     }
 
-    toggleLinkFollowBox = () => {
+    toggleLinkFollowBox = (shouldClose: boolean) => {
         if (LinkFollowBox.Instance) {
-            console.log("is instance!")
-            // if (LinkFollowBox.Instance.props && LinkFollowBox.Instance.props.removeDocument) LinkFollowBox.Instance.props.removeDocument(LinkFollowBox.Instance.props.Document);
+            let dvs = DocumentManager.Instance.getDocumentViews(LinkFollowBox.Instance.props.Document);
+            // if it already exisits, close it
+            if (dvs.length > 0 && shouldClose) LinkFollowBox.Instance.close();
+            // open it if not
+            else Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", LinkFollowBox.Instance.props.Document);
         }
         else {
-            let overlayView = document.getElementById("overlayView");
-            let overlayWidth = 0;
-            if (overlayView) overlayWidth = overlayView.offsetWidth;
-            let x: number = overlayWidth - 500;
-            let doc = Docs.Create.LinkFollowBoxDocument({ x: x, y: 20, width: 500, height: 370, title: "Link Follower" });
+            let doc = Docs.Create.LinkFollowBoxDocument({ x: this.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
             Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
         }
     }
@@ -495,7 +492,7 @@ export class MainView extends React.Component {
                                 <FontAwesomeIcon icon={btn[1]} size="sm" />
                             </button>
                         </div></li>)}
-                    <li key="linkFollow"><button className="add-button round-button" title="Open Link Follower" onClick={this.toggleLinkFollowBox}><FontAwesomeIcon icon="link" size="sm" /></button></li>
+                    <li key="linkFollow"><button className="add-button round-button" title="Open Link Follower" onClick={() => this.toggleLinkFollowBox(true)}><FontAwesomeIcon icon="link" size="sm" /></button></li>
                     <li key="color"><button className="add-button round-button" title="Select Color" style={{ zIndex: 1000 }} onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
                         <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
                             <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss
index a34285727..e425bde69 100644
--- a/src/client/views/linking/LinkFollowBox.scss
+++ b/src/client/views/linking/LinkFollowBox.scss
@@ -18,12 +18,35 @@
         // line-height: 30px;
         letter-spacing: 2px;
         font-size: 16px;
+        width: 100%;
     }
 
     .direction-indicator {
         font-size: 12px;
     }
 
+    .closeDocument {
+        position: relative;
+        // z-index: inherit;
+        max-width: 30px;
+        top: -20px;
+        // left: 230px;
+        left: 460px;
+        color: $darker-alt-accent // right: 5px;
+    }
+
+    .closeDocument:hover {
+        color: $main-accent;
+    }
+
+    .topHeader {
+        // display: grid;
+        // grid-template-columns: 90% 10%;
+        width: 100%;
+        // flex-direction: row;
+        height: 25px;
+    }
+
     .linkFollowBox-footer {
         height: 50px;
         text-align: center;
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index cf44ae649..588f48017 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -2,7 +2,7 @@ import { observable, computed, action, trace, ObservableMap, runInAction, reacti
 import React = require("react");
 import { observer } from "mobx-react";
 import { FieldViewProps, FieldView } from "../nodes/FieldView";
-import { Doc } from "../../../new_fields/Doc";
+import { Doc, DocListCastAsync } from "../../../new_fields/Doc";
 import { undoBatch } from "../../util/UndoManager";
 import { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types";
 import { CollectionViewType } from "../collections/CollectionBaseView";
@@ -17,6 +17,9 @@ import { listSpec } from "../../../new_fields/Schema";
 import { DocServer } from "../../DocServer";
 import { RefField } from "../../../new_fields/RefField";
 import { Docs } from "../../documents/Documents";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faTimes } from '@fortawesome/free-solid-svg-icons';
+import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 
 enum FollowModes {
     OPENTAB = "Open in Tab",
@@ -48,7 +51,6 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     @observable canPan: boolean = false;
     @observable shouldUseOnlyParentContext = false;
     _contextDisposer?: IReactionDisposer;
-    collectionTypes: string[];
 
     @observable private _docs: { col: Doc, target: Doc }[] = [];
     @observable private _otherDocs: { col: Doc, target: Doc }[] = [];
@@ -56,8 +58,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     constructor(props: FieldViewProps) {
         super(props);
         LinkFollowBox.Instance = this;
-
-        this.collectionTypes = ["Invalid", "Freeform", "Schema", "Docking", "Tree", "Stacking", "Masonry"];
+        this.props.Document.isBackground = true;
     }
 
     @computed
@@ -322,7 +323,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     }
 
     //set this to be the default link behavior, can be any of the above
-    private defaultLinkBehavior: (options?: any) => void = this.openLinkInPlace;
+    public defaultLinkBehavior: (options?: any) => void = this.openLinkRight;
 
     @action
     currentLinkBehavior = () => {
@@ -556,12 +557,20 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         return null;
     }
 
+    async close() {
+        let res = await DocListCastAsync((CurrentUserUtils.UserDocument.overlays as Doc).data);
+        if (res) res.splice(res.indexOf(LinkFollowBox.Instance.props.Document), 1);
+    }
+
     render() {
         return (
             <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document.height), width: NumCast(this.props.Document.width) }}>
                 <div className="linkFollowBox-header">
-                    {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"}
-                    <div className="linkFollowBox-header direction-indicator">{LinkFollowBox.linkDoc ?
+                    <div className="topHeader">
+                        {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"}
+                        <div onClick={this.close} className="closeDocument"><FontAwesomeIcon icon={faTimes} size="lg" /></div>
+                    </div>
+                    <div className=" direction-indicator">{LinkFollowBox.linkDoc ?
                         LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc ? "Source: " + StrCast(LinkFollowBox.sourceDoc.title) + ", Destination: " + StrCast(LinkFollowBox.destinationDoc.title)
                             : "" : ""}</div>
                 </div>
@@ -586,6 +595,11 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
                     </div>
                 </div>
                 <div className="linkFollowBox-footer">
+                    <button
+                        onClick={this.resetVars}>
+                        Clear Link
+                    </button>
+                    <div style={{ width: 20 }}></div>
                     <button
                         onClick={this.currentLinkBehavior}
                         disabled={(LinkFollowBox.linkDoc) ? false : true}>
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index d2dc3f7ff..0dda948c4 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -17,6 +17,9 @@ import { CollectionViewType } from '../collections/CollectionBaseView';
 import { DocumentView } from '../nodes/DocumentView';
 import { SearchUtil } from '../../util/SearchUtil';
 import { LinkFollowBox } from './LinkFollowBox';
+import { ContextMenu } from '../ContextMenu';
+import { MainView } from '../MainView';
+import { Docs } from '../../documents/Documents';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp);
 
 
@@ -35,148 +38,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     @observable private _showMore: boolean = false;
     @action toggleShowMore() { this._showMore = !this._showMore; }
 
-
-    unhighlight = () => {
-        Doc.UnhighlightAll();
-        document.removeEventListener("pointerdown", this.unhighlight);
-    }
-
-    @action
-    highlightDoc = () => {
-        document.removeEventListener("pointerdown", this.unhighlight);
-        Doc.HighlightDoc(this.props.destinationDoc);
-        window.setTimeout(() => {
-            document.addEventListener("pointerdown", this.unhighlight);
-        }, 10000);
-    }
-
-    // NOT TESTED
-    // col = collection the doc is in
-    // target = the document to center on
-    @undoBatch
-    openLinkColRight = (col: Doc) => {
-        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
-        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
-            const newPanX = NumCast(this.props.destinationDoc.x) + NumCast(this.props.destinationDoc.width) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
-            const newPanY = NumCast(this.props.destinationDoc.y) + NumCast(this.props.destinationDoc.height) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
-            col.panX = newPanX;
-            col.panY = newPanY;
-        }
-        CollectionDockingView.Instance.AddRightSplit(col, undefined);
-    }
-
-    // DONE
-    @undoBatch
-    openFullScreen = () => {
-        let view: DocumentView | null = DocumentManager.Instance.getDocumentView(this.props.destinationDoc);
-        view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
-    }
-
-    // DONE
-    // this opens the linked doc in a right split, NOT in its collection
-    @undoBatch
-    openLinkRight = () => {
-        this.highlightDoc();
-        let alias = Doc.MakeAlias(this.props.destinationDoc);
-        CollectionDockingView.Instance.AddRightSplit(alias, undefined);
-        SelectionManager.DeselectAll();
-    }
-
-    // DONE
-    // this is the standard "follow link" (jump to document)
-    // taken from follow link
-    @undoBatch
-    jumpToLink = async (shouldZoom: boolean) => {
-        //there is an issue right now so this will be false automatically
-        shouldZoom = false;
-        this.highlightDoc();
-        let jumpToDoc = this.props.destinationDoc;
-        let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc));
-        if (pdfDoc) {
-            jumpToDoc = pdfDoc;
-        }
-        let proto = Doc.GetProto(this.props.linkDoc);
-        let targetContext = await Cast(proto.targetContext, Doc);
-        let sourceContext = await Cast(proto.sourceContext, Doc);
-        let self = this;
-
-        let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
-
-        if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext);
-        }
-        else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, document => dockingFunc(sourceContext!));
-        }
-        else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page)));
-
-        }
-        else {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, dockingFunc);
-        }
-    }
-
-    // DONE
-    // opens link in new tab (not in a collection)
-    // this opens it full screen, do we need a separate full screen option?
-    @undoBatch
-    openLinkTab = () => {
-        this.highlightDoc();
-        let fullScreenAlias = Doc.MakeAlias(this.props.destinationDoc);
-        this.props.addDocTab(fullScreenAlias, undefined, "inTab");
-        SelectionManager.DeselectAll();
-    }
-
-    // NOT TESTED
-    // opens link in new tab in collection
-    // col = collection the doc is in
-    // target = the document to center on
-    @undoBatch
-    openLinkColTab = (col: Doc) => {
-        this.highlightDoc();
-        col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
-        if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
-            const newPanX = NumCast(this.props.destinationDoc.x) + NumCast(this.props.destinationDoc.width) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
-            const newPanY = NumCast(this.props.destinationDoc.y) + NumCast(this.props.destinationDoc.height) / NumCast(this.props.destinationDoc.zoomBasis, 1) / 2;
-            col.panX = newPanX;
-            col.panY = newPanY;
-        }
-        // CollectionDockingView.Instance.AddRightSplit(col, undefined);
-        this.props.addDocTab(col, undefined, "inTab");
-        SelectionManager.DeselectAll();
-    }
-
-    // DONE
-    // this will open a link next to the source doc
-    @undoBatch
-    openLinkInPlace = () => {
-        this.highlightDoc();
-
-        let alias = Doc.MakeAlias(this.props.destinationDoc);
-        let y = NumCast(this.props.sourceDoc.y);
-        let x = NumCast(this.props.sourceDoc.x);
-
-        let width = NumCast(this.props.sourceDoc.width);
-        let height = NumCast(this.props.sourceDoc.height);
-
-        alias.x = x + width + 30;
-        alias.y = y;
-        alias.width = width;
-        alias.height = height;
-
-        SelectionManager.SelectedDocuments().map(dv => {
-            if (dv.props.Document === this.props.sourceDoc) {
-                dv.props.addDocument && dv.props.addDocument(alias, false);
-            }
-        });
-
-        this.jumpToLink(false);
-    }
-
-    //set this to be the default link behavior, can be any of the above
-    private defaultLinkBehavior: any = this.openLinkInPlace;
-
     onEdit = (e: React.PointerEvent): void => {
         e.stopPropagation();
         this.props.showEditor(this.props.linkDoc);
@@ -226,6 +87,26 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         e.stopPropagation();
     }
 
+    onContextMenu = (e: React.MouseEvent) => {
+        e.preventDefault();
+        ContextMenu.Instance.addItem({ description: "Open in Link Follower", event: () => console.log("opening 1!"), icon: "link" });
+        ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" });
+        ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
+    }
+
+    followDefault = () => {
+        if (!LinkFollowBox.Instance) {
+            Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
+        }
+        LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+        LinkFollowBox.Instance.defaultLinkBehavior();
+    }
+
+    openLinkFollower = () => {
+        LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+        MainView.Instance.toggleLinkFollowBox(false);
+    }
+
     render() {
 
         let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType);
@@ -240,12 +121,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                             {canExpand ? <div title="Show more" className="button" onPointerDown={() => this.toggleShowMore()}>
                                 <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
                             <div title="Edit link" className="button" onPointerDown={this.onEdit}><FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
-                            {/* Original */}
-                            {/* <div title="Follow link" className="button" onPointerDown={this.onFollowLink}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */}
-                            {/* New */}
-                            <div title="Follow link" className="button" onClick={() => LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc)}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
-                            {/* <div title="Follow link" className="button" onClick={this.defaultLinkBehavior}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */}
-
+                            <div title="Follow link" className="button" onClick={this.followDefault} onContextMenu={this.onContextMenu}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
                         </div>
                     </div>
                     {this._showMore ? this.renderMetadata() : <></>}
@@ -254,44 +130,4 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
             </div >
         );
     }
-}
-
-    // @undoBatch
-    // onFollowLink = async (e: React.PointerEvent): Promise<void> => {
-    //     e.stopPropagation();
-    //     e.persist();
-    //     let jumpToDoc = this.props.destinationDoc;
-    //     let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc));
-    //     if (pdfDoc) {
-    //         jumpToDoc = pdfDoc;
-    //     }
-    //     let proto = Doc.GetProto(this.props.linkDoc);
-    //     let targetContext = await Cast(proto.targetContext, Doc);
-    //     let sourceContext = await Cast(proto.sourceContext, Doc);
-    //     let self = this;
-
-
-    //     let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
-    //     if (e.ctrlKey) {
-    //         dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined);
-    //     }
-
-    //     if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) {
-    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, async document => dockingFunc(document), undefined, targetContext!);
-    //         console.log("1")
-    //     }
-    //     else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) {
-    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!));
-    //         console.log("2")
-    //     }
-    //     else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
-    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page)));
-    //         console.log("3")
-
-    //     }
-    //     else {
-    //         DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc);
-    //         console.log("4")
-
-    //     }
-    // }
\ No newline at end of file
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From c1adf10630a4fd163c1c9ef11abf9ad090bf29a3 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 27 Aug 2019 18:29:02 -0400
Subject: haudfhajfjadjad['jad'

---
 src/client/views/MainView.tsx             | 2 +-
 src/client/views/linking/LinkMenuItem.tsx | 8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d580925d6..20fc1dce8 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -155,6 +155,7 @@ export class MainView extends React.Component {
     constructor(props: Readonly<{}>) {
         super(props);
         MainView.Instance = this;
+
         // causes errors to be generated when modifying an observable outside of an action
         configure({ enforceActions: "observed" });
         if (window.location.pathname !== RouteStore.home) {
@@ -470,7 +471,6 @@ export class MainView extends React.Component {
             [React.createRef<HTMLDivElement>(), "globe-asia", "Add Website", addWebNode],
             [React.createRef<HTMLDivElement>(), "bolt", "Add Button", addButtonDocument],
             [React.createRef<HTMLDivElement>(), "file", "Add Document Dragger", addDragboxNode],
-            // [React.createRef<HTMLDivElement>(), "link", "Open Link Follow Box", addLinkFollowBox],
             [React.createRef<HTMLDivElement>(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode
             //[React.createRef<HTMLDivElement>(), "play", "Add Youtube Searcher", addYoutubeSearcher],
         ];
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 0dda948c4..1210d7198 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -8,7 +8,7 @@ import './LinkMenu.scss';
 import React = require("react");
 import { Doc, DocListCastAsync, WidthSym } from '../../../new_fields/Doc';
 import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types';
-import { observable, action } from 'mobx';
+import { observable, action, computed } from 'mobx';
 import { LinkManager } from '../../util/LinkManager';
 import { DragLinkAsDocument } from '../../util/DragManager';
 import { CollectionDockingView } from '../collections/CollectionDockingView';
@@ -20,6 +20,7 @@ import { LinkFollowBox } from './LinkFollowBox';
 import { ContextMenu } from '../ContextMenu';
 import { MainView } from '../MainView';
 import { Docs } from '../../documents/Documents';
+import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
 library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp);
 
 
@@ -95,8 +96,9 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     }
 
     followDefault = () => {
-        if (!LinkFollowBox.Instance) {
-            Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
+        if (LinkFollowBox.Instance === undefined) {
+            let doc = Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
+            Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
         }
         LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
         LinkFollowBox.Instance.defaultLinkBehavior();
-- 
cgit v1.2.3-70-g09d2


From f204675b5b952fd9fdf301c41d702cfe1f5633e3 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 27 Aug 2019 18:48:14 -0400
Subject: works i think

---
 src/client/views/linking/LinkMenuItem.tsx | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 1210d7198..0ae578d5a 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -90,23 +90,30 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
     onContextMenu = (e: React.MouseEvent) => {
         e.preventDefault();
-        ContextMenu.Instance.addItem({ description: "Open in Link Follower", event: () => console.log("opening 1!"), icon: "link" });
+        ContextMenu.Instance.addItem({ description: "Open in Link Follower", event: () => this.openLinkFollower(), icon: "link" });
         ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" });
         ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
     }
 
-    followDefault = () => {
+    @action.bound
+    async followDefault() {
         if (LinkFollowBox.Instance === undefined) {
-            let doc = Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
-            Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
+            let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
+            await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
         }
         LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
         LinkFollowBox.Instance.defaultLinkBehavior();
     }
 
-    openLinkFollower = () => {
+    @action.bound
+    async openLinkFollower() {
+        if (LinkFollowBox.Instance === undefined) {
+            let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
+            await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
+        } else {
+            MainView.Instance.toggleLinkFollowBox(false);
+        }
         LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
-        MainView.Instance.toggleLinkFollowBox(false);
     }
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From 0b43aead85c0de5877c0ecea7703acb6f2539249 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 29 Aug 2019 13:48:15 -0400
Subject: fixed re-opening linkbox.  adding linkbox dragging.

---
 src/client/views/OverlayView.scss          |  5 ++
 src/client/views/OverlayView.tsx           | 77 +++++++++++++++++++++---------
 src/client/views/linking/LinkFollowBox.tsx |  5 +-
 src/client/views/linking/LinkMenuItem.tsx  |  7 +--
 4 files changed, 67 insertions(+), 27 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss
index dc122497f..26c2e0e1e 100644
--- a/src/client/views/OverlayView.scss
+++ b/src/client/views/OverlayView.scss
@@ -39,4 +39,9 @@
     width: 10px;
     height: 10px;
     cursor: nwse-resize;
+}
+
+.overlayView-doc {
+    z-index: 1;
+    position: absolute;
 }
\ No newline at end of file
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 8d80ad1f1..bc02a49c6 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,7 +1,7 @@
 import * as React from "react";
 import { observer } from "mobx-react";
 import { observable, action } from "mobx";
-import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString } from "../../Utils";
+import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString, returnZero, returnFalse } from "../../Utils";
 
 import './OverlayView.scss';
 import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
@@ -10,6 +10,8 @@ import { Id } from "../../new_fields/FieldSymbols";
 import { DocumentView } from "./nodes/DocumentView";
 import { Transform } from "../util/Transform";
 import { CollectionFreeFormDocumentView } from "./nodes/CollectionFreeFormDocumentView";
+import { DocumentContentsView } from "./nodes/DocumentContentsView";
+import { NumCast } from "../../new_fields/Types";
 
 export type OverlayDisposer = () => void;
 
@@ -142,27 +144,58 @@ export class OverlayView extends React.Component {
         return (
             <div className="overlayView" id="overlayView">
                 {this._elements}
-                {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => (
-                    <CollectionFreeFormDocumentView key={d[Id]}
-                        Document={d}
-                        bringToFront={emptyFunction}
-                        addDocument={undefined}
-                        removeDocument={undefined}
-                        ContentScaling={returnOne}
-                        PanelWidth={returnOne}
-                        PanelHeight={returnOne}
-                        ScreenToLocalTransform={Transform.Identity}
-                        renderDepth={1}
-                        selectOnLoad={false}
-                        parentActive={returnTrue}
-                        whenActiveChanged={emptyFunction}
-                        focus={emptyFunction}
-                        backgroundColor={returnEmptyString}
-                        addDocTab={emptyFunction}
-                        pinToPres={emptyFunction}
-                        ContainingCollectionView={undefined}
-                        zoomToScale={emptyFunction}
-                        getScale={returnOne} />))}
+                {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => {
+                    let offsetx = 0, offsety = 0;
+                    let onPointerMove = action((e: PointerEvent) => {
+                        if (e.buttons === 1) {
+                            d.x = e.clientX + offsetx;
+                            d.y = e.clientY + offsety;
+                            e.stopPropagation();
+                            e.preventDefault();
+                        }
+                    });
+                    let onPointerUp = action((e: PointerEvent) => {
+                        document.removeEventListener("pointermove", onPointerMove);
+                        document.removeEventListener("pointerup", onPointerUp);
+                        e.stopPropagation();
+                        e.preventDefault();
+                    });
+
+                    let onPointerDown = (e: React.PointerEvent) => {
+                        offsetx = NumCast(d.x) - e.clientX;
+                        offsety = NumCast(d.y) - e.clientY;
+                        e.stopPropagation();
+                        e.preventDefault();
+                        document.addEventListener("pointermove", onPointerMove);
+                        document.addEventListener("pointerup", onPointerUp);
+                    }
+                    return <div className="overlayView-doc" key={d[Id]} onPointerDown={onPointerDown} style={{ transform: `translate(${d.x}px, ${d.y}px)` }}>
+                        <DocumentContentsView
+                            Document={d}
+                            ChromeHeight={returnZero}
+                            isSelected={returnFalse}
+                            select={emptyFunction}
+                            layoutKey={"layout"}
+                            bringToFront={emptyFunction}
+                            addDocument={undefined}
+                            removeDocument={undefined}
+                            ContentScaling={returnOne}
+                            PanelWidth={returnOne}
+                            PanelHeight={returnOne}
+                            ScreenToLocalTransform={Transform.Identity}
+                            renderDepth={1}
+                            selectOnLoad={false}
+                            parentActive={returnTrue}
+                            whenActiveChanged={emptyFunction}
+                            focus={emptyFunction}
+                            backgroundColor={returnEmptyString}
+                            addDocTab={emptyFunction}
+                            pinToPres={emptyFunction}
+                            ContainingCollectionView={undefined}
+                            zoomToScale={emptyFunction}
+                            getScale={returnOne} />
+                    </div>
+                })}
             </div>
         );
     }
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 54670e2c7..07f07f72a 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -38,7 +38,7 @@ enum FollowOptions {
 export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); }
-    public static Instance: LinkFollowBox;
+    public static Instance: LinkFollowBox | undefined;
     @observable static linkDoc: Doc | undefined = undefined;
     @observable static destinationDoc: Doc | undefined = undefined;
     @observable static sourceDoc: Doc | undefined = undefined;
@@ -557,7 +557,8 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     async close() {
         let res = await DocListCastAsync((CurrentUserUtils.UserDocument.overlays as Doc).data);
-        if (res) res.splice(res.indexOf(LinkFollowBox.Instance.props.Document), 1);
+        if (res) res.splice(res.indexOf(LinkFollowBox.Instance!.props.Document), 1);
+        LinkFollowBox.Instance = undefined;
     }
 
     render() {
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 0ae578d5a..6c10d4fb6 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -100,9 +100,10 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         if (LinkFollowBox.Instance === undefined) {
             let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
             await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
+        } else {
+            LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+            LinkFollowBox.Instance!.defaultLinkBehavior();
         }
-        LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
-        LinkFollowBox.Instance.defaultLinkBehavior();
     }
 
     @action.bound
@@ -113,7 +114,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         } else {
             MainView.Instance.toggleLinkFollowBox(false);
         }
-        LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+        LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
     }
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From f6c15087d30f27c15b3b6304af58c93c65536131 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 29 Aug 2019 14:50:22 -0400
Subject: changed linkFollowBox creation approach.  fixed target contexts to
 add link default.

---
 src/client/views/MainView.tsx                      |   8 +-
 src/client/views/OverlayView.tsx                   | 108 +++++++++++----------
 src/client/views/linking/LinkFollowBox.tsx         |  20 ++--
 src/client/views/linking/LinkMenuItem.tsx          |  18 ++--
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   1 -
 src/client/views/nodes/FormattedTextBoxComment.tsx |   8 +-
 .../authentication/models/current_user_utils.ts    |   3 +
 7 files changed, 78 insertions(+), 88 deletions(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 1fc8d1397..b64986084 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -438,13 +438,7 @@ export class MainView extends React.Component {
         if (LinkFollowBox.Instance) {
             let dvs = DocumentManager.Instance.getDocumentViews(LinkFollowBox.Instance.props.Document);
             // if it already exisits, close it
-            if (dvs.length > 0 && shouldClose) LinkFollowBox.Instance.close();
-            // open it if not
-            else Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", LinkFollowBox.Instance.props.Document);
-        }
-        else {
-            let doc = Docs.Create.LinkFollowBoxDocument({ x: this.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
-            Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
+            LinkFollowBox.Instance.props.Document.isMinimized = (dvs.length > 0 && shouldClose);
         }
     }
 
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index a1afe651c..54ab8696e 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,6 +1,6 @@
 import * as React from "react";
 import { observer } from "mobx-react";
-import { observable, action } from "mobx";
+import { observable, action, trace, computed } from "mobx";
 import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString, returnZero, returnFalse } from "../../Utils";
 
 import './OverlayView.scss';
@@ -140,61 +140,65 @@ export class OverlayView extends React.Component {
         return remove;
     }
 
+    @computed get overlayDocs() {
+        return CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => {
+            let offsetx = 0, offsety = 0;
+            let onPointerMove = action((e: PointerEvent) => {
+                if (e.buttons === 1) {
+                    d.x = e.clientX + offsetx;
+                    d.y = e.clientY + offsety;
+                    e.stopPropagation();
+                    e.preventDefault();
+                }
+            });
+            let onPointerUp = action((e: PointerEvent) => {
+                document.removeEventListener("pointermove", onPointerMove);
+                document.removeEventListener("pointerup", onPointerUp);
+                e.stopPropagation();
+                e.preventDefault();
+            });
+
+            let onPointerDown = (e: React.PointerEvent) => {
+                offsetx = NumCast(d.x) - e.clientX;
+                offsety = NumCast(d.y) - e.clientY;
+                e.stopPropagation();
+                e.preventDefault();
+                document.addEventListener("pointermove", onPointerMove);
+                document.addEventListener("pointerup", onPointerUp);
+            };
+            return <div className="overlayView-doc" key={d[Id]} onPointerDown={onPointerDown} style={{ transform: `translate(${d.x}px, ${d.y}px)`, display: d.isMinimized ? "none" : "" }}>
+                <DocumentContentsView
+                    Document={d}
+                    ChromeHeight={returnZero}
+                    isSelected={returnFalse}
+                    select={emptyFunction}
+                    layoutKey={"layout"}
+                    bringToFront={emptyFunction}
+                    addDocument={undefined}
+                    removeDocument={undefined}
+                    ContentScaling={returnOne}
+                    PanelWidth={returnOne}
+                    PanelHeight={returnOne}
+                    ScreenToLocalTransform={Transform.Identity}
+                    renderDepth={1}
+                    parentActive={returnTrue}
+                    whenActiveChanged={emptyFunction}
+                    focus={emptyFunction}
+                    backgroundColor={returnEmptyString}
+                    addDocTab={emptyFunction}
+                    pinToPres={emptyFunction}
+                    ContainingCollectionView={undefined}
+                    zoomToScale={emptyFunction}
+                    getScale={returnOne} />
+            </div>;
+        })
+    }
+
     render() {
         return (
             <div className="overlayView" id="overlayView">
                 {this._elements}
-                {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => {
-                    let offsetx = 0, offsety = 0;
-                    let onPointerMove = action((e: PointerEvent) => {
-                        if (e.buttons === 1) {
-                            d.x = e.clientX + offsetx;
-                            d.y = e.clientY + offsety;
-                            e.stopPropagation();
-                            e.preventDefault();
-                        }
-                    });
-                    let onPointerUp = action((e: PointerEvent) => {
-                        document.removeEventListener("pointermove", onPointerMove);
-                        document.removeEventListener("pointerup", onPointerUp);
-                        e.stopPropagation();
-                        e.preventDefault();
-                    });
-
-                    let onPointerDown = (e: React.PointerEvent) => {
-                        offsetx = NumCast(d.x) - e.clientX;
-                        offsety = NumCast(d.y) - e.clientY;
-                        e.stopPropagation();
-                        e.preventDefault();
-                        document.addEventListener("pointermove", onPointerMove);
-                        document.addEventListener("pointerup", onPointerUp);
-                    }
-                    return <div className="overlayView-doc" key={d[Id]} onPointerDown={onPointerDown} style={{ transform: `translate(${d.x}px, ${d.y}px)` }}>
-                        <DocumentContentsView
-                            Document={d}
-                            ChromeHeight={returnZero}
-                            isSelected={returnFalse}
-                            select={emptyFunction}
-                            layoutKey={"layout"}
-                            bringToFront={emptyFunction}
-                            addDocument={undefined}
-                            removeDocument={undefined}
-                            ContentScaling={returnOne}
-                            PanelWidth={returnOne}
-                            PanelHeight={returnOne}
-                            ScreenToLocalTransform={Transform.Identity}
-                            renderDepth={1}
-                            parentActive={returnTrue}
-                            whenActiveChanged={emptyFunction}
-                            focus={emptyFunction}
-                            backgroundColor={returnEmptyString}
-                            addDocTab={emptyFunction}
-                            pinToPres={emptyFunction}
-                            ContainingCollectionView={undefined}
-                            zoomToScale={emptyFunction}
-                            getScale={returnOne} />
-                    </div>
-                })}
+                {this.overlayDocs}
             </div>
         );
     }
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 07f07f72a..74663f9af 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -1,4 +1,4 @@
-import { observable, computed, action, trace, ObservableMap, runInAction, reaction, IReactionDisposer } from "mobx";
+import { observable, computed, action, runInAction, reaction, IReactionDisposer } from "mobx";
 import React = require("react");
 import { observer } from "mobx-react";
 import { FieldViewProps, FieldView } from "../nodes/FieldView";
@@ -15,8 +15,6 @@ import { SearchUtil } from "../../util/SearchUtil";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { listSpec } from "../../../new_fields/Schema";
 import { DocServer } from "../../DocServer";
-import { RefField } from "../../../new_fields/RefField";
-import { Docs } from "../../documents/Documents";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { faTimes } from '@fortawesome/free-solid-svg-icons';
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
@@ -126,9 +124,11 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs)));
             allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index])));
             docs.forEach(doc => map.delete(doc));
-            runInAction(() => {
+            runInAction(async () => {
                 this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: dest }));
                 this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target }));
+                let tcontext = LinkFollowBox.linkDoc && (await Cast(LinkFollowBox.linkDoc.targetContext, Doc)) as Doc;
+                runInAction(() => tcontext && this._docs.splice(0, 0, { col: tcontext, target: dest }));
             });
         }
     }
@@ -268,7 +268,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             let fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
             // THIS IS EMPTY FUNCTION
             this.props.addDocTab(fullScreenAlias, undefined, "inTab");
-            console.log(this.props.addDocTab)
+            console.log(this.props.addDocTab);
 
             this.highlightDoc();
             SelectionManager.DeselectAll();
@@ -348,7 +348,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             }
             else if (this.selectedMode === FollowModes.OPENTAB) {
                 if (notOpenInContext) this.openLinkTab();
-                else this.selectedContext && this.openLinkColTab({ context: this.selectedContext, shouldZoom: shouldZoom })
+                else this.selectedContext && this.openLinkColTab({ context: this.selectedContext, shouldZoom: shouldZoom });
             }
             else if (this.selectedMode === FollowModes.PAN) {
                 this.jumpToLink({ shouldZoom: shouldZoom });
@@ -555,19 +555,13 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         return null;
     }
 
-    async close() {
-        let res = await DocListCastAsync((CurrentUserUtils.UserDocument.overlays as Doc).data);
-        if (res) res.splice(res.indexOf(LinkFollowBox.Instance!.props.Document), 1);
-        LinkFollowBox.Instance = undefined;
-    }
-
     render() {
         return (
             <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document.height), width: NumCast(this.props.Document.width) }}>
                 <div className="linkFollowBox-header">
                     <div className="topHeader">
                         {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"}
-                        <div onClick={this.close} className="closeDocument"><FontAwesomeIcon icon={faTimes} size="lg" /></div>
+                        <div onClick={() => this.props.Document.isMinimized = true} className="closeDocument"><FontAwesomeIcon icon={faTimes} size="lg" /></div>
                     </div>
                     <div className=" direction-indicator">{LinkFollowBox.linkDoc ?
                         LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc ? "Source: " + StrCast(LinkFollowBox.sourceDoc.title) + ", Destination: " + StrCast(LinkFollowBox.destinationDoc.title)
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 6c10d4fb6..780f161d3 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -97,24 +97,20 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
     @action.bound
     async followDefault() {
-        if (LinkFollowBox.Instance === undefined) {
-            let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
-            await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
-        } else {
-            LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
-            LinkFollowBox.Instance!.defaultLinkBehavior();
+        if (LinkFollowBox.Instance !== undefined) {
+            LinkFollowBox.Instance.props.Document.isMinimized = false;
+            LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+            LinkFollowBox.Instance.defaultLinkBehavior();
         }
     }
 
     @action.bound
     async openLinkFollower() {
-        if (LinkFollowBox.Instance === undefined) {
-            let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
-            await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
-        } else {
+        if (LinkFollowBox.Instance !== undefined) {
+            LinkFollowBox.Instance.props.Document.isMinimized = false;
             MainView.Instance.toggleLinkFollowBox(false);
+            LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
         }
-        LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
     }
 
     render() {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 7631ecc6c..c9c394960 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -8,7 +8,6 @@ import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"
 import "./DocumentView.scss";
 import React = require("react");
 import { Doc } from "../../../new_fields/Doc";
-import { returnEmptyString } from "../../../Utils";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     x?: number;
diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx
index 9123f8aed..0287d93a9 100644
--- a/src/client/views/nodes/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/FormattedTextBoxComment.tsx
@@ -1,12 +1,12 @@
-import { Plugin, EditorState } from "prosemirror-state"
-import './FormattedTextBoxComment.scss'
+import { Plugin, EditorState } from "prosemirror-state";
+import './FormattedTextBoxComment.scss';
 import { ResolvedPos, Mark } from "prosemirror-model";
 import { EditorView } from "prosemirror-view";
 import { Doc } from "../../../new_fields/Doc";
 
 export let selectionSizePlugin = new Plugin({
     view(editorView) { return new SelectionSizeTooltip(editorView); }
-})
+});
 export function findOtherUserMark(marks: Mark[]): Mark | undefined {
     return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail);
 }
@@ -106,5 +106,5 @@ export class SelectionSizeTooltip {
         }
     }
 
-    destroy() { SelectionSizeTooltip.tooltip.style.display = "none" }
+    destroy() { SelectionSizeTooltip.tooltip.style.display = "none"; }
 }
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 83e45d3ce..9866e22eb 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -79,6 +79,9 @@ export class CurrentUserUtils {
             Doc.GetProto(overlays).backgroundColor = "#aca3a6";
             doc.overlays = overlays;
         }
+        if (doc.linkFollowBox === undefined) {
+            PromiseValue(Cast(doc.overlays, Doc)).then(overlays => overlays && Doc.AddDocToList(overlays, "data", doc.linkFollowBox = Docs.Create.LinkFollowBoxDocument({ x: 250, y: 20, width: 500, height: 370, title: "Link Follower" })));
+        }
         StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library");
         doc.width = 100;
         doc.preventTreeViewOpen = true;
-- 
cgit v1.2.3-70-g09d2


From 195497328a6113c40993f3a3d525cc6596955d7c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 29 Aug 2019 14:55:40 -0400
Subject: restored old link edit menu

---
 src/client/views/linking/LinkMenuItem.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/linking/LinkMenuItem.tsx')

diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 780f161d3..6895dae9a 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -42,7 +42,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     onEdit = (e: React.PointerEvent): void => {
         e.stopPropagation();
         this.props.showEditor(this.props.linkDoc);
-        SelectionManager.DeselectAll();
+        //SelectionManager.DeselectAll();
     }
 
     renderMetadata = (): JSX.Element => {
-- 
cgit v1.2.3-70-g09d2

