From 7f6a802ad6306e55332cf2fd50084de80f935650 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Mon, 19 Aug 2019 20:46:26 -0400
Subject: a few link behaviors are done

---
 src/client/views/nodes/LinkMenu.tsx | 1 +
 1 file changed, 1 insertion(+)

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

diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 1a4af04f8..fe7d88457 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -42,6 +42,7 @@ export class LinkMenu extends React.Component<Props> {
             linkItems.push(
                 <LinkMenuGroup
                     key={groupType}
+                    docView={this.props.docView}
                     sourceDoc={this.props.docView.props.Document}
                     group={group}
                     groupType={groupType}
-- 
cgit v1.2.3-70-g09d2


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

---
 package.json                                       |   2 +-
 src/client/views/DocumentDecorations.tsx           |   2 +-
 src/client/views/PreviewCursor.tsx                 |   2 +-
 src/client/views/linking/LinkEditor.scss           | 145 ++++++++
 src/client/views/linking/LinkEditor.tsx            | 400 +++++++++++++++++++++
 src/client/views/linking/LinkFollowBox.tsx         |   9 +
 src/client/views/linking/LinkMenu.scss             | 137 +++++++
 src/client/views/linking/LinkMenu.tsx              |  76 ++++
 src/client/views/linking/LinkMenuGroup.tsx         | 111 ++++++
 src/client/views/linking/LinkMenuItem.tsx          | 282 +++++++++++++++
 src/client/views/nodes/LinkEditor.scss             | 145 --------
 src/client/views/nodes/LinkEditor.tsx              | 400 ---------------------
 src/client/views/nodes/LinkMenu.scss               | 137 -------
 src/client/views/nodes/LinkMenu.tsx                |  76 ----
 src/client/views/nodes/LinkMenuGroup.tsx           | 111 ------
 src/client/views/nodes/LinkMenuItem.tsx            | 282 ---------------
 src/client/views/nodes/WebBox.tsx                  |   3 +-
 .../authentication/models/current_user_utils.ts    |   2 +-
 18 files changed, 1165 insertions(+), 1157 deletions(-)
 create mode 100644 src/client/views/linking/LinkEditor.scss
 create mode 100644 src/client/views/linking/LinkEditor.tsx
 create mode 100644 src/client/views/linking/LinkFollowBox.tsx
 create mode 100644 src/client/views/linking/LinkMenu.scss
 create mode 100644 src/client/views/linking/LinkMenu.tsx
 create mode 100644 src/client/views/linking/LinkMenuGroup.tsx
 create mode 100644 src/client/views/linking/LinkMenuItem.tsx
 delete mode 100644 src/client/views/nodes/LinkEditor.scss
 delete mode 100644 src/client/views/nodes/LinkEditor.tsx
 delete mode 100644 src/client/views/nodes/LinkMenu.scss
 delete mode 100644 src/client/views/nodes/LinkMenu.tsx
 delete mode 100644 src/client/views/nodes/LinkMenuGroup.tsx
 delete mode 100644 src/client/views/nodes/LinkMenuItem.tsx

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

diff --git a/package.json b/package.json
index de1f3f6e6..cd60b7b55 100644
--- a/package.json
+++ b/package.json
@@ -219,4 +219,4 @@
         "xoauth2": "^1.2.0",
         "youtube": "^0.1.0"
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b18a3c192..2d92aaba7 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -20,7 +20,7 @@ import { DocumentView, PositionDocument } from "./nodes/DocumentView";
 import { FieldView } from "./nodes/FieldView";
 import { FormattedTextBox, GoogleRef } from "./nodes/FormattedTextBox";
 import { IconBox } from "./nodes/IconBox";
-import { LinkMenu } from "./nodes/LinkMenu";
+import { LinkMenu } from "./linking/LinkMenu";
 import { TemplateMenu } from "./TemplateMenu";
 import { Template, Templates } from "./Templates";
 import React = require("react");
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 40be470d6..9ec31d67d 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -51,7 +51,7 @@ export class PreviewCursor extends React.Component<{}> {
                     // tests for URL and makes web document
                     let re: any = /^https?:\/\/www\./g;
                     if (re.test(e.clipboardData.getData("text/plain"))) {
-                        const url = e.clipboardData.getData("text/plain")
+                        const url = e.clipboardData.getData("text/plain");
                         PreviewCursor._addDocument(Docs.Create.WebDocument(url, {
                             title: url, width: 300, height: 300,
                             // nativeWidth: 300, nativeHeight: 472.5,
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
new file mode 100644
index 000000000..fc5f2410c
--- /dev/null
+++ b/src/client/views/linking/LinkEditor.scss
@@ -0,0 +1,145 @@
+@import "../globalCssVariables";
+
+.linkEditor {
+    width: 100%;
+    height: auto;
+    font-size: 12px; // TODO
+}
+
+.linkEditor-back {
+    margin-bottom: 6px;
+}
+
+.linkEditor-info {
+    border-bottom: 0.5px solid $light-color-secondary; 
+    padding-bottom: 6px;
+    margin-bottom: 6px;
+    display: flex;
+    justify-content: space-between;
+
+    .linkEditor-linkedTo {
+        width: calc(100% - 26px);
+    }
+}
+
+.linkEditor-button {
+    width: 20px;
+    height: 20px;
+    margin-left: 6px;
+    padding: 0;
+    // font-size: 12px;
+    border-radius: 10px;
+
+    &:disabled {
+        background-color: gray;
+    }
+}
+
+.linkEditor-groupsLabel {
+    display: flex;
+    justify-content: space-between;
+}
+
+.linkEditor-group {
+    background-color: $light-color-secondary; 
+    padding: 6px;
+    margin: 3px 0;
+    border-radius: 3px;
+
+    .linkEditor-group-row {
+        display: flex;
+        margin-bottom: 3px;
+
+        .linkEditor-group-row-label {
+            margin-right: 6px;
+        }
+    }
+
+    .linkEditor-metadata-row {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 6px;
+
+        .linkEditor-error {
+            border-color: red;
+        }
+
+        input {
+            width: calc(50% - 16px);
+            height: 20px;
+        }
+
+        button {
+            width: 20px;
+            height: 20px;
+            margin-left: 3px;
+            padding: 0;
+            font-size: 10px;
+        }
+    }
+}
+
+
+.linkEditor-dropdown {
+    width: 100%;
+    position: relative;
+    z-index: 999;
+
+    input {
+        width: 100%;
+    }
+
+    .linkEditor-options-wrapper {
+        width: 100%;
+        position: absolute;
+        top: 19px;
+        left: 0;
+        display: flex;
+        flex-direction: column;
+    }
+
+    .linkEditor-option {
+        background-color: $light-color-secondary;
+        border: 1px solid $intermediate-color;
+        border-top: 0;
+        padding: 3px;
+        cursor: pointer;
+
+        &:hover {
+            background-color: lightgray;
+        }
+
+        &.onDown {
+            background-color: gray;
+        }
+    }
+}
+
+.linkEditor-typeButton {
+    background-color: transparent;
+    color: $dark-color;
+    width: 100%;
+    height: 20px;
+    padding: 0 3px;
+    padding-bottom: 2px;
+    text-align: left;
+    text-transform: none;
+    letter-spacing: normal;
+    font-size: 12px;
+    font-weight: bold;
+
+    &:hover {
+        background-color: $light-color;
+    }
+}
+
+.linkEditor-group-buttons {
+    height: 20px;
+    display: flex;
+    justify-content: flex-end;
+    margin-top: 5px;
+
+    .linkEditor-button {
+        margin-left: 6px;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
new file mode 100644
index 000000000..ecb3e9db4
--- /dev/null
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -0,0 +1,400 @@
+import { observable, computed, action, trace } from "mobx";
+import React = require("react");
+import { observer } from "mobx-react";
+import './LinkEditor.scss';
+import { StrCast, Cast, FieldValue } from "../../../new_fields/Types";
+import { Doc } from "../../../new_fields/Doc";
+import { LinkManager } from "../../util/LinkManager";
+import { Docs } from "../../documents/Documents";
+import { Utils } from "../../../Utils";
+import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus } from '@fortawesome/free-solid-svg-icons';
+import { library } from "@fortawesome/fontawesome-svg-core";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { SetupDrag } from "../../util/DragManager";
+import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
+
+library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus);
+
+
+interface GroupTypesDropdownProps {
+    groupType: string;
+    setGroupType: (group: string) => void;
+}
+// this dropdown could be generalized
+@observer
+class GroupTypesDropdown extends React.Component<GroupTypesDropdownProps> {
+    @observable private _searchTerm: string = this.props.groupType;
+    @observable private _groupType: string = this.props.groupType;
+    @observable private _isEditing: boolean = false;
+
+    @action
+    createGroup = (groupType: string): void => {
+        this.props.setGroupType(groupType);
+        LinkManager.Instance.addGroupType(groupType);
+    }
+
+    @action
+    onChange = (val: string): void => {
+        this._searchTerm = val;
+        this._groupType = val;
+        this._isEditing = true;
+    }
+
+    @action
+    onKeyDown = (e: React.KeyboardEvent): void => {
+        if (e.key === "Enter") {
+            let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes());
+            let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+            let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase());
+
+            if (exactFound > -1) {
+                let groupType = groupOptions[exactFound];
+                this.props.setGroupType(groupType);
+                this._groupType = groupType;
+            } else {
+                this.createGroup(this._searchTerm);
+                this._groupType = this._searchTerm;
+            }
+
+            this._searchTerm = this._groupType;
+            this._isEditing = false;
+        }
+    }
+
+    @action
+    onOptionClick = (value: string, createNew: boolean): void => {
+        if (createNew) {
+            this.createGroup(this._searchTerm);
+            this._groupType = this._searchTerm;
+
+        } else {
+            this.props.setGroupType(value);
+            this._groupType = value;
+
+        }
+        this._searchTerm = this._groupType;
+        this._isEditing = false;
+    }
+
+    @action
+    onButtonPointerDown = (): void => {
+        this._isEditing = true;
+    }
+
+    renderOptions = (): JSX.Element[] | JSX.Element => {
+        if (this._searchTerm === "") return <></>;
+
+        let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes());
+        let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+        let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()) > -1;
+
+        let options = groupOptions.map(groupType => {
+            let ref = React.createRef<HTMLDivElement>();
+            return <div key={groupType} ref={ref} className="linkEditor-option"
+                onClick={() => this.onOptionClick(groupType, false)}>{groupType}</div>;
+        });
+
+        // if search term does not already exist as a group type, give option to create new group type
+        if (!exactFound && this._searchTerm !== "") {
+            let ref = React.createRef<HTMLDivElement>();
+            options.push(<div key={""} ref={ref} className="linkEditor-option"
+                onClick={() => this.onOptionClick(this._searchTerm, true)}>Define new "{this._searchTerm}" relationship</div>);
+        }
+
+        return options;
+    }
+
+    render() {
+        if (this._isEditing || this._groupType === "") {
+            return (
+                <div className="linkEditor-dropdown">
+                    <input type="text" value={this._groupType} placeholder="Search for or create a new group"
+                        onChange={e => this.onChange(e.target.value)} onKeyDown={this.onKeyDown} autoFocus></input>
+                    <div className="linkEditor-options-wrapper">
+                        {this.renderOptions()}
+                    </div>
+                </div >
+            );
+        } else {
+            return <button className="linkEditor-typeButton" onClick={() => this.onButtonPointerDown()}>{this._groupType}</button>;
+        }
+    }
+}
+
+
+interface LinkMetadataEditorProps {
+    id: string;
+    groupType: string;
+    mdDoc: Doc;
+    mdKey: string;
+    mdValue: string;
+    changeMdIdKey: (id: string, newKey: string) => void;
+}
+@observer
+class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
+    @observable private _key: string = this.props.mdKey;
+    @observable private _value: string = this.props.mdValue;
+    @observable private _keyError: boolean = false;
+
+    @action
+    setMetadataKey = (value: string): void => {
+        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);
+
+        // don't allow user to create existing key
+        let newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase());
+        if (newIndex > -1) {
+            this._keyError = true;
+            this._key = value;
+            return;
+        } else {
+            this._keyError = false;
+        }
+
+        // set new value for key
+        let currIndex = groupMdKeys.findIndex(key => {
+            return StrCast(key).toUpperCase() === this._key.toUpperCase();
+        });
+        if (currIndex === -1) console.error("LinkMetadataEditor: key was not found");
+        groupMdKeys[currIndex] = value;
+
+        this.props.changeMdIdKey(this.props.id, value);
+        this._key = value;
+        LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, [...groupMdKeys]);
+    }
+
+    @action
+    setMetadataValue = (value: string): void => {
+        if (!this._keyError) {
+            this._value = value;
+            this.props.mdDoc[this._key] = value;
+        }
+    }
+
+    @action
+    removeMetadata = (): void => {
+        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);
+
+        let index = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase());
+        if (index === -1) console.error("LinkMetadataEditor: key was not found");
+        groupMdKeys.splice(index, 1);
+
+        LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, groupMdKeys);
+        this._key = "";
+    }
+
+    render() {
+        return (
+            <div className="linkEditor-metadata-row">
+                <input className={this._keyError ? "linkEditor-error" : ""} type="text" value={this._key === "new key" ? "" : this._key} placeholder="key" onChange={e => this.setMetadataKey(e.target.value)}></input>:
+                <input type="text" value={this._value} placeholder="value" onChange={e => this.setMetadataValue(e.target.value)}></input>
+                <button onClick={() => this.removeMetadata()}><FontAwesomeIcon icon="times" size="sm" /></button>
+            </div>
+        );
+    }
+}
+
+interface LinkGroupEditorProps {
+    sourceDoc: Doc;
+    linkDoc: Doc;
+    groupDoc: Doc;
+}
+@observer
+export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
+
+    private _metadataIds: Map<string, string> = new Map();
+
+    constructor(props: LinkGroupEditorProps) {
+        super(props);
+
+        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.type));
+        groupMdKeys.forEach(key => {
+            this._metadataIds.set(key, Utils.GenerateGuid());
+        });
+    }
+
+    @action
+    setGroupType = (groupType: string): void => {
+        this.props.groupDoc.type = groupType;
+    }
+
+    removeGroupFromLink = (groupType: string): void => {
+        LinkManager.Instance.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType);
+    }
+
+    deleteGroup = (groupType: string): void => {
+        LinkManager.Instance.deleteGroupType(groupType);
+    }
+
+    copyGroup = async (groupType: string): Promise<void> => {
+        let sourceGroupDoc = this.props.groupDoc;
+        const sourceMdDoc = await Cast(sourceGroupDoc.metadata, Doc);
+        if (!sourceMdDoc) return;
+
+        let destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
+        // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc);
+        let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+
+        // create new metadata doc with copied kvp
+        let destMdDoc = new Doc();
+        destMdDoc.anchor1 = StrCast(sourceMdDoc.anchor2);
+        destMdDoc.anchor2 = StrCast(sourceMdDoc.anchor1);
+        keys.forEach(key => {
+            let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]);
+            destMdDoc[key] = val;
+        });
+
+        // create new group doc with new metadata doc
+        let destGroupDoc = new Doc();
+        destGroupDoc.type = groupType;
+        destGroupDoc.metadata = destMdDoc;
+
+        if (destDoc) {
+            LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, destDoc, destGroupDoc, true);
+        }
+    }
+
+    @action
+    addMetadata = (groupType: string): void => {
+        this._metadataIds.set("new key", Utils.GenerateGuid());
+        let mdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+        // only add "new key" if there is no other key with value "new key"; prevents spamming
+        if (mdKeys.indexOf("new key") === -1) mdKeys.push("new key");
+        LinkManager.Instance.setMetadataKeysForGroup(groupType, mdKeys);
+    }
+
+    // for key rendering purposes
+    changeMdIdKey = (id: string, newKey: string) => {
+        this._metadataIds.set(newKey, id);
+    }
+
+    renderMetadata = (): JSX.Element[] => {
+        let metadata: Array<JSX.Element> = [];
+        let groupDoc = this.props.groupDoc;
+        const mdDoc = FieldValue(Cast(groupDoc.metadata, Doc));
+        if (!mdDoc) {
+            return [];
+        }
+        let groupType = StrCast(groupDoc.type);
+        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+
+        groupMdKeys.forEach((key) => {
+            let val = StrCast(mdDoc[key]);
+            metadata.push(
+                <LinkMetadataEditor key={"mded-" + this._metadataIds.get(key)} id={this._metadataIds.get(key)!} groupType={groupType} mdDoc={mdDoc} mdKey={key} mdValue={val} changeMdIdKey={this.changeMdIdKey} />
+            );
+        });
+        return metadata;
+    }
+
+    viewGroupAsTable = (groupType: string): JSX.Element => {
+        let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+        let index = keys.indexOf("");
+        if (index > -1) keys.splice(index, 1);
+        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
+        let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
+        let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
+        let ref = React.createRef<HTMLDivElement>();
+        return <div ref={ref}><button className="linkEditor-button" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>;
+    }
+
+    render() {
+        let groupType = StrCast(this.props.groupDoc.type);
+        // if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") {
+        let buttons;
+        if (groupType === "") {
+            buttons = (
+                <>
+                    <button className="linkEditor-button" disabled={true} title="Add KVP"><FontAwesomeIcon icon="plus" size="sm" /></button>
+                    <button className="linkEditor-button" disabled title="Copy group to opposite anchor"><FontAwesomeIcon icon="exchange-alt" size="sm" /></button>
+                    <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupType)} title="Remove group from link"><FontAwesomeIcon icon="times" size="sm" /></button>
+                    <button className="linkEditor-button" disabled title="Delete group"><FontAwesomeIcon icon="trash" size="sm" /></button>
+                    <button className="linkEditor-button" disabled title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button>
+                </>
+            );
+        } else {
+            buttons = (
+                <>
+                    <button className="linkEditor-button" onClick={() => this.addMetadata(groupType)} title="Add KVP"><FontAwesomeIcon icon="plus" size="sm" /></button>
+                    <button className="linkEditor-button" onClick={() => this.copyGroup(groupType)} title="Copy group to opposite anchor"><FontAwesomeIcon icon="exchange-alt" size="sm" /></button>
+                    <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupType)} title="Remove group from link"><FontAwesomeIcon icon="times" size="sm" /></button>
+                    <button className="linkEditor-button" onClick={() => this.deleteGroup(groupType)} title="Delete group"><FontAwesomeIcon icon="trash" size="sm" /></button>
+                    {this.viewGroupAsTable(groupType)}
+                </>
+            );
+        }
+        return (
+            <div className="linkEditor-group">
+                <div className="linkEditor-group-row ">
+                    <p className="linkEditor-group-row-label">type:</p>
+                    <GroupTypesDropdown groupType={groupType} setGroupType={this.setGroupType} />
+                </div>
+                {this.renderMetadata().length > 0 ? <p className="linkEditor-group-row-label">metadata:</p> : <></>}
+                {this.renderMetadata()}
+                <div className="linkEditor-group-buttons">
+                    {buttons}
+                </div>
+            </div>
+        );
+    }
+}
+
+
+interface LinkEditorProps {
+    sourceDoc: Doc;
+    linkDoc: Doc;
+    showLinks: () => void;
+}
+@observer
+export class LinkEditor extends React.Component<LinkEditorProps> {
+
+    @action
+    deleteLink = (): void => {
+        LinkManager.Instance.deleteLink(this.props.linkDoc);
+        this.props.showLinks();
+    }
+
+    @action
+    addGroup = (): void => {
+        // create new metadata document for group
+        let mdDoc = new Doc();
+        mdDoc.anchor1 = this.props.sourceDoc.title;
+        let opp = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
+        if (opp) {
+            mdDoc.anchor2 = opp.title;
+        }
+
+        // create new group document
+        let groupDoc = new Doc();
+        groupDoc.type = "";
+        groupDoc.metadata = mdDoc;
+
+        LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, this.props.sourceDoc, groupDoc);
+    }
+
+    render() {
+        let destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
+
+        let groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc);
+        let groups = groupList.map(groupDoc => {
+            return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.type)} linkDoc={this.props.linkDoc} sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />;
+        });
+
+        if (destination) {
+            return (
+                <div className="linkEditor">
+                    <button className="linkEditor-back" onPointerDown={() => this.props.showLinks()}><FontAwesomeIcon icon="arrow-left" size="sm" /></button>
+                    <div className="linkEditor-info">
+                        <p className="linkEditor-linkedTo">editing link to: <b>{destination.proto!.title}</b></p>
+                        <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link"><FontAwesomeIcon icon="trash" size="sm" /></button>
+                    </div>
+                    <div className="linkEditor-groupsLabel">
+                        <b>Relationships:</b>
+                        <button className="linkEditor-button" onClick={() => this.addGroup()} title=" Add Group"><FontAwesomeIcon icon="plus" size="sm" /></button>
+                    </div>
+                    {groups.length > 0 ? groups : <div className="linkEditor-group">There are currently no relationships associated with this link.</div>}
+                </div>
+
+            );
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
new file mode 100644
index 000000000..487281d50
--- /dev/null
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -0,0 +1,9 @@
+import { observable, computed, action, trace } from "mobx";
+import React = require("react");
+import { observer } from "mobx-react";
+import { FieldViewProps } from "../nodes/FieldView";
+
+@observer
+export class LinkFollowBox extends React.Component<FieldViewProps> {
+
+}
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
new file mode 100644
index 000000000..a4018bd2d
--- /dev/null
+++ b/src/client/views/linking/LinkMenu.scss
@@ -0,0 +1,137 @@
+@import "../globalCssVariables";
+
+.linkMenu {
+    width: 100%;
+    height: auto;
+}
+
+.linkMenu-list {
+    max-height: 200px;
+    overflow-y: scroll;
+}
+
+.linkMenu-group {
+    border-bottom: 0.5px solid lightgray; 
+    padding: 5px 0;
+
+
+    &:last-child {
+        border-bottom: none;
+    }
+
+    .linkMenu-group-name {
+        display: flex;
+
+        &:hover {
+            p {
+                background-color: lightgray;
+            }
+            p.expand-one {
+                width: calc(100% - 26px);
+            }
+            .linkEditor-tableButton {
+                display: block;
+            }
+        }
+
+        p {
+            width: 100%;
+            padding: 4px 6px;
+            line-height: 12px;
+            border-radius: 5px;
+            font-weight: bold;
+        }
+
+        .linkEditor-tableButton {
+            display: none;
+        }
+    }
+}
+
+.linkMenu-item {
+    // border-top: 0.5px solid $main-accent; 
+    position: relative;
+    display: flex;
+    font-size: 12px;
+    
+
+    .link-name {
+        position: relative;
+
+        p {
+            padding: 4px 6px;
+            line-height: 12px;
+            border-radius: 5px;
+            overflow-wrap: break-word;
+        }
+    }
+
+    .linkMenu-item-content {
+        width: 100%;
+    }
+    
+    .link-metadata {
+        padding: 0 10px 0 16px;
+        margin-bottom: 4px;
+        color: $main-accent;
+        font-style: italic;
+        font-size: 10.5px;
+    }
+
+    &:hover {
+        .linkMenu-item-buttons {
+            display: flex;
+        }
+        .linkMenu-item-content {
+            &.expand-two p {
+                width: calc(100% - 52px);
+                background-color: lightgray;
+            }
+            &.expand-three p {
+                width: calc(100% - 84px);
+                background-color: lightgray;
+            }
+        }
+    }
+}
+
+.linkMenu-item-buttons {
+    display: none;
+    position: absolute;
+    top: 50%;
+    right: 0;
+    transform: translateY(-50%);
+
+    .button {
+        width: 20px;
+        height: 20px;
+        margin: 0;
+        margin-right: 6px;
+        border-radius: 50%;
+        cursor: pointer;
+        pointer-events: auto;
+        background-color: $dark-color;
+        color: $light-color;
+        font-size: 65%;
+        transition: transform 0.2s;
+        text-align: center;
+        position: relative;
+
+        .fa-icon {
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+        }
+
+        &:last-child {
+            margin-right: 0;
+        }
+        &:hover {
+            background: $main-accent;
+        }
+    }
+}
+
+
+
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
new file mode 100644
index 000000000..842ce45b1
--- /dev/null
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -0,0 +1,76 @@
+import { action, observable } from "mobx";
+import { observer } from "mobx-react";
+import { DocumentView } from "../nodes/DocumentView";
+import { LinkEditor } from "./LinkEditor";
+import './LinkMenu.scss';
+import React = require("react");
+import { Doc } from "../../../new_fields/Doc";
+import { LinkManager } from "../../util/LinkManager";
+import { LinkMenuGroup } from "./LinkMenuGroup";
+import { faTrash } from '@fortawesome/free-solid-svg-icons';
+import { library } from "@fortawesome/fontawesome-svg-core";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+library.add(faTrash);
+
+interface Props {
+    docView: DocumentView;
+    changeFlyout: () => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+}
+
+@observer
+export class LinkMenu extends React.Component<Props> {
+
+    @observable private _editingLink?: Doc;
+
+    @action
+    componentWillReceiveProps() {
+        this._editingLink = undefined;
+    }
+
+    clearAllLinks = () => {
+        LinkManager.Instance.deleteAllLinksOnAnchor(this.props.docView.props.Document);
+    }
+
+    renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => {
+        let linkItems: Array<JSX.Element> = [];
+        groups.forEach((group, groupType) => {
+            linkItems.push(
+                <LinkMenuGroup
+                    key={groupType}
+                    docView={this.props.docView}
+                    sourceDoc={this.props.docView.props.Document}
+                    group={group}
+                    groupType={groupType}
+                    showEditor={action((linkDoc: Doc) => this._editingLink = linkDoc)}
+                    addDocTab={this.props.addDocTab} />
+            );
+        });
+
+        // if source doc has no links push message
+        if (linkItems.length === 0) linkItems.push(<p key="">No links have been created yet. Drag the linking button onto another document to create a link.</p>);
+
+        return linkItems;
+    }
+
+    render() {
+        let sourceDoc = this.props.docView.props.Document;
+        let groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc);
+        if (this._editingLink === undefined) {
+            return (
+                <div className="linkMenu">
+                    <button className="linkEditor-button linkEditor-clearButton" onClick={() => this.clearAllLinks()} title="Clear all links"><FontAwesomeIcon icon="trash" size="sm" /></button>
+                    {/* <input id="linkMenu-searchBar" type="text" placeholder="Search..."></input> */}
+                    <div className="linkMenu-list">
+                        {this.renderAllGroups(groups)}
+                    </div>
+                </div>
+            );
+        } else {
+            return (
+                <LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink} showLinks={action(() => this._editingLink = undefined)}></LinkEditor>
+            );
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
new file mode 100644
index 000000000..b6a24b0c8
--- /dev/null
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -0,0 +1,111 @@
+import { action, observable } from "mobx";
+import { observer } from "mobx-react";
+import { DocumentView } from "../nodes/DocumentView";
+import { LinkMenuItem } from "./LinkMenuItem";
+import { LinkEditor } from "./LinkEditor";
+import './LinkMenu.scss';
+import React = require("react");
+import { Doc, DocListCast } from "../../../new_fields/Doc";
+import { Id } from "../../../new_fields/FieldSymbols";
+import { LinkManager } from "../../util/LinkManager";
+import { DragLinksAsDocuments, DragManager, SetupDrag } from "../../util/DragManager";
+import { emptyFunction } from "../../../Utils";
+import { Docs } from "../../documents/Documents";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { UndoManager } from "../../util/UndoManager";
+import { StrCast } from "../../../new_fields/Types";
+import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
+
+interface LinkMenuGroupProps {
+    sourceDoc: Doc;
+    group: Doc[];
+    groupType: string;
+    showEditor: (linkDoc: Doc) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    docView: DocumentView;
+
+}
+
+@observer
+export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
+
+    private _drag = React.createRef<HTMLDivElement>();
+    private _table = React.createRef<HTMLDivElement>();
+
+    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) => {
+        UndoManager.RunInBatch(() => {
+            if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) {
+                document.removeEventListener("pointermove", this.onLinkButtonMoved);
+                document.removeEventListener("pointerup", this.onLinkButtonUp);
+
+                let draggedDocs = this.props.group.map(linkDoc => {
+                    let opp = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
+                    if (opp) return opp;
+                }) as Doc[];
+                let dragData = new DragManager.DocumentDragData(draggedDocs, draggedDocs.map(d => undefined));
+
+                DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, {
+                    handlers: {
+                        dragComplete: action(emptyFunction),
+                    },
+                    hideSource: false
+                });
+            }
+        }, "drag links");
+        e.stopPropagation();
+    }
+
+    viewGroupAsTable = (groupType: string): JSX.Element => {
+        let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+        let index = keys.indexOf("");
+        if (index > -1) keys.splice(index, 1);
+        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
+        let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
+        let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
+        let ref = React.createRef<HTMLDivElement>();
+        return <div ref={ref}><button className="linkEditor-button linkEditor-tableButton" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>;
+    }
+
+    render() {
+        let groupItems = this.props.group.map(linkDoc => {
+            let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
+            if (destination && this.props.sourceDoc) {
+                return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]}
+                    groupType={this.props.groupType}
+                    addDocTab={this.props.addDocTab}
+                    linkDoc={linkDoc}
+                    sourceDoc={this.props.sourceDoc}
+                    destinationDoc={destination}
+                    showEditor={this.props.showEditor} />;
+            }
+        });
+
+        return (
+            <div className="linkMenu-group">
+                <div className="linkMenu-group-name">
+                    <p ref={this._drag} onPointerDown={this.onLinkButtonDown}
+                        className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p>
+                    {this.props.groupType === "*" || this.props.groupType === "" ? <></> : this.viewGroupAsTable(this.props.groupType)}
+                </div>
+                <div className="linkMenu-group-wrapper">
+                    {groupItems}
+                </div>
+            </div >
+        );
+    }
+}
\ No newline at end of file
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
diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss
deleted file mode 100644
index fc5f2410c..000000000
--- a/src/client/views/nodes/LinkEditor.scss
+++ /dev/null
@@ -1,145 +0,0 @@
-@import "../globalCssVariables";
-
-.linkEditor {
-    width: 100%;
-    height: auto;
-    font-size: 12px; // TODO
-}
-
-.linkEditor-back {
-    margin-bottom: 6px;
-}
-
-.linkEditor-info {
-    border-bottom: 0.5px solid $light-color-secondary; 
-    padding-bottom: 6px;
-    margin-bottom: 6px;
-    display: flex;
-    justify-content: space-between;
-
-    .linkEditor-linkedTo {
-        width: calc(100% - 26px);
-    }
-}
-
-.linkEditor-button {
-    width: 20px;
-    height: 20px;
-    margin-left: 6px;
-    padding: 0;
-    // font-size: 12px;
-    border-radius: 10px;
-
-    &:disabled {
-        background-color: gray;
-    }
-}
-
-.linkEditor-groupsLabel {
-    display: flex;
-    justify-content: space-between;
-}
-
-.linkEditor-group {
-    background-color: $light-color-secondary; 
-    padding: 6px;
-    margin: 3px 0;
-    border-radius: 3px;
-
-    .linkEditor-group-row {
-        display: flex;
-        margin-bottom: 3px;
-
-        .linkEditor-group-row-label {
-            margin-right: 6px;
-        }
-    }
-
-    .linkEditor-metadata-row {
-        display: flex;
-        justify-content: space-between;
-        margin-bottom: 6px;
-
-        .linkEditor-error {
-            border-color: red;
-        }
-
-        input {
-            width: calc(50% - 16px);
-            height: 20px;
-        }
-
-        button {
-            width: 20px;
-            height: 20px;
-            margin-left: 3px;
-            padding: 0;
-            font-size: 10px;
-        }
-    }
-}
-
-
-.linkEditor-dropdown {
-    width: 100%;
-    position: relative;
-    z-index: 999;
-
-    input {
-        width: 100%;
-    }
-
-    .linkEditor-options-wrapper {
-        width: 100%;
-        position: absolute;
-        top: 19px;
-        left: 0;
-        display: flex;
-        flex-direction: column;
-    }
-
-    .linkEditor-option {
-        background-color: $light-color-secondary;
-        border: 1px solid $intermediate-color;
-        border-top: 0;
-        padding: 3px;
-        cursor: pointer;
-
-        &:hover {
-            background-color: lightgray;
-        }
-
-        &.onDown {
-            background-color: gray;
-        }
-    }
-}
-
-.linkEditor-typeButton {
-    background-color: transparent;
-    color: $dark-color;
-    width: 100%;
-    height: 20px;
-    padding: 0 3px;
-    padding-bottom: 2px;
-    text-align: left;
-    text-transform: none;
-    letter-spacing: normal;
-    font-size: 12px;
-    font-weight: bold;
-
-    &:hover {
-        background-color: $light-color;
-    }
-}
-
-.linkEditor-group-buttons {
-    height: 20px;
-    display: flex;
-    justify-content: flex-end;
-    margin-top: 5px;
-
-    .linkEditor-button {
-        margin-left: 6px;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx
deleted file mode 100644
index ecb3e9db4..000000000
--- a/src/client/views/nodes/LinkEditor.tsx
+++ /dev/null
@@ -1,400 +0,0 @@
-import { observable, computed, action, trace } from "mobx";
-import React = require("react");
-import { observer } from "mobx-react";
-import './LinkEditor.scss';
-import { StrCast, Cast, FieldValue } from "../../../new_fields/Types";
-import { Doc } from "../../../new_fields/Doc";
-import { LinkManager } from "../../util/LinkManager";
-import { Docs } from "../../documents/Documents";
-import { Utils } from "../../../Utils";
-import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus } from '@fortawesome/free-solid-svg-icons';
-import { library } from "@fortawesome/fontawesome-svg-core";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { SetupDrag } from "../../util/DragManager";
-import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
-
-library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus);
-
-
-interface GroupTypesDropdownProps {
-    groupType: string;
-    setGroupType: (group: string) => void;
-}
-// this dropdown could be generalized
-@observer
-class GroupTypesDropdown extends React.Component<GroupTypesDropdownProps> {
-    @observable private _searchTerm: string = this.props.groupType;
-    @observable private _groupType: string = this.props.groupType;
-    @observable private _isEditing: boolean = false;
-
-    @action
-    createGroup = (groupType: string): void => {
-        this.props.setGroupType(groupType);
-        LinkManager.Instance.addGroupType(groupType);
-    }
-
-    @action
-    onChange = (val: string): void => {
-        this._searchTerm = val;
-        this._groupType = val;
-        this._isEditing = true;
-    }
-
-    @action
-    onKeyDown = (e: React.KeyboardEvent): void => {
-        if (e.key === "Enter") {
-            let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes());
-            let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
-            let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase());
-
-            if (exactFound > -1) {
-                let groupType = groupOptions[exactFound];
-                this.props.setGroupType(groupType);
-                this._groupType = groupType;
-            } else {
-                this.createGroup(this._searchTerm);
-                this._groupType = this._searchTerm;
-            }
-
-            this._searchTerm = this._groupType;
-            this._isEditing = false;
-        }
-    }
-
-    @action
-    onOptionClick = (value: string, createNew: boolean): void => {
-        if (createNew) {
-            this.createGroup(this._searchTerm);
-            this._groupType = this._searchTerm;
-
-        } else {
-            this.props.setGroupType(value);
-            this._groupType = value;
-
-        }
-        this._searchTerm = this._groupType;
-        this._isEditing = false;
-    }
-
-    @action
-    onButtonPointerDown = (): void => {
-        this._isEditing = true;
-    }
-
-    renderOptions = (): JSX.Element[] | JSX.Element => {
-        if (this._searchTerm === "") return <></>;
-
-        let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes());
-        let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
-        let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()) > -1;
-
-        let options = groupOptions.map(groupType => {
-            let ref = React.createRef<HTMLDivElement>();
-            return <div key={groupType} ref={ref} className="linkEditor-option"
-                onClick={() => this.onOptionClick(groupType, false)}>{groupType}</div>;
-        });
-
-        // if search term does not already exist as a group type, give option to create new group type
-        if (!exactFound && this._searchTerm !== "") {
-            let ref = React.createRef<HTMLDivElement>();
-            options.push(<div key={""} ref={ref} className="linkEditor-option"
-                onClick={() => this.onOptionClick(this._searchTerm, true)}>Define new "{this._searchTerm}" relationship</div>);
-        }
-
-        return options;
-    }
-
-    render() {
-        if (this._isEditing || this._groupType === "") {
-            return (
-                <div className="linkEditor-dropdown">
-                    <input type="text" value={this._groupType} placeholder="Search for or create a new group"
-                        onChange={e => this.onChange(e.target.value)} onKeyDown={this.onKeyDown} autoFocus></input>
-                    <div className="linkEditor-options-wrapper">
-                        {this.renderOptions()}
-                    </div>
-                </div >
-            );
-        } else {
-            return <button className="linkEditor-typeButton" onClick={() => this.onButtonPointerDown()}>{this._groupType}</button>;
-        }
-    }
-}
-
-
-interface LinkMetadataEditorProps {
-    id: string;
-    groupType: string;
-    mdDoc: Doc;
-    mdKey: string;
-    mdValue: string;
-    changeMdIdKey: (id: string, newKey: string) => void;
-}
-@observer
-class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
-    @observable private _key: string = this.props.mdKey;
-    @observable private _value: string = this.props.mdValue;
-    @observable private _keyError: boolean = false;
-
-    @action
-    setMetadataKey = (value: string): void => {
-        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);
-
-        // don't allow user to create existing key
-        let newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase());
-        if (newIndex > -1) {
-            this._keyError = true;
-            this._key = value;
-            return;
-        } else {
-            this._keyError = false;
-        }
-
-        // set new value for key
-        let currIndex = groupMdKeys.findIndex(key => {
-            return StrCast(key).toUpperCase() === this._key.toUpperCase();
-        });
-        if (currIndex === -1) console.error("LinkMetadataEditor: key was not found");
-        groupMdKeys[currIndex] = value;
-
-        this.props.changeMdIdKey(this.props.id, value);
-        this._key = value;
-        LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, [...groupMdKeys]);
-    }
-
-    @action
-    setMetadataValue = (value: string): void => {
-        if (!this._keyError) {
-            this._value = value;
-            this.props.mdDoc[this._key] = value;
-        }
-    }
-
-    @action
-    removeMetadata = (): void => {
-        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);
-
-        let index = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase());
-        if (index === -1) console.error("LinkMetadataEditor: key was not found");
-        groupMdKeys.splice(index, 1);
-
-        LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, groupMdKeys);
-        this._key = "";
-    }
-
-    render() {
-        return (
-            <div className="linkEditor-metadata-row">
-                <input className={this._keyError ? "linkEditor-error" : ""} type="text" value={this._key === "new key" ? "" : this._key} placeholder="key" onChange={e => this.setMetadataKey(e.target.value)}></input>:
-                <input type="text" value={this._value} placeholder="value" onChange={e => this.setMetadataValue(e.target.value)}></input>
-                <button onClick={() => this.removeMetadata()}><FontAwesomeIcon icon="times" size="sm" /></button>
-            </div>
-        );
-    }
-}
-
-interface LinkGroupEditorProps {
-    sourceDoc: Doc;
-    linkDoc: Doc;
-    groupDoc: Doc;
-}
-@observer
-export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
-
-    private _metadataIds: Map<string, string> = new Map();
-
-    constructor(props: LinkGroupEditorProps) {
-        super(props);
-
-        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.type));
-        groupMdKeys.forEach(key => {
-            this._metadataIds.set(key, Utils.GenerateGuid());
-        });
-    }
-
-    @action
-    setGroupType = (groupType: string): void => {
-        this.props.groupDoc.type = groupType;
-    }
-
-    removeGroupFromLink = (groupType: string): void => {
-        LinkManager.Instance.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType);
-    }
-
-    deleteGroup = (groupType: string): void => {
-        LinkManager.Instance.deleteGroupType(groupType);
-    }
-
-    copyGroup = async (groupType: string): Promise<void> => {
-        let sourceGroupDoc = this.props.groupDoc;
-        const sourceMdDoc = await Cast(sourceGroupDoc.metadata, Doc);
-        if (!sourceMdDoc) return;
-
-        let destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
-        // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc);
-        let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
-
-        // create new metadata doc with copied kvp
-        let destMdDoc = new Doc();
-        destMdDoc.anchor1 = StrCast(sourceMdDoc.anchor2);
-        destMdDoc.anchor2 = StrCast(sourceMdDoc.anchor1);
-        keys.forEach(key => {
-            let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]);
-            destMdDoc[key] = val;
-        });
-
-        // create new group doc with new metadata doc
-        let destGroupDoc = new Doc();
-        destGroupDoc.type = groupType;
-        destGroupDoc.metadata = destMdDoc;
-
-        if (destDoc) {
-            LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, destDoc, destGroupDoc, true);
-        }
-    }
-
-    @action
-    addMetadata = (groupType: string): void => {
-        this._metadataIds.set("new key", Utils.GenerateGuid());
-        let mdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
-        // only add "new key" if there is no other key with value "new key"; prevents spamming
-        if (mdKeys.indexOf("new key") === -1) mdKeys.push("new key");
-        LinkManager.Instance.setMetadataKeysForGroup(groupType, mdKeys);
-    }
-
-    // for key rendering purposes
-    changeMdIdKey = (id: string, newKey: string) => {
-        this._metadataIds.set(newKey, id);
-    }
-
-    renderMetadata = (): JSX.Element[] => {
-        let metadata: Array<JSX.Element> = [];
-        let groupDoc = this.props.groupDoc;
-        const mdDoc = FieldValue(Cast(groupDoc.metadata, Doc));
-        if (!mdDoc) {
-            return [];
-        }
-        let groupType = StrCast(groupDoc.type);
-        let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
-
-        groupMdKeys.forEach((key) => {
-            let val = StrCast(mdDoc[key]);
-            metadata.push(
-                <LinkMetadataEditor key={"mded-" + this._metadataIds.get(key)} id={this._metadataIds.get(key)!} groupType={groupType} mdDoc={mdDoc} mdKey={key} mdValue={val} changeMdIdKey={this.changeMdIdKey} />
-            );
-        });
-        return metadata;
-    }
-
-    viewGroupAsTable = (groupType: string): JSX.Element => {
-        let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
-        let index = keys.indexOf("");
-        if (index > -1) keys.splice(index, 1);
-        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
-        let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
-        let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
-        let ref = React.createRef<HTMLDivElement>();
-        return <div ref={ref}><button className="linkEditor-button" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>;
-    }
-
-    render() {
-        let groupType = StrCast(this.props.groupDoc.type);
-        // if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") {
-        let buttons;
-        if (groupType === "") {
-            buttons = (
-                <>
-                    <button className="linkEditor-button" disabled={true} title="Add KVP"><FontAwesomeIcon icon="plus" size="sm" /></button>
-                    <button className="linkEditor-button" disabled title="Copy group to opposite anchor"><FontAwesomeIcon icon="exchange-alt" size="sm" /></button>
-                    <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupType)} title="Remove group from link"><FontAwesomeIcon icon="times" size="sm" /></button>
-                    <button className="linkEditor-button" disabled title="Delete group"><FontAwesomeIcon icon="trash" size="sm" /></button>
-                    <button className="linkEditor-button" disabled title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button>
-                </>
-            );
-        } else {
-            buttons = (
-                <>
-                    <button className="linkEditor-button" onClick={() => this.addMetadata(groupType)} title="Add KVP"><FontAwesomeIcon icon="plus" size="sm" /></button>
-                    <button className="linkEditor-button" onClick={() => this.copyGroup(groupType)} title="Copy group to opposite anchor"><FontAwesomeIcon icon="exchange-alt" size="sm" /></button>
-                    <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupType)} title="Remove group from link"><FontAwesomeIcon icon="times" size="sm" /></button>
-                    <button className="linkEditor-button" onClick={() => this.deleteGroup(groupType)} title="Delete group"><FontAwesomeIcon icon="trash" size="sm" /></button>
-                    {this.viewGroupAsTable(groupType)}
-                </>
-            );
-        }
-        return (
-            <div className="linkEditor-group">
-                <div className="linkEditor-group-row ">
-                    <p className="linkEditor-group-row-label">type:</p>
-                    <GroupTypesDropdown groupType={groupType} setGroupType={this.setGroupType} />
-                </div>
-                {this.renderMetadata().length > 0 ? <p className="linkEditor-group-row-label">metadata:</p> : <></>}
-                {this.renderMetadata()}
-                <div className="linkEditor-group-buttons">
-                    {buttons}
-                </div>
-            </div>
-        );
-    }
-}
-
-
-interface LinkEditorProps {
-    sourceDoc: Doc;
-    linkDoc: Doc;
-    showLinks: () => void;
-}
-@observer
-export class LinkEditor extends React.Component<LinkEditorProps> {
-
-    @action
-    deleteLink = (): void => {
-        LinkManager.Instance.deleteLink(this.props.linkDoc);
-        this.props.showLinks();
-    }
-
-    @action
-    addGroup = (): void => {
-        // create new metadata document for group
-        let mdDoc = new Doc();
-        mdDoc.anchor1 = this.props.sourceDoc.title;
-        let opp = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
-        if (opp) {
-            mdDoc.anchor2 = opp.title;
-        }
-
-        // create new group document
-        let groupDoc = new Doc();
-        groupDoc.type = "";
-        groupDoc.metadata = mdDoc;
-
-        LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, this.props.sourceDoc, groupDoc);
-    }
-
-    render() {
-        let destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
-
-        let groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc);
-        let groups = groupList.map(groupDoc => {
-            return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.type)} linkDoc={this.props.linkDoc} sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />;
-        });
-
-        if (destination) {
-            return (
-                <div className="linkEditor">
-                    <button className="linkEditor-back" onPointerDown={() => this.props.showLinks()}><FontAwesomeIcon icon="arrow-left" size="sm" /></button>
-                    <div className="linkEditor-info">
-                        <p className="linkEditor-linkedTo">editing link to: <b>{destination.proto!.title}</b></p>
-                        <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link"><FontAwesomeIcon icon="trash" size="sm" /></button>
-                    </div>
-                    <div className="linkEditor-groupsLabel">
-                        <b>Relationships:</b>
-                        <button className="linkEditor-button" onClick={() => this.addGroup()} title=" Add Group"><FontAwesomeIcon icon="plus" size="sm" /></button>
-                    </div>
-                    {groups.length > 0 ? groups : <div className="linkEditor-group">There are currently no relationships associated with this link.</div>}
-                </div>
-
-            );
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss
deleted file mode 100644
index a4018bd2d..000000000
--- a/src/client/views/nodes/LinkMenu.scss
+++ /dev/null
@@ -1,137 +0,0 @@
-@import "../globalCssVariables";
-
-.linkMenu {
-    width: 100%;
-    height: auto;
-}
-
-.linkMenu-list {
-    max-height: 200px;
-    overflow-y: scroll;
-}
-
-.linkMenu-group {
-    border-bottom: 0.5px solid lightgray; 
-    padding: 5px 0;
-
-
-    &:last-child {
-        border-bottom: none;
-    }
-
-    .linkMenu-group-name {
-        display: flex;
-
-        &:hover {
-            p {
-                background-color: lightgray;
-            }
-            p.expand-one {
-                width: calc(100% - 26px);
-            }
-            .linkEditor-tableButton {
-                display: block;
-            }
-        }
-
-        p {
-            width: 100%;
-            padding: 4px 6px;
-            line-height: 12px;
-            border-radius: 5px;
-            font-weight: bold;
-        }
-
-        .linkEditor-tableButton {
-            display: none;
-        }
-    }
-}
-
-.linkMenu-item {
-    // border-top: 0.5px solid $main-accent; 
-    position: relative;
-    display: flex;
-    font-size: 12px;
-    
-
-    .link-name {
-        position: relative;
-
-        p {
-            padding: 4px 6px;
-            line-height: 12px;
-            border-radius: 5px;
-            overflow-wrap: break-word;
-        }
-    }
-
-    .linkMenu-item-content {
-        width: 100%;
-    }
-    
-    .link-metadata {
-        padding: 0 10px 0 16px;
-        margin-bottom: 4px;
-        color: $main-accent;
-        font-style: italic;
-        font-size: 10.5px;
-    }
-
-    &:hover {
-        .linkMenu-item-buttons {
-            display: flex;
-        }
-        .linkMenu-item-content {
-            &.expand-two p {
-                width: calc(100% - 52px);
-                background-color: lightgray;
-            }
-            &.expand-three p {
-                width: calc(100% - 84px);
-                background-color: lightgray;
-            }
-        }
-    }
-}
-
-.linkMenu-item-buttons {
-    display: none;
-    position: absolute;
-    top: 50%;
-    right: 0;
-    transform: translateY(-50%);
-
-    .button {
-        width: 20px;
-        height: 20px;
-        margin: 0;
-        margin-right: 6px;
-        border-radius: 50%;
-        cursor: pointer;
-        pointer-events: auto;
-        background-color: $dark-color;
-        color: $light-color;
-        font-size: 65%;
-        transition: transform 0.2s;
-        text-align: center;
-        position: relative;
-
-        .fa-icon {
-            position: absolute;
-            top: 50%;
-            left: 50%;
-            transform: translate(-50%, -50%);
-        }
-
-        &:last-child {
-            margin-right: 0;
-        }
-        &:hover {
-            background: $main-accent;
-        }
-    }
-}
-
-
-
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
deleted file mode 100644
index 16e318f7a..000000000
--- a/src/client/views/nodes/LinkMenu.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import { action, observable } from "mobx";
-import { observer } from "mobx-react";
-import { DocumentView } from "./DocumentView";
-import { LinkEditor } from "./LinkEditor";
-import './LinkMenu.scss';
-import React = require("react");
-import { Doc } from "../../../new_fields/Doc";
-import { LinkManager } from "../../util/LinkManager";
-import { LinkMenuGroup } from "./LinkMenuGroup";
-import { faTrash } from '@fortawesome/free-solid-svg-icons';
-import { library } from "@fortawesome/fontawesome-svg-core";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-
-library.add(faTrash);
-
-interface Props {
-    docView: DocumentView;
-    changeFlyout: () => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
-}
-
-@observer
-export class LinkMenu extends React.Component<Props> {
-
-    @observable private _editingLink?: Doc;
-
-    @action
-    componentWillReceiveProps() {
-        this._editingLink = undefined;
-    }
-
-    clearAllLinks = () => {
-        LinkManager.Instance.deleteAllLinksOnAnchor(this.props.docView.props.Document);
-    }
-
-    renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => {
-        let linkItems: Array<JSX.Element> = [];
-        groups.forEach((group, groupType) => {
-            linkItems.push(
-                <LinkMenuGroup
-                    key={groupType}
-                    docView={this.props.docView}
-                    sourceDoc={this.props.docView.props.Document}
-                    group={group}
-                    groupType={groupType}
-                    showEditor={action((linkDoc: Doc) => this._editingLink = linkDoc)}
-                    addDocTab={this.props.addDocTab} />
-            );
-        });
-
-        // if source doc has no links push message
-        if (linkItems.length === 0) linkItems.push(<p key="">No links have been created yet. Drag the linking button onto another document to create a link.</p>);
-
-        return linkItems;
-    }
-
-    render() {
-        let sourceDoc = this.props.docView.props.Document;
-        let groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc);
-        if (this._editingLink === undefined) {
-            return (
-                <div className="linkMenu">
-                    <button className="linkEditor-button linkEditor-clearButton" onClick={() => this.clearAllLinks()} title="Clear all links"><FontAwesomeIcon icon="trash" size="sm" /></button>
-                    {/* <input id="linkMenu-searchBar" type="text" placeholder="Search..."></input> */}
-                    <div className="linkMenu-list">
-                        {this.renderAllGroups(groups)}
-                    </div>
-                </div>
-            );
-        } else {
-            return (
-                <LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink} showLinks={action(() => this._editingLink = undefined)}></LinkEditor>
-            );
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx
deleted file mode 100644
index aa23d80a1..000000000
--- a/src/client/views/nodes/LinkMenuGroup.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import { action, observable } from "mobx";
-import { observer } from "mobx-react";
-import { DocumentView } from "./DocumentView";
-import { LinkMenuItem } from "./LinkMenuItem";
-import { LinkEditor } from "./LinkEditor";
-import './LinkMenu.scss';
-import React = require("react");
-import { Doc, DocListCast } from "../../../new_fields/Doc";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { LinkManager } from "../../util/LinkManager";
-import { DragLinksAsDocuments, DragManager, SetupDrag } from "../../util/DragManager";
-import { emptyFunction } from "../../../Utils";
-import { Docs } from "../../documents/Documents";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { UndoManager } from "../../util/UndoManager";
-import { StrCast } from "../../../new_fields/Types";
-import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
-
-interface LinkMenuGroupProps {
-    sourceDoc: Doc;
-    group: Doc[];
-    groupType: string;
-    showEditor: (linkDoc: Doc) => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
-    docView: DocumentView;
-
-}
-
-@observer
-export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
-
-    private _drag = React.createRef<HTMLDivElement>();
-    private _table = React.createRef<HTMLDivElement>();
-
-    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) => {
-        UndoManager.RunInBatch(() => {
-            if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) {
-                document.removeEventListener("pointermove", this.onLinkButtonMoved);
-                document.removeEventListener("pointerup", this.onLinkButtonUp);
-
-                let draggedDocs = this.props.group.map(linkDoc => {
-                    let opp = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
-                    if (opp) return opp;
-                }) as Doc[];
-                let dragData = new DragManager.DocumentDragData(draggedDocs, draggedDocs.map(d => undefined));
-
-                DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, {
-                    handlers: {
-                        dragComplete: action(emptyFunction),
-                    },
-                    hideSource: false
-                });
-            }
-        }, "drag links");
-        e.stopPropagation();
-    }
-
-    viewGroupAsTable = (groupType: string): JSX.Element => {
-        let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
-        let index = keys.indexOf("");
-        if (index > -1) keys.splice(index, 1);
-        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
-        let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
-        let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
-        let ref = React.createRef<HTMLDivElement>();
-        return <div ref={ref}><button className="linkEditor-button linkEditor-tableButton" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>;
-    }
-
-    render() {
-        let groupItems = this.props.group.map(linkDoc => {
-            let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
-            if (destination && this.props.sourceDoc) {
-                return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]}
-                    groupType={this.props.groupType}
-                    addDocTab={this.props.addDocTab}
-                    linkDoc={linkDoc}
-                    sourceDoc={this.props.sourceDoc}
-                    destinationDoc={destination}
-                    showEditor={this.props.showEditor} />;
-            }
-        });
-
-        return (
-            <div className="linkMenu-group">
-                <div className="linkMenu-group-name">
-                    <p ref={this._drag} onPointerDown={this.onLinkButtonDown}
-                        className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p>
-                    {this.props.groupType === "*" || this.props.groupType === "" ? <></> : this.viewGroupAsTable(this.props.groupType)}
-                </div>
-                <div className="linkMenu-group-wrapper">
-                    {groupItems}
-                </div>
-            </div >
-        );
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx
deleted file mode 100644
index 9349dbbac..000000000
--- a/src/client/views/nodes/LinkMenuItem.tsx
+++ /dev/null
@@ -1,282 +0,0 @@
-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 './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
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 173de64de..1b54472e5 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -23,7 +23,7 @@ import { library } from "@fortawesome/fontawesome-svg-core";
 import { Docs } from "../../documents/Documents";
 import { PreviewCursor } from "../PreviewCursor";
 
-library.add(faStickyNote)
+library.add(faStickyNote);
 
 @observer
 export class WebBox extends React.Component<FieldViewProps> {
@@ -76,7 +76,6 @@ export class WebBox extends React.Component<FieldViewProps> {
     }
 
     switchToText() {
-        console.log("switchng to text")
         if (this.props.removeDocument) this.props.removeDocument(this.props.Document);
         // let newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]);
         let newBox = Docs.Create.TextDocument({
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 508655605..de45aad02 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -29,7 +29,7 @@ export class CurrentUserUtils {
         doc.viewType = CollectionViewType.Tree;
         doc.dropAction = "alias";
         doc.layout = CollectionView.LayoutString();
-        doc.title = Doc.CurrentUserEmail
+        doc.title = Doc.CurrentUserEmail;
         this.updateUserDocument(doc);
         doc.data = new List<Doc>();
         doc.gridGap = 5;
-- 
cgit v1.2.3-70-g09d2

