From 61aa3a0a34a647a7f414fbeb72345675a5154433 Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Mon, 18 Feb 2019 18:18:53 -0500
Subject: title

---
 src/client/views/DocumentDecorations.tsx | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7efaa5533..3e674e5ae 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -4,6 +4,7 @@ import { SelectionManager } from "../util/SelectionManager";
 import { observer } from "mobx-react";
 import './DocumentDecorations.scss'
 import { CollectionFreeFormView } from "./collections/CollectionFreeFormView";
+import ContentEditable from 'react-contenteditable'
 
 @observer
 export class DocumentDecorations extends React.Component {
@@ -14,10 +15,14 @@ export class DocumentDecorations extends React.Component {
 
     constructor(props: Readonly<{}>) {
         super(props)
-
         DocumentDecorations.Instance = this
+        this.state = { html: "hi" };
     }
 
+    // handleChange = evt => {
+    //     this.setState({ html: evt.target.value });
+    // };
+
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
         return SelectionManager.SelectedDocuments().reduce((bounds, element) => {
@@ -47,6 +52,7 @@ export class DocumentDecorations extends React.Component {
         e.stopPropagation();
         if (e.button === 0) {
             this._isPointerDown = true;
+            console.log("Pointer down");
             this._resizer = e.currentTarget.id;
             document.removeEventListener("pointermove", this.onPointerMove);
             document.addEventListener("pointermove", this.onPointerMove);
@@ -133,12 +139,14 @@ export class DocumentDecorations extends React.Component {
         var bounds = this.Bounds;
         return (
             <div id="documentDecorations-container" style={{
-                width: (bounds.r - bounds.x + 40) + "px",
-                height: (bounds.b - bounds.y + 40) + "px",
+                width: (bounds.r - bounds.x + 20 + 20) + "px",
+                height: (bounds.b - bounds.y + 40 + 20) + "px",
                 left: bounds.x - 20,
-                top: bounds.y - 20,
+                top: bounds.y - 20 - 20,
                 opacity: this.opacity
             }}>
+                {/*<input className="title" name="dynbox" value="hey" onPointerDown={this.onPointerDown} />*/}
+                <div className="title" onPointerDown={this.onPointerDown}>{document.title}</div>
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
@@ -148,7 +156,6 @@ export class DocumentDecorations extends React.Component {
                 <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-
             </div>
         )
     }
-- 
cgit v1.2.3-70-g09d2


From 2886c2859bfc6ad396fc4bab3e90cf18da5442f1 Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Mon, 18 Feb 2019 19:01:17 -0500
Subject: input title

---
 src/client/views/DocumentDecorations.scss |  2 +-
 src/client/views/DocumentDecorations.tsx  | 15 ++++++++-------
 2 files changed, 9 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 5c99c52ea..9bafbda44 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -33,6 +33,6 @@
         background: lightblue;
         grid-column-start:1;
         grid-column-end: 4;
-        cursor: ne-resize;
+        pointer-events: auto;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index dcfedfcd1..b44e32c52 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -8,7 +8,7 @@ import ContentEditable from 'react-contenteditable'
 import { KeyStore } from '../../fields/Key'
 
 @observer
-export class DocumentDecorations extends React.Component {
+export class DocumentDecorations extends React.Component<{}, { value: string }> {
     static Instance: DocumentDecorations
     private _resizer = ""
     private _isPointerDown = false;
@@ -17,12 +17,13 @@ export class DocumentDecorations extends React.Component {
     constructor(props: Readonly<{}>) {
         super(props)
         DocumentDecorations.Instance = this
-        this.state = { html: "hi" };
+        this.state = { value: document.title };
+        this.handleChange = this.handleChange.bind(this);
     }
 
-    // handleChange = evt => {
-    //     this.setState({ html: evt.target.value });
-    // };
+    handleChange(event: any) {
+        this.setState({ value: event.target.value });
+    };
 
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
@@ -146,8 +147,8 @@ export class DocumentDecorations extends React.Component {
                 top: bounds.y - 20 - 20,
                 opacity: this.opacity
             }}>
-                {/*<input className="title" name="dynbox" value="hey" onPointerDown={this.onPointerDown} />*/}
-                <div className="title" onPointerDown={this.onPointerDown}>{document.title}</div>
+                <input className="title" type="text" name="dynbox" value={this.state.value} onChange={this.handleChange} onPointerDown={this.onPointerDown} />
+                {/* <div className="title" onPointerDown={this.onPointerDown}>{document.title}</div> */}
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-- 
cgit v1.2.3-70-g09d2


From 12d20ab1b9b843d816bde445d9b67b3aa6abc6ae Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Tue, 19 Feb 2019 18:17:17 -0500
Subject: reference created

---
 src/client/views/DocumentDecorations.tsx | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b44e32c52..4f16453df 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -13,18 +13,34 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     private _resizer = ""
     private _isPointerDown = false;
     @observable private _opacity = 1;
+    private keyinput: React.RefObject<HTMLInputElement>;
 
     constructor(props: Readonly<{}>) {
         super(props)
         DocumentDecorations.Instance = this
         this.state = { value: document.title };
         this.handleChange = this.handleChange.bind(this);
+        this.keyinput = React.createRef();
     }
 
     handleChange(event: any) {
         this.setState({ value: event.target.value });
+        console.log("Input box has changed")
     };
 
+    enterPressed(e: any) {
+        var key = e.keyCode || e.which;
+        // enter pressed
+        if (key == 13) {
+            var text = e.target.value;
+            if (text[0] == '#') {
+                console.log("hashtag");
+                // TODO: Change field with switch statement
+            }
+            e.target.blur();
+        }
+    }
+
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
         return SelectionManager.SelectedDocuments().reduce((bounds, element) => {
@@ -147,7 +163,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 top: bounds.y - 20 - 20,
                 opacity: this.opacity
             }}>
-                <input className="title" type="text" name="dynbox" value={this.state.value} onChange={this.handleChange} onPointerDown={this.onPointerDown} />
+                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.state.value} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
                 {/* <div className="title" onPointerDown={this.onPointerDown}>{document.title}</div> */}
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-- 
cgit v1.2.3-70-g09d2


From 381b008c9f860265c0a160104252eee76057bd6b Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Sat, 9 Mar 2019 16:09:57 -0500
Subject: stage

---
 src/client/views/DocumentDecorations.tsx | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 0a126de1f..280fad2e5 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -184,12 +184,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 width: (bounds.r - bounds.x + 20 + 20) + "px",
                 height: (bounds.b - bounds.y + 40 + 20) + "px",
                 left: bounds.x - 20,
-<<<<<<< HEAD
                 top: bounds.y - 20 - 20,
-                opacity: this.opacity
-=======
-                top: bounds.y - 20,
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
+                opacity: this._opacity
             }}>
                 <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.state.value} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
                 {/* <div className="title" onPointerDown={this.onPointerDown}>{document.title}</div> */}
-- 
cgit v1.2.3-70-g09d2


From 70676c2456f7f330869d6009b52456aba10e7e97 Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Sat, 9 Mar 2019 16:17:34 -0500
Subject: idk

---
 src/client/views/DocumentDecorations.tsx | 9 ---------
 1 file changed, 9 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 280fad2e5..7bddc298e 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -3,26 +3,17 @@ import React = require("react");
 import { SelectionManager } from "../util/SelectionManager";
 import { observer } from "mobx-react";
 import './DocumentDecorations.scss'
-<<<<<<< HEAD
 import { CollectionFreeFormView } from "./collections/CollectionFreeFormView";
 import ContentEditable from 'react-contenteditable'
 import { KeyStore } from '../../fields/Key'
-=======
-import { KeyStore } from '../../fields/KeyStore'
-import { NumberField } from "../../fields/NumberField";
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
 
 @observer
 export class DocumentDecorations extends React.Component<{}, { value: string }> {
     static Instance: DocumentDecorations
     private _resizer = ""
     private _isPointerDown = false;
-<<<<<<< HEAD
     @observable private _opacity = 1;
     private keyinput: React.RefObject<HTMLInputElement>;
-=======
-    @observable private _hidden = false;
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
 
     constructor(props: Readonly<{}>) {
         super(props)
-- 
cgit v1.2.3-70-g09d2


From 8d2e07367afd3497cc474d611554eea27d706f0c Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Sat, 9 Mar 2019 19:06:41 -0500
Subject: key commands work

---
 src/client/views/DocumentDecorations.tsx | 40 +++++++++++++++++++++++++-------
 src/client/views/Main.tsx                | 39 ++++---------------------------
 2 files changed, 35 insertions(+), 44 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7bddc298e..3b2cd2626 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,11 +1,14 @@
-import { observable, computed } from "mobx";
+import { observable, computed, action } from "mobx";
 import React = require("react");
 import { SelectionManager } from "../util/SelectionManager";
 import { observer } from "mobx-react";
 import './DocumentDecorations.scss'
 import { CollectionFreeFormView } from "./collections/CollectionFreeFormView";
 import ContentEditable from 'react-contenteditable'
-import { KeyStore } from '../../fields/Key'
+import { KeyStore } from "../../fields/KeyStore";
+import { NumberField } from "../../fields/NumberField";
+import { Document } from "../../fields/Document";
+import { DocumentView } from "./nodes/DocumentView";
 
 @observer
 export class DocumentDecorations extends React.Component<{}, { value: string }> {
@@ -14,6 +17,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     private _isPointerDown = false;
     @observable private _opacity = 1;
     private keyinput: React.RefObject<HTMLInputElement>;
+    @observable private _documents: DocumentView[] = [];
+    //@observable private _title: string = this._documents[0].props.Document.Title;
+    @observable private _title: string = document.title;
 
     constructor(props: Readonly<{}>) {
         super(props)
@@ -23,26 +29,42 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         this.keyinput = React.createRef();
     }
 
-    handleChange(event: any) {
-        this.setState({ value: event.target.value });
-        console.log("Input box has changed")
+    @action
+    handleChange = (event: any) => {
+        //this.setState({ value: event.target.value });
+        this._title = event.target.value;
+        console.log("Input box has changed");
     };
 
-    enterPressed(e: any) {
+    @action
+    enterPressed = (e: any) => {
         var key = e.keyCode || e.which;
         // enter pressed
         if (key == 13) {
             var text = e.target.value;
             if (text[0] == '#') {
-                console.log("hashtag");
+                let command = text.slice(1, text.length);
+                if (command == "Title" || command == "title") {
+                    this._title = this._documents[0].props.Document.Title;
+                }
+                else if (command == "Width" || command == "width") {
+                    this._title = this._documents[0].props.Document.GetNumber(KeyStore.Width, 0).toString();
+                }
+                else {
+                    this._title = "undefined key";
+                }
                 // TODO: Change field with switch statement
             }
+            else {
+                this._title = document.title;
+            }
             e.target.blur();
         }
     }
 
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
+        this._documents = SelectionManager.SelectedDocuments();
         return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
             if (documentView.props.isTopMost) {
                 return bounds;
@@ -61,6 +83,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     @computed
     public get Hidden() { return this._hidden; }
     public set Hidden(value: boolean) { this._hidden = value; }
+    private _hidden: boolean = false;
 
     onPointerDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
@@ -178,8 +201,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 top: bounds.y - 20 - 20,
                 opacity: this._opacity
             }}>
-                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.state.value} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
-                {/* <div className="title" onPointerDown={this.onPointerDown}>{document.title}</div> */}
+                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this._title} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 4a3710e74..6e5b84075 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -18,6 +18,9 @@ import { DocumentDecorations } from './DocumentDecorations';
 import { DocumentView } from './nodes/DocumentView';
 import "./Main.scss";
 import { InkingControl } from './InkingControl';
+import { NumberField } from '../../fields/NumberField';
+import { TextField } from '../../fields/TextField';
+import { ListField } from '../../fields/ListField';
 
 
 configure({ enforceActions: "observed" });  // causes errors to be generated when modifying an observable outside of an action
@@ -30,40 +33,6 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
 }), true)
 
 
-<<<<<<< HEAD
-//runInAction(() => 
-{
-    let doc1 = Documents.TextDocument({ title: "hello", width: 400, height: 300 });
-    let doc2 = doc1.MakeDelegate();
-    doc2.Set(KS.X, new NumberField(150));
-    doc2.Set(KS.Y, new NumberField(500));
-    let doc3 = Documents.ImageDocument("https://psmag.com/.image/t_share/MTMyNzc2NzM1MDY1MjgzMDM4/shutterstock_151341212jpg.jpg", {
-        x: 450, y: 100, title: "dog", width: 606, height: 386, nativeWidth: 606, nativeHeight: 386
-    });
-    //doc3.Set(KeyStore.Data, new ImageField);
-    const schemaDocs = Array.from(Array(5).keys()).map(v => Documents.ImageDocument("https://psmag.com/.image/t_share/MTMyNzc2NzM1MDY1MjgzMDM4/shutterstock_151341212jpg.jpg", {
-        x: 50 + 100 * v, y: 50, width: 100, height: 100, title: "cat" + v, nativeWidth: 606, nativeHeight: 386
-    }));
-    schemaDocs.push(doc3);
-    schemaDocs[0].SetData(KS.Author, "Tyler", TextField);
-    schemaDocs[4].SetData(KS.Author, "Bob", TextField);
-    schemaDocs.push(doc2);
-    const doc7 = Documents.SchemaDocument(schemaDocs)
-    const docset = [doc1, doc2, doc3, doc7];
-    let doc4 = Documents.CollectionDocument(docset, {
-        x: 0, y: 400, title: "mini collection"
-    });
-    // let doc5 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
-    //     x: 650, y: 500, width: 600, height: 600, title: "cat 2"
-    // });
-    let docset2 = [doc3, doc4, doc2];
-    let doc6 = Documents.CollectionDocument(docset2, {
-        x: 350, y: 100, width: 600, height: 600, title: "docking collection"
-    });
-    let mainNodes = null;// mainContainer.GetFieldT(KeyStore.Data, ListField);
-    if (!mainNodes) {
-        mainNodes = new ListField<Document>();
-=======
 const mainDocId = "mainDoc";
 let mainContainer: Document;
 let mainfreeform: Document;
@@ -83,7 +52,6 @@ Documents.initProtos(mainDocId, (res?: Document) => {
             mainContainer.SetText(KeyStore.Data, JSON.stringify(dockingLayout));
             mainContainer.Set(KeyStore.ActiveFrame, mainfreeform);
         }, 0);
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
     }
 
     let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
@@ -141,3 +109,4 @@ Documents.initProtos(mainDocId, (res?: Document) => {
         </div>),
         document.getElementById('root'));
 })
+
-- 
cgit v1.2.3-70-g09d2


From 43a0768690caa89c606dd5d296d3cc8825c1702b Mon Sep 17 00:00:00 2001
From: ab <abdullah_ahmed@brown.edu>
Date: Mon, 11 Mar 2019 19:59:34 -0400
Subject: title binding works

---
 package-lock.json                        | 832 ++++++++++---------------------
 package.json                             |   2 +-
 src/client/views/DocumentDecorations.tsx |  51 +-
 3 files changed, 287 insertions(+), 598 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index 3ebd0a0d0..3422cd9f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,10 +9,7 @@
       "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz",
       "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==",
       "requires": {
-<<<<<<< HEAD
         "regenerator-runtime": "^0.12.0"
-=======
-        "regenerator-runtime": "0.12.1"
       },
       "dependencies": {
         "regenerator-runtime": {
@@ -20,7 +17,6 @@
           "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
           "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
         }
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
       }
     },
     "@fortawesome/fontawesome-common-types": {
@@ -33,7 +29,7 @@
       "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-solid/-/fontawesome-free-solid-5.0.13.tgz",
       "integrity": "sha512-b+krVnqkdDt52Yfev0x0ZZgtxBQsLw00Zfa3uaVWIDzpNZVtrEXuxldUSUaN/ihgGhSNi8VpvDAdNPVgCKOSxw==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "0.1.7"
+        "@fortawesome/fontawesome-common-types": "^0.1.7"
       },
       "dependencies": {
         "@fortawesome/fontawesome-common-types": {
@@ -48,11 +44,7 @@
       "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.15.tgz",
       "integrity": "sha512-M/sHyl4g2VBtKYkay1Z+XImMyTVcaBPmehYtPw4HKD9zg2E7eovB7Yx98aUfZjPbroGqa+IL4/+KhWBMOGlHIQ==",
       "requires": {
-<<<<<<< HEAD
-        "@fortawesome/fontawesome-common-types": "^0.2.14"
-=======
-        "@fortawesome/fontawesome-common-types": "0.2.15"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
+        "@fortawesome/fontawesome-common-types": "^0.2.15"
       }
     },
     "@fortawesome/free-solid-svg-icons": {
@@ -60,7 +52,7 @@
       "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.7.2.tgz",
       "integrity": "sha512-iujcXMyAvIbWM8W3jkOLpvJbR+rPpdN1QyqhZeJaLRdHPH4JmuovIAYP4vx5Sa1csZVXfRD1eDWqVZ/jGM620A==",
       "requires": {
-        "@fortawesome/fontawesome-common-types": "0.2.15"
+        "@fortawesome/fontawesome-common-types": "^0.2.15"
       }
     },
     "@fortawesome/react-fontawesome": {
@@ -68,8 +60,8 @@
       "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.4.tgz",
       "integrity": "sha512-GwmxQ+TK7PEdfSwvxtGnMCqrfEm0/HbRHArbUudsYiy9KzVCwndxa2KMcfyTQ8El0vROrq8gOOff09RF1oQe8g==",
       "requires": {
-        "humps": "2.0.1",
-        "prop-types": "15.6.2"
+        "humps": "^2.0.1",
+        "prop-types": "^15.5.10"
       }
     },
     "@icons/material": {
@@ -92,7 +84,7 @@
       "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz",
       "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==",
       "requires": {
-        "@types/babel-types": "7.0.6"
+        "@types/babel-types": "*"
       }
     },
     "@types/bcrypt-nodejs": {
@@ -110,13 +102,8 @@
       "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz",
       "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==",
       "requires": {
-<<<<<<< HEAD
         "@types/connect": "*",
         "@types/node": "*"
-=======
-        "@types/connect": "3.4.32",
-        "@types/node": "10.12.29"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
       }
     },
     "@types/bson": {
@@ -124,7 +111,7 @@
       "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.0.tgz",
       "integrity": "sha512-pq/rqJwJWkbS10crsG5bgnrisL8pML79KlMKQMoQwLUjlPAkrUHMvHJ3oGwE7WHR61Lv/nadMwXVAD2b+fpD8Q==",
       "requires": {
-        "@types/node": "10.12.29"
+        "@types/node": "*"
       }
     },
     "@types/caseless": {
@@ -143,10 +130,7 @@
       "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
       "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
       "requires": {
-<<<<<<< HEAD
         "@types/node": "*"
-=======
-        "@types/node": "10.12.29"
       }
     },
     "@types/connect-flash": {
@@ -154,8 +138,7 @@
       "resolved": "https://registry.npmjs.org/@types/connect-flash/-/connect-flash-0.0.34.tgz",
       "integrity": "sha512-QC93TwnTZ0sk//bfT81o7U4GOedbOZAcgvqi0v1vJqCESC8tqIVnhzB1CHiAUBUWFjoxG5JQF0TYaNa6DMb6Ig==",
       "requires": {
-        "@types/express": "4.16.1"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
+        "@types/express": "*"
       }
     },
     "@types/express": {
@@ -173,8 +156,8 @@
       "resolved": "https://registry.npmjs.org/@types/express-flash/-/express-flash-0.0.0.tgz",
       "integrity": "sha512-zs1xXRIZOjghUBriJPSnhPmfDpqf/EQxT21ggi/9XZ9/RHYrUi+5vK2jnQrP2pD1abbuZvm7owLICiNCLBQzEQ==",
       "requires": {
-        "@types/connect-flash": "0.0.34",
-        "@types/express": "4.16.1"
+        "@types/connect-flash": "*",
+        "@types/express": "*"
       }
     },
     "@types/express-serve-static-core": {
@@ -182,13 +165,8 @@
       "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.1.tgz",
       "integrity": "sha512-QgbIMRU1EVRry5cIu1ORCQP4flSYqLM1lS5LYyGWfKnFT3E58f0gKto7BR13clBFVrVZ0G0rbLZ1hUpSkgQQOA==",
       "requires": {
-<<<<<<< HEAD
         "@types/node": "*",
         "@types/range-parser": "*"
-=======
-        "@types/node": "10.12.29",
-        "@types/range-parser": "1.2.3"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
       }
     },
     "@types/express-session": {
@@ -196,8 +174,8 @@
       "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.15.12.tgz",
       "integrity": "sha512-DHZXzWy6Nu5Ng0syXUiVFRpZ6/1DOXoTCWa6RG3itGrub2ioBYvgtDbkT6VHHNo3iOdHRROyWANsMBJVaflblQ==",
       "requires": {
-        "@types/express": "4.16.1",
-        "@types/node": "10.12.29"
+        "@types/express": "*",
+        "@types/node": "*"
       }
     },
     "@types/express-validator": {
@@ -205,7 +183,7 @@
       "resolved": "https://registry.npmjs.org/@types/express-validator/-/express-validator-3.0.0.tgz",
       "integrity": "sha512-LusnB0YhTXpBT25PXyGPQlK7leE1e41Vezq1hHEUwjfkopM1Pkv2X2Ppxqh9c+w/HZ6Udzki8AJotKNjDTGdkQ==",
       "requires": {
-        "express-validator": "5.3.1"
+        "express-validator": "*"
       }
     },
     "@types/form-data": {
@@ -213,7 +191,7 @@
       "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
       "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
       "requires": {
-        "@types/node": "10.12.29"
+        "@types/node": "*"
       }
     },
     "@types/jquery": {
@@ -229,7 +207,7 @@
       "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
       "integrity": "sha512-YKnUTR4VxwljbPORPrRon9E3uel1aD8nUdvzqArCCdMTWPvo0gnI2UZkwIHN2QATdj6HYXV/Iq3/KcecAO42Ww==",
       "requires": {
-        "@types/node": "10.12.29"
+        "@types/node": "*"
       }
     },
     "@types/lodash": {
@@ -249,11 +227,7 @@
       "integrity": "sha512-j5AcZo7dbMxHoOimcHEIh0JZe5e1b8q8AqGSpZJrYc7xOgCIP79cIjTdx5jSDLtySnQDwkDTqwlC7Xw7uXw7qg==",
       "dev": true,
       "requires": {
-<<<<<<< HEAD
         "@types/node": "*"
-=======
-        "@types/node": "10.12.29"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
       }
     },
     "@types/mime": {
@@ -272,8 +246,8 @@
       "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.1.20.tgz",
       "integrity": "sha512-tl9iKbhM8d9BQjhB/9L4KuyLxfEn9Weq6cBuM8C06fIuUJyyfk+5wlfwzvltvssuxjGY1GiHvZHmSTK8kJ1zwg==",
       "requires": {
-        "@types/bson": "4.0.0",
-        "@types/node": "10.12.29"
+        "@types/bson": "*",
+        "@types/node": "*"
       }
     },
     "@types/mongoose": {
@@ -281,8 +255,8 @@
       "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.3.20.tgz",
       "integrity": "sha512-KXD/wRaUkxA7NwU+0yp60WEFFmkhzJ4idGawycjUxFMTANIM7ZqlZsoXhHu3p33cg450D8PuwtAorFUwuMXLwA==",
       "requires": {
-        "@types/mongodb": "3.1.20",
-        "@types/node": "10.12.29"
+        "@types/mongodb": "*",
+        "@types/node": "*"
       }
     },
     "@types/node": {
@@ -300,7 +274,7 @@
       "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.0.tgz",
       "integrity": "sha512-R2FXqM+AgsMIym0PuKj08Ybx+GR6d2rU3b1/8OcHolJ+4ga2pRPX105wboV6hq1AJvMo2frQzYKdqXS5+4cyMw==",
       "requires": {
-        "@types/express": "4.16.1"
+        "@types/express": "*"
       }
     },
     "@types/passport-local": {
@@ -308,9 +282,9 @@
       "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.33.tgz",
       "integrity": "sha512-+rn6ZIxje0jZ2+DAiWFI8vGG7ZFKB0hXx2cUdMmudSWsigSq6ES7Emso46r4HJk0qCgrZVfI8sJiM7HIYf4SbA==",
       "requires": {
-        "@types/express": "4.16.1",
-        "@types/passport": "1.0.0",
-        "@types/passport-strategy": "0.2.35"
+        "@types/express": "*",
+        "@types/passport": "*",
+        "@types/passport-strategy": "*"
       }
     },
     "@types/passport-strategy": {
@@ -318,8 +292,8 @@
       "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz",
       "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==",
       "requires": {
-        "@types/express": "4.16.1",
-        "@types/passport": "1.0.0"
+        "@types/express": "*",
+        "@types/passport": "*"
       }
     },
     "@types/prop-types": {
@@ -376,9 +350,9 @@
       "resolved": "https://registry.npmjs.org/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.1.tgz",
       "integrity": "sha512-+iUYq+pj2wVHSThj0MjNDzkkGwq8aDQ6j0UJK8a0cNCL8v44Ftcx1noGPtBIEUJgitH960VnfBNoTWfQoQZfRA==",
       "requires": {
-        "@types/orderedmap": "1.0.0",
-        "@types/prosemirror-model": "1.7.0",
-        "@types/prosemirror-state": "1.2.1"
+        "@types/orderedmap": "*",
+        "@types/prosemirror-model": "*",
+        "@types/prosemirror-state": "*"
       }
     },
     "@types/prosemirror-state": {
@@ -433,7 +407,7 @@
       "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-2.14.1.tgz",
       "integrity": "sha512-mIHKhPpN0tTnfmDXBzMw68ReFkDyzQWRUcDmJD13UA8L7vfjWATIZu1oM1BKW1eJdrUDdXFI6Cu5mJrV5Z/ZPw==",
       "requires": {
-        "@types/react": "16.8.1"
+        "@types/react": "*"
       }
     },
     "@types/react-dom": {
@@ -466,10 +440,10 @@
       "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz",
       "integrity": "sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==",
       "requires": {
-        "@types/caseless": "0.12.1",
-        "@types/form-data": "2.2.1",
-        "@types/node": "10.12.29",
-        "@types/tough-cookie": "2.3.5"
+        "@types/caseless": "*",
+        "@types/form-data": "*",
+        "@types/node": "*",
+        "@types/tough-cookie": "*"
       }
     },
     "@types/serve-static": {
@@ -491,7 +465,7 @@
       "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.2.tgz",
       "integrity": "sha512-Ind+4qMNfQ62llyB4IMs1D8znMEBsMKohZBPqfBUIXqLQ9bdtWIbNTBWwtdcBWJKnokMZGcmWOOKslatni5vtA==",
       "requires": {
-        "@types/node": "10.12.29"
+        "@types/node": "*"
       }
     },
     "@types/socket.io-client": {
@@ -537,11 +511,7 @@
       "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz",
       "integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==",
       "requires": {
-<<<<<<< HEAD
         "@types/node": "*"
-=======
-        "@types/node": "10.12.29"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
       }
     },
     "@types/webpack": {
@@ -549,19 +519,11 @@
       "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.4.24.tgz",
       "integrity": "sha512-yg99CjvB7xZ/iuHrsZ7dkGKoq/FRDzqLzAxKh2EmTem6FWjzrty4FqCqBYuX5z+MFwSaaQGDAX4Q9HQkLjGLnQ==",
       "requires": {
-<<<<<<< HEAD
         "@types/anymatch": "*",
         "@types/node": "*",
         "@types/tapable": "*",
         "@types/uglify-js": "*",
         "source-map": "^0.6.0"
-=======
-        "@types/anymatch": "1.3.1",
-        "@types/node": "10.12.29",
-        "@types/tapable": "1.0.4",
-        "@types/uglify-js": "3.0.4",
-        "source-map": "0.6.1"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
       },
       "dependencies": {
         "source-map": {
@@ -807,7 +769,7 @@
       "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
       "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
       "requires": {
-        "acorn": "4.0.13"
+        "acorn": "^4.0.4"
       },
       "dependencies": {
         "acorn": {
@@ -856,9 +818,9 @@
       "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
       "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
       "requires": {
-        "kind-of": "3.2.2",
-        "longest": "1.0.1",
-        "repeat-string": "1.6.1"
+        "kind-of": "^3.0.2",
+        "longest": "^1.0.1",
+        "repeat-string": "^1.5.2"
       },
       "dependencies": {
         "kind-of": {
@@ -866,7 +828,7 @@
           "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
           "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
           "requires": {
-            "is-buffer": "1.1.6"
+            "is-buffer": "^1.1.5"
           }
         }
       }
@@ -1179,8 +1141,8 @@
       "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
       "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
       "requires": {
-        "core-js": "2.6.4",
-        "regenerator-runtime": "0.11.1"
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
       },
       "dependencies": {
         "regenerator-runtime": {
@@ -1195,10 +1157,10 @@
       "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
       "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
       "requires": {
-        "babel-runtime": "6.26.0",
-        "esutils": "2.0.2",
-        "lodash": "4.17.11",
-        "to-fast-properties": "1.0.3"
+        "babel-runtime": "^6.26.0",
+        "esutils": "^2.0.2",
+        "lodash": "^4.17.4",
+        "to-fast-properties": "^1.0.3"
       }
     },
     "babylon": {
@@ -1711,8 +1673,8 @@
       "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
       "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
       "requires": {
-        "align-text": "0.1.4",
-        "lazy-cache": "1.0.4"
+        "align-text": "^0.1.3",
+        "lazy-cache": "^1.0.3"
       }
     },
     "chai": {
@@ -1746,7 +1708,7 @@
       "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
       "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
       "requires": {
-        "is-regex": "1.0.4"
+        "is-regex": "^1.0.3"
       }
     },
     "check-error": {
@@ -1837,7 +1799,7 @@
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
       "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
       "requires": {
-        "source-map": "0.6.1"
+        "source-map": "~0.6.0"
       },
       "dependencies": {
         "source-map": {
@@ -2035,7 +1997,7 @@
       "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-2.0.3.tgz",
       "integrity": "sha512-Vs+QZ/6X6gbCrP1Ls7Oh/wlyY6pgpbPSrUKF5yRT+zd+4GZPNbjNquxquZ+Clv2+03HBXE7T4lVM0PUcaBhihg==",
       "requires": {
-        "mongodb": "2.2.36"
+        "mongodb": "^2.0.36"
       },
       "dependencies": {
         "mongodb": {
@@ -2053,8 +2015,8 @@
           "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz",
           "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==",
           "requires": {
-            "bson": "1.0.9",
-            "require_optional": "1.0.1"
+            "bson": "~1.0.4",
+            "require_optional": "~1.0.0"
           }
         },
         "process-nextick-args": {
@@ -2067,13 +2029,13 @@
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
           "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
           "requires": {
-            "buffer-shims": "1.0.0",
-            "core-util-is": "1.0.2",
-            "inherits": "2.0.3",
-            "isarray": "1.0.0",
-            "process-nextick-args": "1.0.7",
-            "string_decoder": "1.0.3",
-            "util-deprecate": "1.0.2"
+            "buffer-shims": "~1.0.0",
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~1.0.6",
+            "string_decoder": "~1.0.0",
+            "util-deprecate": "~1.0.1"
           }
         },
         "string_decoder": {
@@ -2081,7 +2043,7 @@
           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
           "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
           "requires": {
-            "safe-buffer": "5.1.2"
+            "safe-buffer": "~5.1.0"
           }
         }
       }
@@ -2105,10 +2067,10 @@
       "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz",
       "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==",
       "requires": {
-        "@types/babel-types": "7.0.6",
-        "@types/babylon": "6.16.5",
-        "babel-types": "6.26.0",
-        "babylon": "6.18.0"
+        "@types/babel-types": "^7.0.0",
+        "@types/babylon": "^6.16.2",
+        "babel-types": "^6.26.0",
+        "babylon": "^6.18.0"
       }
     },
     "constants-browserify": {
@@ -2694,7 +2656,7 @@
       "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
       "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
       "requires": {
-        "safe-buffer": "5.1.2"
+        "safe-buffer": "^5.0.1"
       }
     },
     "ee-first": {
@@ -2746,12 +2708,12 @@
       "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz",
       "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==",
       "requires": {
-        "accepts": "1.3.5",
+        "accepts": "~1.3.4",
         "base64id": "1.0.0",
         "cookie": "0.3.1",
-        "debug": "3.1.0",
-        "engine.io-parser": "2.1.3",
-        "ws": "6.1.4"
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.0",
+        "ws": "~6.1.0"
       },
       "dependencies": {
         "debug": {
@@ -2771,14 +2733,14 @@
       "requires": {
         "component-emitter": "1.2.1",
         "component-inherit": "0.0.3",
-        "debug": "3.1.0",
-        "engine.io-parser": "2.1.3",
+        "debug": "~3.1.0",
+        "engine.io-parser": "~2.1.1",
         "has-cors": "1.1.0",
         "indexof": "0.0.1",
         "parseqs": "0.0.5",
         "parseuri": "0.0.5",
-        "ws": "6.1.4",
-        "xmlhttprequest-ssl": "1.5.5",
+        "ws": "~6.1.0",
+        "xmlhttprequest-ssl": "~1.5.4",
         "yeast": "0.1.2"
       },
       "dependencies": {
@@ -2798,10 +2760,10 @@
       "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
       "requires": {
         "after": "0.8.2",
-        "arraybuffer.slice": "0.0.7",
+        "arraybuffer.slice": "~0.0.7",
         "base64-arraybuffer": "0.1.5",
         "blob": "0.0.5",
-        "has-binary2": "1.0.3"
+        "has-binary2": "~1.0.2"
       }
     },
     "enhanced-resolve": {
@@ -3083,7 +3045,7 @@
       "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz",
       "integrity": "sha1-I9GovPP5DXB5KOSJ+Whp7K0KzaI=",
       "requires": {
-        "connect-flash": "0.1.1"
+        "connect-flash": "0.1.x"
       }
     },
     "express-session": {
@@ -3095,10 +3057,10 @@
         "cookie-signature": "1.0.6",
         "crc": "3.4.4",
         "debug": "2.6.9",
-        "depd": "1.1.2",
-        "on-headers": "1.0.1",
-        "parseurl": "1.3.2",
-        "uid-safe": "2.1.5",
+        "depd": "~1.1.1",
+        "on-headers": "~1.0.1",
+        "parseurl": "~1.3.2",
+        "uid-safe": "~2.1.5",
         "utils-merge": "1.0.1"
       }
     },
@@ -3107,8 +3069,8 @@
       "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-5.3.1.tgz",
       "integrity": "sha512-g8xkipBF6VxHbO1+ksC7nxUU7+pWif0+OZXjZTybKJ/V0aTVhuCoHbyhIPgSYVldwQLocGExPtB2pE0DqK4jsw==",
       "requires": {
-        "lodash": "4.17.11",
-        "validator": "10.11.0"
+        "lodash": "^4.17.10",
+        "validator": "^10.4.0"
       }
     },
     "expressjs": {
@@ -3234,18 +3196,11 @@
       "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.6.1.tgz",
       "integrity": "sha1-lja3cF9bqWhNRLcveDISVK/IYPc=",
       "requires": {
-<<<<<<< HEAD
         "core-js": "^1.0.0",
         "loose-envify": "^1.0.0",
         "promise": "^7.0.3",
         "ua-parser-js": "^0.7.9",
         "whatwg-fetch": "^0.9.0"
-=======
-        "core-js": "1.2.7",
-        "loose-envify": "1.4.0",
-        "promise": "7.3.1",
-        "ua-parser-js": "0.7.19",
-        "whatwg-fetch": "0.9.0"
       },
       "dependencies": {
         "core-js": {
@@ -3253,7 +3208,6 @@
           "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
           "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
         }
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
       }
     },
     "figgy-pudding": {
@@ -3268,8 +3222,8 @@
       "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==",
       "dev": true,
       "requires": {
-        "loader-utils": "1.2.3",
-        "schema-utils": "1.0.0"
+        "loader-utils": "^1.0.2",
+        "schema-utils": "^1.0.0"
       }
     },
     "fill-range": {
@@ -3512,12 +3466,14 @@
         "balanced-match": {
           "version": "1.0.0",
           "resolved": false,
-          "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+          "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+          "optional": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "resolved": false,
           "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -3537,7 +3493,8 @@
         "concat-map": {
           "version": "0.0.1",
           "resolved": false,
-          "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+          "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+          "optional": true
         },
         "console-control-strings": {
           "version": "1.1.0",
@@ -3685,6 +3642,7 @@
           "version": "3.0.4",
           "resolved": false,
           "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -4265,7 +4223,7 @@
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
       "requires": {
-        "function-bind": "1.1.1"
+        "function-bind": "^1.1.1"
       }
     },
     "has-ansi": {
@@ -4801,8 +4759,8 @@
       "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
       "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
       "requires": {
-        "acorn": "4.0.13",
-        "object-assign": "4.1.1"
+        "acorn": "~4.0.2",
+        "object-assign": "^4.0.1"
       },
       "dependencies": {
         "acorn": {
@@ -4929,7 +4887,7 @@
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
       "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
       "requires": {
-        "has": "1.0.3"
+        "has": "^1.0.1"
       }
     },
     "is-retry-allowed": {
@@ -5059,15 +5017,15 @@
       "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz",
       "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==",
       "requires": {
-        "jws": "3.2.1",
-        "lodash.includes": "4.3.0",
-        "lodash.isboolean": "3.0.3",
-        "lodash.isinteger": "4.0.4",
-        "lodash.isnumber": "3.0.3",
-        "lodash.isplainobject": "4.0.6",
-        "lodash.isstring": "4.0.1",
-        "lodash.once": "4.1.1",
-        "ms": "2.1.1"
+        "jws": "^3.1.5",
+        "lodash.includes": "^4.3.0",
+        "lodash.isboolean": "^3.0.3",
+        "lodash.isinteger": "^4.0.4",
+        "lodash.isnumber": "^3.0.3",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.isstring": "^4.0.1",
+        "lodash.once": "^4.0.0",
+        "ms": "^2.1.1"
       },
       "dependencies": {
         "ms": {
@@ -5112,8 +5070,8 @@
       "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
       "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
       "requires": {
-        "is-promise": "2.1.0",
-        "promise": "7.3.1"
+        "is-promise": "^2.0.0",
+        "promise": "^7.0.1"
       }
     },
     "jsx-to-string": {
@@ -5144,7 +5102,7 @@
       "requires": {
         "buffer-equal-constant-time": "1.0.1",
         "ecdsa-sig-formatter": "1.0.11",
-        "safe-buffer": "5.1.2"
+        "safe-buffer": "^5.0.1"
       }
     },
     "jws": {
@@ -5152,8 +5110,8 @@
       "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz",
       "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==",
       "requires": {
-        "jwa": "1.4.0",
-        "safe-buffer": "5.1.2"
+        "jwa": "^1.2.0",
+        "safe-buffer": "^5.0.1"
       }
     },
     "kareem": {
@@ -5764,7 +5722,7 @@
       "integrity": "sha512-sz2dhvBZQWf3LRNDhbd30KHVzdjZx9IKC0L+kSZ/gzYquCF5zPOgGqRz6sSCqYZtKP2ekB4nfLxhGtzGHnIKxA==",
       "requires": {
         "mongodb-core": "3.1.11",
-        "safe-buffer": "5.1.2"
+        "safe-buffer": "^5.1.2"
       },
       "dependencies": {
         "bson": {
@@ -5777,10 +5735,10 @@
           "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.11.tgz",
           "integrity": "sha512-rD2US2s5qk/ckbiiGFHeu+yKYDXdJ1G87F6CG3YdaZpzdOm5zpoAZd/EKbPmFO6cQZ+XVXBXBJ660sSI0gc6qg==",
           "requires": {
-            "bson": "1.1.0",
-            "require_optional": "1.0.1",
-            "safe-buffer": "5.1.2",
-            "saslprep": "1.0.2"
+            "bson": "^1.1.0",
+            "require_optional": "^1.0.1",
+            "safe-buffer": "^5.1.2",
+            "saslprep": "^1.0.0"
           }
         }
       }
@@ -5791,7 +5749,7 @@
       "integrity": "sha512-9aAg8M0YUmGHQRDYvsKJ02wx/Qaof1Jn2iDH21ZtWGAZpQt9uVLNEOdcBuzi+lPJwGbLYh2dphdKX0sZ+dXAJQ==",
       "requires": {
         "async": "2.6.1",
-        "bson": "1.1.0",
+        "bson": "~1.1.0",
         "kareem": "2.3.0",
         "mongodb": "3.1.13",
         "mongodb-core": "3.1.11",
@@ -5809,7 +5767,7 @@
           "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
           "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
           "requires": {
-            "lodash": "4.17.11"
+            "lodash": "^4.17.10"
           }
         },
         "bson": {
@@ -6161,7 +6119,6 @@
       "resolved": "https://registry.npmjs.org/npm/-/npm-6.8.0.tgz",
       "integrity": "sha512-xMH6V0OCSJ5ZET6yWPI3BmJSqMMCuVJSIcLx3LSH/SrratFSt6EDuCuGRFMQYty98Q1l6x/7vKmfURosoyWgrA==",
       "requires": {
-<<<<<<< HEAD
         "JSONStream": "^1.3.5",
         "abbrev": "~1.1.1",
         "ansicolors": "~0.3.2",
@@ -6231,22 +6188,22 @@
         "move-concurrently": "^1.0.1",
         "node-gyp": "^3.8.0",
         "nopt": "~4.0.1",
-        "normalize-package-data": "~2.4.0",
+        "normalize-package-data": "^2.5.0",
         "npm-audit-report": "^1.3.2",
         "npm-cache-filename": "~1.0.2",
         "npm-install-checks": "~3.0.0",
         "npm-lifecycle": "^2.1.0",
         "npm-package-arg": "^6.1.0",
-        "npm-packlist": "^1.2.0",
+        "npm-packlist": "^1.3.0",
         "npm-pick-manifest": "^2.2.3",
         "npm-profile": "*",
-        "npm-registry-fetch": "^3.8.0",
+        "npm-registry-fetch": "^3.9.0",
         "npm-user-validate": "~1.0.0",
         "npmlog": "~4.1.2",
         "once": "~1.4.0",
         "opener": "^1.5.1",
         "osenv": "^0.1.5",
-        "pacote": "^9.4.0",
+        "pacote": "^9.4.1",
         "path-is-inside": "~1.0.2",
         "promise-inflight": "~1.0.1",
         "qrcode-terminal": "^0.12.0",
@@ -6256,7 +6213,7 @@
         "read-cmd-shim": "~1.0.1",
         "read-installed": "~4.0.3",
         "read-package-json": "^2.0.13",
-        "read-package-tree": "^5.2.1",
+        "read-package-tree": "^5.2.2",
         "readable-stream": "^3.1.1",
         "readdir-scoped-modules": "*",
         "request": "^2.88.0",
@@ -6273,119 +6230,6 @@
         "tar": "^4.4.8",
         "text-table": "~0.2.0",
         "tiny-relative-date": "^1.3.0",
-=======
-        "JSONStream": "1.3.5",
-        "abbrev": "1.1.1",
-        "ansicolors": "0.3.2",
-        "ansistyles": "0.1.3",
-        "aproba": "2.0.0",
-        "archy": "1.0.0",
-        "bin-links": "1.1.2",
-        "bluebird": "3.5.3",
-        "byte-size": "5.0.1",
-        "cacache": "11.3.2",
-        "call-limit": "1.1.0",
-        "chownr": "1.1.1",
-        "ci-info": "2.0.0",
-        "cli-columns": "3.1.2",
-        "cli-table3": "0.5.1",
-        "cmd-shim": "2.0.2",
-        "columnify": "1.5.4",
-        "config-chain": "1.1.12",
-        "debuglog": "1.0.1",
-        "detect-indent": "5.0.0",
-        "detect-newline": "2.1.0",
-        "dezalgo": "1.0.3",
-        "editor": "1.0.0",
-        "figgy-pudding": "3.5.1",
-        "find-npm-prefix": "1.0.2",
-        "fs-vacuum": "1.2.10",
-        "fs-write-stream-atomic": "1.0.10",
-        "gentle-fs": "2.0.1",
-        "glob": "7.1.3",
-        "graceful-fs": "4.1.15",
-        "has-unicode": "2.0.1",
-        "hosted-git-info": "2.7.1",
-        "iferr": "1.0.2",
-        "imurmurhash": "0.1.4",
-        "inflight": "1.0.6",
-        "inherits": "2.0.3",
-        "ini": "1.3.5",
-        "init-package-json": "1.10.3",
-        "is-cidr": "3.0.0",
-        "json-parse-better-errors": "1.0.2",
-        "lazy-property": "1.0.0",
-        "libcipm": "3.0.3",
-        "libnpm": "2.0.1",
-        "libnpmaccess": "3.0.1",
-        "libnpmhook": "5.0.2",
-        "libnpmorg": "1.0.0",
-        "libnpmsearch": "2.0.0",
-        "libnpmteam": "1.0.1",
-        "libnpx": "10.2.0",
-        "lock-verify": "2.0.2",
-        "lockfile": "1.0.4",
-        "lodash._baseindexof": "3.1.0",
-        "lodash._baseuniq": "4.6.0",
-        "lodash._bindcallback": "3.0.1",
-        "lodash._cacheindexof": "3.0.2",
-        "lodash._createcache": "3.1.2",
-        "lodash._getnative": "3.9.1",
-        "lodash.clonedeep": "4.5.0",
-        "lodash.restparam": "3.6.1",
-        "lodash.union": "4.6.0",
-        "lodash.uniq": "4.5.0",
-        "lodash.without": "4.4.0",
-        "lru-cache": "4.1.5",
-        "meant": "1.0.1",
-        "mississippi": "3.0.0",
-        "mkdirp": "0.5.1",
-        "move-concurrently": "1.0.1",
-        "node-gyp": "3.8.0",
-        "nopt": "4.0.1",
-        "normalize-package-data": "2.5.0",
-        "npm-audit-report": "1.3.2",
-        "npm-cache-filename": "1.0.2",
-        "npm-install-checks": "3.0.0",
-        "npm-lifecycle": "2.1.0",
-        "npm-package-arg": "6.1.0",
-        "npm-packlist": "1.3.0",
-        "npm-pick-manifest": "2.2.3",
-        "npm-profile": "4.0.1",
-        "npm-registry-fetch": "3.9.0",
-        "npm-user-validate": "1.0.0",
-        "npmlog": "4.1.2",
-        "once": "1.4.0",
-        "opener": "1.5.1",
-        "osenv": "0.1.5",
-        "pacote": "9.4.1",
-        "path-is-inside": "1.0.2",
-        "promise-inflight": "1.0.1",
-        "qrcode-terminal": "0.12.0",
-        "query-string": "6.2.0",
-        "qw": "1.0.1",
-        "read": "1.0.7",
-        "read-cmd-shim": "1.0.1",
-        "read-installed": "4.0.3",
-        "read-package-json": "2.0.13",
-        "read-package-tree": "5.2.2",
-        "readable-stream": "3.1.1",
-        "readdir-scoped-modules": "1.0.2",
-        "request": "2.88.0",
-        "retry": "0.12.0",
-        "rimraf": "2.6.3",
-        "safe-buffer": "5.1.2",
-        "semver": "5.6.0",
-        "sha": "2.0.1",
-        "slide": "1.1.6",
-        "sorted-object": "2.0.1",
-        "sorted-union-stream": "2.1.3",
-        "ssri": "6.0.1",
-        "stringify-package": "1.0.0",
-        "tar": "4.4.8",
-        "text-table": "0.2.0",
-        "tiny-relative-date": "1.3.0",
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
         "uid-number": "0.0.6",
         "umask": "~1.1.0",
         "unique-filename": "^1.1.1",
@@ -7652,19 +7496,8 @@
         },
         "ip-regex": {
           "version": "2.1.0",
-<<<<<<< HEAD
-          "bundled": true
-        },
-        "is-builtin-module": {
-          "version": "1.0.0",
-          "bundled": true,
-          "requires": {
-            "builtin-modules": "^1.0.0"
-          }
-=======
           "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
           "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk="
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
         },
         "is-ci": {
           "version": "1.1.0",
@@ -7827,23 +7660,6 @@
           "resolved": "https://registry.npmjs.org/libcipm/-/libcipm-3.0.3.tgz",
           "integrity": "sha512-71V5CpTI+zFydTc5IjJ/tx8JHbXEJvmYF2zaSVW1V3X1rRnRjXqh44iuiyry1xgi3ProUQ1vX1uwFiWs00+2og==",
           "requires": {
-<<<<<<< HEAD
-            "bin-links": "^1.1.2",
-            "bluebird": "^3.5.1",
-            "figgy-pudding": "^3.5.1",
-            "find-npm-prefix": "^1.0.2",
-            "graceful-fs": "^4.1.11",
-            "ini": "^1.3.5",
-            "lock-verify": "^2.0.2",
-            "mkdirp": "^0.5.1",
-            "npm-lifecycle": "^2.0.3",
-            "npm-logical-tree": "^1.2.1",
-            "npm-package-arg": "^6.1.0",
-            "pacote": "^9.1.0",
-            "read-package-json": "^2.0.13",
-            "rimraf": "^2.6.2",
-            "worker-farm": "^1.6.0"
-=======
             "bin-links": "1.1.2",
             "bluebird": "3.5.3",
             "figgy-pudding": "3.5.1",
@@ -7859,7 +7675,6 @@
             "read-package-json": "2.0.13",
             "rimraf": "2.6.3",
             "worker-farm": "1.6.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "libnpm": {
@@ -7867,28 +7682,6 @@
           "resolved": "https://registry.npmjs.org/libnpm/-/libnpm-2.0.1.tgz",
           "integrity": "sha512-qTKoxyJvpBxHZQB6k0AhSLajyXq9ZE/lUsZzuHAplr2Bpv9G+k4YuYlExYdUCeVRRGqcJt8hvkPh4tBwKoV98w==",
           "requires": {
-<<<<<<< HEAD
-            "bin-links": "^1.1.2",
-            "bluebird": "^3.5.3",
-            "find-npm-prefix": "^1.0.2",
-            "libnpmaccess": "^3.0.1",
-            "libnpmconfig": "^1.2.1",
-            "libnpmhook": "^5.0.2",
-            "libnpmorg": "^1.0.0",
-            "libnpmpublish": "^1.1.0",
-            "libnpmsearch": "^2.0.0",
-            "libnpmteam": "^1.0.1",
-            "lock-verify": "^2.0.2",
-            "npm-lifecycle": "^2.1.0",
-            "npm-logical-tree": "^1.2.1",
-            "npm-package-arg": "^6.1.0",
-            "npm-profile": "^4.0.1",
-            "npm-registry-fetch": "^3.8.0",
-            "npmlog": "^4.1.2",
-            "pacote": "^9.2.3",
-            "read-package-json": "^2.0.13",
-            "stringify-package": "^1.0.0"
-=======
             "bin-links": "1.1.2",
             "bluebird": "3.5.3",
             "find-npm-prefix": "1.0.2",
@@ -7909,7 +7702,6 @@
             "pacote": "9.4.1",
             "read-package-json": "2.0.13",
             "stringify-package": "1.0.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "libnpmaccess": {
@@ -7917,17 +7709,10 @@
           "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-3.0.1.tgz",
           "integrity": "sha512-RlZ7PNarCBt+XbnP7R6PoVgOq9t+kou5rvhaInoNibhPO7eMlRfS0B8yjatgn2yaHIwWNyoJDolC/6Lc5L/IQA==",
           "requires": {
-<<<<<<< HEAD
-            "aproba": "^2.0.0",
-            "get-stream": "^4.0.0",
-            "npm-package-arg": "^6.1.0",
-            "npm-registry-fetch": "^3.8.0"
-=======
             "aproba": "2.0.0",
             "get-stream": "4.1.0",
             "npm-package-arg": "6.1.0",
             "npm-registry-fetch": "3.9.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           },
           "dependencies": {
             "aproba": {
@@ -7992,17 +7777,10 @@
           "resolved": "https://registry.npmjs.org/libnpmhook/-/libnpmhook-5.0.2.tgz",
           "integrity": "sha512-vLenmdFWhRfnnZiNFPNMog6CK7Ujofy2TWiM2CrpZUjBRIhHkJeDaAbJdYCT6W4lcHtyrJR8yXW8KFyq6UAp1g==",
           "requires": {
-<<<<<<< HEAD
-            "aproba": "^2.0.0",
-            "figgy-pudding": "^3.4.1",
-            "get-stream": "^4.0.0",
-            "npm-registry-fetch": "^3.8.0"
-=======
             "aproba": "2.0.0",
             "figgy-pudding": "3.5.1",
             "get-stream": "4.1.0",
             "npm-registry-fetch": "3.9.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "libnpmorg": {
@@ -8010,17 +7788,10 @@
           "resolved": "https://registry.npmjs.org/libnpmorg/-/libnpmorg-1.0.0.tgz",
           "integrity": "sha512-o+4eVJBoDGMgRwh2lJY0a8pRV2c/tQM/SxlqXezjcAg26Qe9jigYVs+Xk0vvlYDWCDhP0g74J8UwWeAgsB7gGw==",
           "requires": {
-<<<<<<< HEAD
-            "aproba": "^2.0.0",
-            "figgy-pudding": "^3.4.1",
-            "get-stream": "^4.0.0",
-            "npm-registry-fetch": "^3.8.0"
-=======
             "aproba": "2.0.0",
             "figgy-pudding": "3.5.1",
             "get-stream": "4.1.0",
             "npm-registry-fetch": "3.9.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           },
           "dependencies": {
             "aproba": {
@@ -8035,17 +7806,6 @@
           "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-1.1.1.tgz",
           "integrity": "sha512-nefbvJd/wY38zdt+b9SHL6171vqBrMtZ56Gsgfd0duEKb/pB8rDT4/ObUQLrHz1tOfht1flt2zM+UGaemzAG5g==",
           "requires": {
-<<<<<<< HEAD
-            "aproba": "^2.0.0",
-            "figgy-pudding": "^3.5.1",
-            "get-stream": "^4.0.0",
-            "lodash.clonedeep": "^4.5.0",
-            "normalize-package-data": "^2.4.0",
-            "npm-package-arg": "^6.1.0",
-            "npm-registry-fetch": "^3.8.0",
-            "semver": "^5.5.1",
-            "ssri": "^6.0.1"
-=======
             "aproba": "2.0.0",
             "figgy-pudding": "3.5.1",
             "get-stream": "4.1.0",
@@ -8055,7 +7815,6 @@
             "npm-registry-fetch": "3.9.0",
             "semver": "5.6.0",
             "ssri": "6.0.1"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "libnpmsearch": {
@@ -8063,15 +7822,9 @@
           "resolved": "https://registry.npmjs.org/libnpmsearch/-/libnpmsearch-2.0.0.tgz",
           "integrity": "sha512-vd+JWbTGzOSfiOc+72MU6y7WqmBXn49egCCrIXp27iE/88bX8EpG64ST1blWQI1bSMUr9l1AKPMVsqa2tS5KWA==",
           "requires": {
-<<<<<<< HEAD
-            "figgy-pudding": "^3.5.1",
-            "get-stream": "^4.0.0",
-            "npm-registry-fetch": "^3.8.0"
-=======
             "figgy-pudding": "3.5.1",
             "get-stream": "4.1.0",
             "npm-registry-fetch": "3.9.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "libnpmteam": {
@@ -8079,17 +7832,10 @@
           "resolved": "https://registry.npmjs.org/libnpmteam/-/libnpmteam-1.0.1.tgz",
           "integrity": "sha512-gDdrflKFCX7TNwOMX1snWojCoDE5LoRWcfOC0C/fqF7mBq8Uz9zWAX4B2RllYETNO7pBupBaSyBDkTAC15cAMg==",
           "requires": {
-<<<<<<< HEAD
-            "aproba": "^2.0.0",
-            "figgy-pudding": "^3.4.1",
-            "get-stream": "^4.0.0",
-            "npm-registry-fetch": "^3.8.0"
-=======
             "aproba": "2.0.0",
             "figgy-pudding": "3.5.1",
             "get-stream": "4.1.0",
             "npm-registry-fetch": "3.9.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           },
           "dependencies": {
             "aproba": {
@@ -8443,12 +8189,6 @@
           "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
           "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
           "requires": {
-<<<<<<< HEAD
-            "hosted-git-info": "^2.1.4",
-            "is-builtin-module": "^1.0.0",
-            "semver": "2 || 3 || 4 || 5",
-            "validate-npm-package-license": "^3.0.1"
-=======
             "hosted-git-info": "2.7.1",
             "resolve": "1.10.0",
             "semver": "5.6.0",
@@ -8463,7 +8203,6 @@
                 "path-parse": "1.0.6"
               }
             }
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "npm-audit-report": {
@@ -8529,13 +8268,8 @@
           "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.3.0.tgz",
           "integrity": "sha512-qPBc6CnxEzpOcc4bjoIBJbYdy0D/LFFPUdxvfwor4/w3vxeE0h6TiOVurCEPpQ6trjN77u/ShyfeJGsbAfB3dA==",
           "requires": {
-<<<<<<< HEAD
             "ignore-walk": "^3.0.1",
             "npm-bundled": "^1.0.1"
-=======
-            "ignore-walk": "3.0.1",
-            "npm-bundled": "1.0.6"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "npm-pick-manifest": {
@@ -8553,15 +8287,9 @@
           "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-4.0.1.tgz",
           "integrity": "sha512-NQ1I/1Q7YRtHZXkcuU1/IyHeLy6pd+ScKg4+DQHdfsm769TGq6HPrkbuNJVJS4zwE+0mvvmeULzQdWn2L2EsVA==",
           "requires": {
-<<<<<<< HEAD
-            "aproba": "^1.1.2 || 2",
-            "figgy-pudding": "^3.4.1",
-            "npm-registry-fetch": "^3.8.0"
-=======
             "aproba": "2.0.0",
             "figgy-pudding": "3.5.1",
             "npm-registry-fetch": "3.9.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "npm-registry-fetch": {
@@ -8700,7 +8428,6 @@
           "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.4.1.tgz",
           "integrity": "sha512-YKSRsQqmeHxgra0KCdWA2FtVxDPUlBiCdmew+mSe44pzlx5t1ViRMWiQg18T+DREA+vSqYfKzynaToFR4hcKHw==",
           "requires": {
-<<<<<<< HEAD
             "bluebird": "^3.5.3",
             "cacache": "^11.3.2",
             "figgy-pudding": "^3.5.1",
@@ -8728,35 +8455,6 @@
             "tar": "^4.4.8",
             "unique-filename": "^1.1.1",
             "which": "^1.3.1"
-=======
-            "bluebird": "3.5.3",
-            "cacache": "11.3.2",
-            "figgy-pudding": "3.5.1",
-            "get-stream": "4.1.0",
-            "glob": "7.1.3",
-            "lru-cache": "5.1.1",
-            "make-fetch-happen": "4.0.1",
-            "minimatch": "3.0.4",
-            "minipass": "2.3.5",
-            "mississippi": "3.0.0",
-            "mkdirp": "0.5.1",
-            "normalize-package-data": "2.5.0",
-            "npm-package-arg": "6.1.0",
-            "npm-packlist": "1.3.0",
-            "npm-pick-manifest": "2.2.3",
-            "npm-registry-fetch": "3.9.0",
-            "osenv": "0.1.5",
-            "promise-inflight": "1.0.1",
-            "promise-retry": "1.1.1",
-            "protoduck": "5.0.1",
-            "rimraf": "2.6.3",
-            "safe-buffer": "5.1.2",
-            "semver": "5.6.0",
-            "ssri": "6.0.1",
-            "tar": "4.4.8",
-            "unique-filename": "1.1.1",
-            "which": "1.3.1"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           },
           "dependencies": {
             "lru-cache": {
@@ -9031,19 +8729,11 @@
           "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.13.tgz",
           "integrity": "sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg==",
           "requires": {
-<<<<<<< HEAD
-            "glob": "^7.1.1",
-            "graceful-fs": "^4.1.2",
-            "json-parse-better-errors": "^1.0.1",
-            "normalize-package-data": "^2.0.0",
-            "slash": "^1.0.0"
-=======
             "glob": "7.1.3",
             "graceful-fs": "4.1.15",
             "json-parse-better-errors": "1.0.2",
             "normalize-package-data": "2.5.0",
             "slash": "1.0.0"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
           }
         },
         "read-package-tree": {
@@ -10172,7 +9862,7 @@
       "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
       "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
       "requires": {
-        "better-assert": "1.0.2"
+        "better-assert": "~1.0.0"
       }
     },
     "parseuri": {
@@ -10180,7 +9870,7 @@
       "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
       "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
       "requires": {
-        "better-assert": "1.0.2"
+        "better-assert": "~1.0.0"
       }
     },
     "parseurl": {
@@ -10198,7 +9888,7 @@
       "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz",
       "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=",
       "requires": {
-        "passport-strategy": "1.0.0",
+        "passport-strategy": "1.x.x",
         "pause": "0.0.1"
       }
     },
@@ -10207,7 +9897,7 @@
       "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
       "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
       "requires": {
-        "passport-strategy": "1.0.0"
+        "passport-strategy": "1.x.x"
       }
     },
     "passport-strategy": {
@@ -10298,8 +9988,8 @@
       "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.1.266.tgz",
       "integrity": "sha512-Jy7o1wE3NezPxozexSbq4ltuLT0Z21ew/qrEiAEeUZzHxMHGk4DUV1D7RuCXg5vJDvHmjX1YssN+we9QfRRgXQ==",
       "requires": {
-        "node-ensure": "0.0.0",
-        "worker-loader": "2.0.0"
+        "node-ensure": "^0.0.0",
+        "worker-loader": "^2.0.0"
       }
     },
     "performance-now": {
@@ -10525,9 +10215,9 @@
       "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.1.1.tgz",
       "integrity": "sha512-GeUyMO/tOEf8MXrP7Xb7UIMrfK86OGh0fnyBrHfhav4VjY9cw65mNoqHy87CklE5711AhCP5Qzfp8RL/hVKusg==",
       "requires": {
-        "prosemirror-state": "1.2.2",
-        "prosemirror-transform": "1.1.3",
-        "prosemirror-view": "1.7.1"
+        "prosemirror-state": "^1.0.0",
+        "prosemirror-transform": "^1.1.0",
+        "prosemirror-view": "^1.1.0"
       }
     },
     "prosemirror-example-setup": {
@@ -10535,15 +10225,15 @@
       "resolved": "https://registry.npmjs.org/prosemirror-example-setup/-/prosemirror-example-setup-1.0.1.tgz",
       "integrity": "sha512-4NKWpdmm75Zzgq/dIrypRnkBNPx+ONKyoGF42a9g3VIVv0TWglf1CBNxt5kzCgli9xdfut/xE5B42F9DR6BLHw==",
       "requires": {
-        "prosemirror-commands": "1.0.7",
-        "prosemirror-dropcursor": "1.1.1",
-        "prosemirror-gapcursor": "1.0.3",
-        "prosemirror-history": "1.0.3",
-        "prosemirror-inputrules": "1.0.1",
-        "prosemirror-keymap": "1.0.1",
-        "prosemirror-menu": "1.0.5",
-        "prosemirror-schema-list": "1.0.2",
-        "prosemirror-state": "1.2.2"
+        "prosemirror-commands": "^1.0.0",
+        "prosemirror-dropcursor": "^1.0.0",
+        "prosemirror-gapcursor": "^1.0.0",
+        "prosemirror-history": "^1.0.0",
+        "prosemirror-inputrules": "^1.0.0",
+        "prosemirror-keymap": "^1.0.0",
+        "prosemirror-menu": "^1.0.0",
+        "prosemirror-schema-list": "^1.0.0",
+        "prosemirror-state": "^1.0.0"
       }
     },
     "prosemirror-gapcursor": {
@@ -10551,10 +10241,10 @@
       "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.0.3.tgz",
       "integrity": "sha512-X+hJhr42PcHWiSWL+lI5f/UeOhXCxlBFb8M6O8aG1hssmaRrW7sS2/Fjg5jFV+pTdS1REFkmm1occh01FMdDIQ==",
       "requires": {
-        "prosemirror-keymap": "1.0.1",
-        "prosemirror-model": "1.7.0",
-        "prosemirror-state": "1.2.2",
-        "prosemirror-view": "1.7.1"
+        "prosemirror-keymap": "^1.0.0",
+        "prosemirror-model": "^1.0.0",
+        "prosemirror-state": "^1.0.0",
+        "prosemirror-view": "^1.0.0"
       }
     },
     "prosemirror-history": {
@@ -10572,8 +10262,8 @@
       "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.0.1.tgz",
       "integrity": "sha512-UHy22NmwxS5WIMQYkzraDttQAF8mpP82FfbJsmKFfx6jwkR/SZa+ZhbkLY0zKQ5fBdJN7euj36JG/B5iAlrpxA==",
       "requires": {
-        "prosemirror-state": "1.2.2",
-        "prosemirror-transform": "1.1.3"
+        "prosemirror-state": "^1.0.0",
+        "prosemirror-transform": "^1.0.0"
       }
     },
     "prosemirror-keymap": {
@@ -10590,10 +10280,10 @@
       "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.0.5.tgz",
       "integrity": "sha512-9Vrn7CC191v7FA4QrAkL8W1SrR73V3CRIYCDuk94R8oFVk4VxSFdoKVLHuvGzxZ8b5LCu3DMJfh86YW9uL4RkQ==",
       "requires": {
-        "crel": "3.1.0",
-        "prosemirror-commands": "1.0.7",
-        "prosemirror-history": "1.0.3",
-        "prosemirror-state": "1.2.2"
+        "crel": "^3.0.0",
+        "prosemirror-commands": "^1.0.0",
+        "prosemirror-history": "^1.0.0",
+        "prosemirror-state": "^1.0.0"
       }
     },
     "prosemirror-model": {
@@ -10617,8 +10307,8 @@
       "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.0.2.tgz",
       "integrity": "sha512-IJ4DEpUEymfO+NNA4DAgCMF39XiQqpmCoPYY3SXa1jYcVgObGpGfJlSjZYVFEpimoLI7/mLoOLDhCtpGCRhTfg==",
       "requires": {
-        "prosemirror-model": "1.7.0",
-        "prosemirror-transform": "1.1.3"
+        "prosemirror-model": "^1.0.0",
+        "prosemirror-transform": "^1.0.0"
       }
     },
     "prosemirror-state": {
@@ -10684,12 +10374,12 @@
       "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
       "dev": true,
       "requires": {
-        "bn.js": "4.11.8",
-        "browserify-rsa": "4.0.1",
-        "create-hash": "1.2.0",
-        "parse-asn1": "5.1.3",
-        "randombytes": "2.0.6",
-        "safe-buffer": "5.1.2"
+        "bn.js": "^4.1.0",
+        "browserify-rsa": "^4.0.0",
+        "create-hash": "^1.1.0",
+        "parse-asn1": "^5.0.0",
+        "randombytes": "^2.0.1",
+        "safe-buffer": "^5.1.2"
       }
     },
     "pug": {
@@ -10697,14 +10387,14 @@
       "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.3.tgz",
       "integrity": "sha1-ccuoJTfJWl6rftBGluQiH1Oqh44=",
       "requires": {
-        "pug-code-gen": "2.0.1",
-        "pug-filters": "3.1.0",
-        "pug-lexer": "4.0.0",
-        "pug-linker": "3.0.5",
-        "pug-load": "2.0.11",
-        "pug-parser": "5.0.0",
-        "pug-runtime": "2.0.4",
-        "pug-strip-comments": "1.0.3"
+        "pug-code-gen": "^2.0.1",
+        "pug-filters": "^3.1.0",
+        "pug-lexer": "^4.0.0",
+        "pug-linker": "^3.0.5",
+        "pug-load": "^2.0.11",
+        "pug-parser": "^5.0.0",
+        "pug-runtime": "^2.0.4",
+        "pug-strip-comments": "^1.0.3"
       }
     },
     "pug-attrs": {
@@ -10712,9 +10402,9 @@
       "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.3.tgz",
       "integrity": "sha1-owlflw5kFR972tlX7vVftdeQXRU=",
       "requires": {
-        "constantinople": "3.1.2",
-        "js-stringify": "1.0.2",
-        "pug-runtime": "2.0.4"
+        "constantinople": "^3.0.1",
+        "js-stringify": "^1.0.1",
+        "pug-runtime": "^2.0.4"
       }
     },
     "pug-code-gen": {
@@ -10722,14 +10412,14 @@
       "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.1.tgz",
       "integrity": "sha1-CVHsgyJddNjPxHan+Zolm199BQw=",
       "requires": {
-        "constantinople": "3.1.2",
-        "doctypes": "1.1.0",
-        "js-stringify": "1.0.2",
-        "pug-attrs": "2.0.3",
-        "pug-error": "1.3.2",
-        "pug-runtime": "2.0.4",
-        "void-elements": "2.0.1",
-        "with": "5.1.1"
+        "constantinople": "^3.0.1",
+        "doctypes": "^1.1.0",
+        "js-stringify": "^1.0.1",
+        "pug-attrs": "^2.0.3",
+        "pug-error": "^1.3.2",
+        "pug-runtime": "^2.0.4",
+        "void-elements": "^2.0.1",
+        "with": "^5.0.0"
       }
     },
     "pug-error": {
@@ -10742,13 +10432,13 @@
       "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.0.tgz",
       "integrity": "sha1-JxZVVbwEwjbkqisDZiRt+gIbYm4=",
       "requires": {
-        "clean-css": "4.2.1",
-        "constantinople": "3.1.2",
+        "clean-css": "^4.1.11",
+        "constantinople": "^3.0.1",
         "jstransformer": "1.0.0",
-        "pug-error": "1.3.2",
-        "pug-walk": "1.1.7",
-        "resolve": "1.10.0",
-        "uglify-js": "2.8.29"
+        "pug-error": "^1.3.2",
+        "pug-walk": "^1.1.7",
+        "resolve": "^1.1.6",
+        "uglify-js": "^2.6.1"
       }
     },
     "pug-lexer": {
@@ -10756,9 +10446,9 @@
       "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.0.0.tgz",
       "integrity": "sha1-IQwYRX7y4XYCQnQMXmR715TOwng=",
       "requires": {
-        "character-parser": "2.2.0",
-        "is-expression": "3.0.0",
-        "pug-error": "1.3.2"
+        "character-parser": "^2.1.1",
+        "is-expression": "^3.0.0",
+        "pug-error": "^1.3.2"
       }
     },
     "pug-linker": {
@@ -10766,8 +10456,8 @@
       "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.5.tgz",
       "integrity": "sha1-npp65ABWgtAn3uuWsAD4juuDoC8=",
       "requires": {
-        "pug-error": "1.3.2",
-        "pug-walk": "1.1.7"
+        "pug-error": "^1.3.2",
+        "pug-walk": "^1.1.7"
       }
     },
     "pug-load": {
@@ -10775,8 +10465,8 @@
       "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.11.tgz",
       "integrity": "sha1-5kjlftET/iwfRdV4WOorrWvAFSc=",
       "requires": {
-        "object-assign": "4.1.1",
-        "pug-walk": "1.1.7"
+        "object-assign": "^4.1.0",
+        "pug-walk": "^1.1.7"
       }
     },
     "pug-parser": {
@@ -10784,7 +10474,7 @@
       "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.0.tgz",
       "integrity": "sha1-45Stmz/KkxI5QK/4hcBuRKt+aOQ=",
       "requires": {
-        "pug-error": "1.3.2",
+        "pug-error": "^1.3.2",
         "token-stream": "0.0.1"
       }
     },
@@ -10798,16 +10488,7 @@
       "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz",
       "integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=",
       "requires": {
-<<<<<<< HEAD
-        "bn.js": "^4.1.0",
-        "browserify-rsa": "^4.0.0",
-        "create-hash": "^1.1.0",
-        "parse-asn1": "^5.0.0",
-        "randombytes": "^2.0.1",
-        "safe-buffer": "^5.1.2"
-=======
-        "pug-error": "1.3.2"
->>>>>>> 96eede5f7d1706a3f7ac6ee02a85bb3da217f467
+        "pug-error": "^1.3.2"
       }
     },
     "pug-walk": {
@@ -10914,8 +10595,8 @@
       "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-1.0.0.tgz",
       "integrity": "sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA==",
       "requires": {
-        "loader-utils": "1.2.3",
-        "schema-utils": "1.0.0"
+        "loader-utils": "^1.1.0",
+        "schema-utils": "^1.0.0"
       }
     },
     "rc": {
@@ -10945,26 +10626,17 @@
         "scheduler": "^0.12.0"
       }
     },
-    "react-contenteditable": {
-      "version": "3.2.6",
-      "resolved": "https://registry.npmjs.org/react-contenteditable/-/react-contenteditable-3.2.6.tgz",
-      "integrity": "sha512-jmr/wnuaU0teJ7U5ePUtEV4xDqaJS3jAFaXMF/3Dyr0COLV6gegcH0Yj727BdT7DnHWVoXVpR7m1s9hDgmSBTw==",
-      "requires": {
-        "@types/prop-types": "^15.5.6",
-        "fast-deep-equal": "^2.0.1"
-      }
-    },
     "react-color": {
       "version": "2.17.0",
       "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.17.0.tgz",
       "integrity": "sha512-kJfE5tSaFe6GzalXOHksVjqwCPAsTl+nzS9/BWfP7j3EXbQ4IiLAF9sZGNzk3uq7HfofGYgjmcUgh0JP7xAQ0w==",
       "requires": {
-        "@icons/material": "0.2.4",
-        "lodash": "4.17.11",
-        "material-colors": "1.2.6",
-        "prop-types": "15.6.2",
-        "reactcss": "1.2.3",
-        "tinycolor2": "1.4.1"
+        "@icons/material": "^0.2.4",
+        "lodash": ">4.17.4",
+        "material-colors": "^1.2.1",
+        "prop-types": "^15.5.10",
+        "reactcss": "^1.2.0",
+        "tinycolor2": "^1.4.1"
       }
     },
     "react-dimensions": {
@@ -10991,8 +10663,8 @@
       "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-3.2.1.tgz",
       "integrity": "sha512-r+3Bs9InID2lyIEbR8UIRVtpn4jgu1ArFEZgIy8vibJjijLSdNLX7rH9U68BBVD4RD9v44RXbaK4EHLyKXzNQw==",
       "requires": {
-        "classnames": "2.2.6",
-        "prop-types": "15.6.2"
+        "classnames": "^2.2.5",
+        "prop-types": "^15.6.0"
       }
     },
     "react-golden-layout": {
@@ -11069,12 +10741,12 @@
       "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-4.0.5.tgz",
       "integrity": "sha512-hoIL08qU5pU1fNEx6NnLl3omD08LAUc+UkmxGXEql/PXiNWjMZHWlu8MSVg9pwSTN6dXtfky0gehrisWvSOrCg==",
       "requires": {
-        "@babel/runtime": "7.3.1",
-        "lodash.once": "4.1.1",
-        "make-event-props": "1.2.0",
-        "merge-class-names": "1.1.1",
+        "@babel/runtime": "^7.0.0",
+        "lodash.once": "^4.1.1",
+        "make-event-props": "^1.1.0",
+        "merge-class-names": "^1.1.1",
         "pdfjs-dist": "2.1.266",
-        "prop-types": "15.6.2"
+        "prop-types": "^15.6.2"
       }
     },
     "react-pdf-highlighter": {
@@ -11082,10 +10754,10 @@
       "resolved": "https://registry.npmjs.org/react-pdf-highlighter/-/react-pdf-highlighter-2.1.2.tgz",
       "integrity": "sha512-aKa/rzpFjOywcRmNyfupvrGdh7mp0VGS9RKCWDbD9p32+P3+DhJvQe/2qCvDAnTXa4LmabNqM+O0RDUcai1C1Q==",
       "requires": {
-        "lodash": "4.17.11",
+        "lodash": "^4.17.10",
         "pdfjs-dist": "2.0.489",
-        "react-pointable": "1.1.3",
-        "react-rnd": "7.4.3"
+        "react-pointable": "^1.1.1",
+        "react-rnd": "^7.1.5"
       },
       "dependencies": {
         "pdfjs-dist": {
@@ -11093,8 +10765,8 @@
           "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.0.489.tgz",
           "integrity": "sha1-Y+VLKSqGeQpFRpfrRNQ0e4+/rSc=",
           "requires": {
-            "node-ensure": "0.0.0",
-            "worker-loader": "1.1.1"
+            "node-ensure": "^0.0.0",
+            "worker-loader": "^1.1.1"
           }
         },
         "schema-utils": {
@@ -11102,8 +10774,8 @@
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
           "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
           "requires": {
-            "ajv": "6.8.1",
-            "ajv-keywords": "3.3.0"
+            "ajv": "^6.1.0",
+            "ajv-keywords": "^3.1.0"
           }
         },
         "worker-loader": {
@@ -11111,8 +10783,8 @@
           "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-1.1.1.tgz",
           "integrity": "sha512-qJZLVS/jMCBITDzPo/RuweYSIG8VJP5P67mP/71alGyTZRe1LYJFdwLjLalY3T5ifx0bMDRD3OB6P2p1escvlg==",
           "requires": {
-            "loader-utils": "1.2.3",
-            "schema-utils": "0.4.7"
+            "loader-utils": "^1.0.0",
+            "schema-utils": "^0.4.0"
           }
         }
       }
@@ -11130,8 +10802,8 @@
           "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.0.943.tgz",
           "integrity": "sha512-iLhNcm4XceTHRaSU5o22ZGCm4YpuW5+rf4+BJFH/feBhMQLbCGBry+Jet8Q419QDI4qgARaIQzXuiNrsNWS8Yw==",
           "requires": {
-            "node-ensure": "0.0.0",
-            "worker-loader": "2.0.0"
+            "node-ensure": "^0.0.0",
+            "worker-loader": "^2.0.0"
           }
         }
       }
@@ -11147,7 +10819,7 @@
       "integrity": "sha512-TLQ35nqXup7rC63qAETebbO6Znilr20CroTTeAdlYu8nvRSwB7BrmPKZhHB2GgeiSucOoeCyAA9pHPhbMpEd/Q==",
       "requires": {
         "re-resizable": "4.5.1",
-        "react-draggable": "3.2.1"
+        "react-draggable": "^3.0.5"
       }
     },
     "react-split-pane": {
@@ -11183,7 +10855,7 @@
       "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz",
       "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==",
       "requires": {
-        "lodash": "4.17.11"
+        "lodash": "^4.0.1"
       }
     },
     "read-pkg": {
@@ -11389,8 +11061,8 @@
       "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
       "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
       "requires": {
-        "resolve-from": "2.0.0",
-        "semver": "5.6.0"
+        "resolve-from": "^2.0.0",
+        "semver": "^5.1.0"
       },
       "dependencies": {
         "resolve-from": {
@@ -11416,7 +11088,7 @@
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
       "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
       "requires": {
-        "path-parse": "1.0.6"
+        "path-parse": "^1.0.6"
       }
     },
     "resolve-cwd": {
@@ -11459,7 +11131,7 @@
       "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
       "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
       "requires": {
-        "align-text": "0.1.4"
+        "align-text": "^0.1.1"
       }
     },
     "rimraf": {
@@ -11518,7 +11190,7 @@
       "integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==",
       "optional": true,
       "requires": {
-        "sparse-bitfield": "3.0.3"
+        "sparse-bitfield": "^3.0.3"
       }
     },
     "sass-graph": {
@@ -11877,12 +11549,12 @@
       "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz",
       "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==",
       "requires": {
-        "debug": "4.1.1",
-        "engine.io": "3.3.2",
-        "has-binary2": "1.0.3",
-        "socket.io-adapter": "1.1.1",
+        "debug": "~4.1.0",
+        "engine.io": "~3.3.1",
+        "has-binary2": "~1.0.2",
+        "socket.io-adapter": "~1.1.0",
         "socket.io-client": "2.2.0",
-        "socket.io-parser": "3.3.0"
+        "socket.io-parser": "~3.3.0"
       },
       "dependencies": {
         "debug": {
@@ -11890,7 +11562,7 @@
           "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
           "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "requires": {
-            "ms": "2.1.1"
+            "ms": "^2.1.1"
           }
         },
         "ms": {
@@ -11914,15 +11586,15 @@
         "base64-arraybuffer": "0.1.5",
         "component-bind": "1.0.0",
         "component-emitter": "1.2.1",
-        "debug": "3.1.0",
-        "engine.io-client": "3.3.2",
-        "has-binary2": "1.0.3",
+        "debug": "~3.1.0",
+        "engine.io-client": "~3.3.1",
+        "has-binary2": "~1.0.2",
         "has-cors": "1.1.0",
         "indexof": "0.0.1",
         "object-component": "0.0.3",
         "parseqs": "0.0.5",
         "parseuri": "0.0.5",
-        "socket.io-parser": "3.3.0",
+        "socket.io-parser": "~3.3.0",
         "to-array": "0.1.4"
       },
       "dependencies": {
@@ -11942,7 +11614,7 @@
       "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
       "requires": {
         "component-emitter": "1.2.1",
-        "debug": "3.1.0",
+        "debug": "~3.1.0",
         "isarray": "2.0.1"
       },
       "dependencies": {
@@ -12066,7 +11738,7 @@
       "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
       "optional": true,
       "requires": {
-        "memory-pager": "1.5.0"
+        "memory-pager": "^1.0.2"
       }
     },
     "spdx-correct": {
@@ -12825,9 +12497,9 @@
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
       "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
       "requires": {
-        "source-map": "0.5.7",
-        "uglify-to-browserify": "1.0.2",
-        "yargs": "3.10.0"
+        "source-map": "~0.5.1",
+        "uglify-to-browserify": "~1.0.0",
+        "yargs": "~3.10.0"
       },
       "dependencies": {
         "camelcase": {
@@ -12840,8 +12512,8 @@
           "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
           "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
           "requires": {
-            "center-align": "0.1.3",
-            "right-align": "0.1.3",
+            "center-align": "^0.1.1",
+            "right-align": "^0.1.1",
             "wordwrap": "0.0.2"
           }
         },
@@ -12855,9 +12527,9 @@
           "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
           "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
           "requires": {
-            "camelcase": "1.2.1",
-            "cliui": "2.1.0",
-            "decamelize": "1.2.0",
+            "camelcase": "^1.0.2",
+            "cliui": "^2.1.0",
+            "decamelize": "^1.0.0",
             "window-size": "0.1.0"
           }
         }
@@ -12874,7 +12546,7 @@
       "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
       "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
       "requires": {
-        "random-bytes": "1.0.0"
+        "random-bytes": "~1.0.0"
       }
     },
     "undefsafe": {
@@ -13489,7 +13161,7 @@
       "integrity": "sha512-oeXA3m+5gbYbDBGo4SvKpAHJJEGMoekUbHgo1RK7CP1sz7/WOSeu/dWJtSTk+rzDCLkPwQhGocgIq6lQqOyOwg==",
       "dev": true,
       "requires": {
-        "memory-fs": "~0.4.1",
+        "memory-fs": "^0.4.1",
         "mime": "^2.3.1",
         "range-parser": "^1.0.3",
         "webpack-log": "^2.0.0"
@@ -13935,8 +13607,8 @@
       "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz",
       "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=",
       "requires": {
-        "acorn": "3.3.0",
-        "acorn-globals": "3.1.0"
+        "acorn": "^3.1.0",
+        "acorn-globals": "^3.0.0"
       },
       "dependencies": {
         "acorn": {
@@ -13965,8 +13637,8 @@
       "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz",
       "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==",
       "requires": {
-        "loader-utils": "1.2.3",
-        "schema-utils": "0.4.7"
+        "loader-utils": "^1.0.0",
+        "schema-utils": "^0.4.0"
       },
       "dependencies": {
         "schema-utils": {
@@ -13974,8 +13646,8 @@
           "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
           "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
           "requires": {
-            "ajv": "6.8.1",
-            "ajv-keywords": "3.3.0"
+            "ajv": "^6.1.0",
+            "ajv-keywords": "^3.1.0"
           }
         }
       }
@@ -14009,7 +13681,7 @@
       "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz",
       "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==",
       "requires": {
-        "async-limiter": "1.0.0"
+        "async-limiter": "~1.0.0"
       }
     },
     "xdg-basedir": {
diff --git a/package.json b/package.json
index e1a9cc6fb..f20f9d427 100644
--- a/package.json
+++ b/package.json
@@ -131,4 +131,4 @@
     "url-loader": "^1.1.2",
     "uuid": "^3.3.2"
   }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 3b2cd2626..84009907a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -4,11 +4,15 @@ import { SelectionManager } from "../util/SelectionManager";
 import { observer } from "mobx-react";
 import './DocumentDecorations.scss'
 import { CollectionFreeFormView } from "./collections/CollectionFreeFormView";
-import ContentEditable from 'react-contenteditable'
+//import ContentEditable from 'react-contenteditable'
 import { KeyStore } from "../../fields/KeyStore";
 import { NumberField } from "../../fields/NumberField";
 import { Document } from "../../fields/Document";
 import { DocumentView } from "./nodes/DocumentView";
+import { Key } from "../../fields/Key";
+import { TextField } from "../../fields/TextField";
+import { BasicField } from "../../fields/BasicField";
+import { Field, FieldValue } from "../../fields/Field";
 
 @observer
 export class DocumentDecorations extends React.Component<{}, { value: string }> {
@@ -17,23 +21,21 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     private _isPointerDown = false;
     @observable private _opacity = 1;
     private keyinput: React.RefObject<HTMLInputElement>;
-    @observable private _documents: DocumentView[] = [];
+    private _documents: DocumentView[] = SelectionManager.SelectedDocuments();
     //@observable private _title: string = this._documents[0].props.Document.Title;
-    @observable private _title: string = document.title;
+    @observable private _title: string = this._documents.length > 0 ? this._documents[0].props.Document.Title : "";
+    @observable private _fieldKey: Key = KeyStore.Title;
 
     constructor(props: Readonly<{}>) {
         super(props)
         DocumentDecorations.Instance = this
-        this.state = { value: document.title };
         this.handleChange = this.handleChange.bind(this);
         this.keyinput = React.createRef();
     }
 
     @action
     handleChange = (event: any) => {
-        //this.setState({ value: event.target.value });
         this._title = event.target.value;
-        console.log("Input box has changed");
     };
 
     @action
@@ -44,19 +46,18 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             var text = e.target.value;
             if (text[0] == '#') {
                 let command = text.slice(1, text.length);
-                if (command == "Title" || command == "title") {
-                    this._title = this._documents[0].props.Document.Title;
-                }
-                else if (command == "Width" || command == "width") {
-                    this._title = this._documents[0].props.Document.GetNumber(KeyStore.Width, 0).toString();
-                }
-                else {
-                    this._title = "undefined key";
-                }
+                this._fieldKey = new Key(command)
+                // if (command == "Title" || command == "title") {
+                //     this._fieldKey = KeyStore.Title;
+                // }
+                // else if (command == "Width" || command == "width") {
+                //     this._fieldKey = KeyStore.Width;
+                // }
+                this._title = "changed"
                 // TODO: Change field with switch statement
             }
             else {
-                this._title = document.title;
+                this._title = "changed";
             }
             e.target.blur();
         }
@@ -184,8 +185,24 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
     }
 
+    getValue = (): string => {
+        console.log("value watched");
+        if (this._title === "changed" && this._documents.length > 0) {
+            let field = this._documents[0].props.Document.Get(this._fieldKey);
+            if (field instanceof TextField) {
+                return (field as TextField).GetValue();
+            }
+            else if (field instanceof NumberField) {
+                return (field as NumberField).GetValue().toString();
+            }
+        }
+        return this._title;
+    }
+
     render() {
         var bounds = this.Bounds;
+        // console.log(this._documents.length)
+        // let test = this._documents[0].props.Document.Title;
         if (this.Hidden) {
             return (null);
         }
@@ -201,7 +218,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 top: bounds.y - 20 - 20,
                 opacity: this._opacity
             }}>
-                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this._title} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
+                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-- 
cgit v1.2.3-70-g09d2


From 8448679e0a260ec881c54a10578bc464cd38f04e Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 1 Apr 2019 17:05:42 -0400
Subject: added dragging multiple items.

---
 src/client/northstar/dash-nodes/HistogramBox.tsx   |   4 +-
 src/client/util/DragManager.ts                     | 168 +++++++++++----------
 src/client/views/DocumentDecorations.scss          |   6 +
 src/client/views/DocumentDecorations.tsx           | 109 +++++++++----
 src/client/views/Main.tsx                          |   7 +-
 .../views/collections/CollectionDockingView.tsx    |  11 +-
 src/client/views/collections/CollectionView.tsx    |   2 +-
 .../views/collections/CollectionViewBase.tsx       |   4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  21 ++-
 src/client/views/nodes/DocumentView.tsx            |  15 +-
 10 files changed, 213 insertions(+), 134 deletions(-)

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

diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index a968def96..49ebe5ebc 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -54,7 +54,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
     @action
     dropX = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.DocumentDragData) {
-            let h = de.data.draggedDocument.GetT(KeyStore.Data, HistogramField);
+            let h = de.data.draggedDocuments[0].GetT(KeyStore.Data, HistogramField);
             if (h && h != FieldWaiting) {
                 this.HistoOp.X = h.Data.X;
             }
@@ -65,7 +65,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
     @action
     dropY = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.DocumentDragData) {
-            let h = de.data.draggedDocument.GetT(KeyStore.Data, HistogramField);
+            let h = de.data.draggedDocuments[0].GetT(KeyStore.Data, HistogramField);
             if (h && h != FieldWaiting) {
                 this.HistoOp.Y = h.Data.X;
             }
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 70b1c9829..9ffe964ef 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -14,9 +14,9 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
 
         document.removeEventListener("pointermove", onRowMove);
         document.removeEventListener('pointerup', onRowUp);
-        var dragData = new DragManager.DocumentDragData(docFunc());
+        var dragData = new DragManager.DocumentDragData([docFunc()]);
         dragData.removeDocument = removeFunc;
-        DragManager.StartDocumentDrag(_reference.current!, dragData);
+        DragManager.StartDocumentDrag([_reference.current!], dragData);
     });
     let onRowUp = action((e: PointerEvent): void => {
         document.removeEventListener("pointermove", onRowMove);
@@ -27,7 +27,7 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
         if (e.button == 0) {
             e.stopPropagation();
             if (e.shiftKey) {
-                CollectionDockingView.Instance.StartOtherDrag(docFunc(), e);
+                CollectionDockingView.Instance.StartOtherDrag([docFunc()], e);
             } else {
                 document.addEventListener("pointermove", onRowMove);
                 document.addEventListener('pointerup', onRowUp);
@@ -101,20 +101,21 @@ export namespace DragManager {
     }
 
     export class DocumentDragData {
-        constructor(dragDoc: Document) {
-            this.draggedDocument = dragDoc;
-            this.droppedDocument = dragDoc;
+        constructor(dragDoc: Document[]) {
+            this.draggedDocuments = dragDoc;
+            this.droppedDocuments = dragDoc;
         }
-        draggedDocument: Document;
-        droppedDocument: Document;
+        draggedDocuments: Document[];
+        droppedDocuments: Document[];
         xOffset?: number;
         yOffset?: number;
         aliasOnDrop?: boolean;
         removeDocument?: (collectionDrop: CollectionView) => void;
         [id: string]: any;
     }
-    export function StartDocumentDrag(ele: HTMLElement, dragData: DocumentDragData, options?: DragOptions) {
-        StartDrag(ele, dragData, options, (dropData: { [id: string]: any }) => dropData.droppedDocument = dragData.aliasOnDrop ? dragData.draggedDocument.CreateAlias() : dragData.draggedDocument);
+
+    export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, options?: DragOptions) {
+        StartDrag(eles, dragData, options, (dropData: { [id: string]: any }) => dropData.droppedDocuments = dragData.aliasOnDrop ? dragData.draggedDocuments.map(d => d.CreateAlias()) : dragData.draggedDocuments);
     }
 
     export class LinkDragData {
@@ -125,49 +126,58 @@ export namespace DragManager {
         [id: string]: any;
     }
     export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, options?: DragOptions) {
-        StartDrag(ele, dragData, options);
+        StartDrag([ele], dragData, options);
     }
-    function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) {
+    function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) {
         if (!dragDiv) {
             dragDiv = document.createElement("div");
             dragDiv.className = "dragManager-dragDiv"
             DragManager.Root().appendChild(dragDiv);
         }
-        const w = ele.offsetWidth, h = ele.offsetHeight;
-        const rect = ele.getBoundingClientRect();
-        const scaleX = rect.width / w, scaleY = rect.height / h;
-        let x = rect.left, y = rect.top;
-        // const offsetX = e.x - rect.left, offsetY = e.y - rect.top;
-
-        let dragElement = ele.cloneNode(true) as HTMLElement;
-        dragElement.style.opacity = "0.7";
-        dragElement.style.position = "absolute";
-        dragElement.style.bottom = "";
-        dragElement.style.left = "";
-        dragElement.style.transformOrigin = "0 0";
-        dragElement.style.zIndex = "1000";
-        dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
-        dragElement.style.width = `${rect.width / scaleX}px`;
-        dragElement.style.height = `${rect.height / scaleY}px`;
-
-        // bcz: PDFs don't show up if you clone them because they contain a canvas.
-        //      however, PDF's have a thumbnail field that contains an image of their canvas.
-        //      So we replace the pdf's canvas with the image thumbnail
-        const doc: Document = dragData["draggedDocument"];
-        if (doc) {
-            var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement;
-            let thumbnail = doc.GetT(KeyStore.Thumbnail, ImageField);
-            if (pdfBox && pdfBox.childElementCount && thumbnail) {
-                let img = new Image();
-                img!.src = thumbnail.toString();
-                img!.style.position = "absolute";
-                img!.style.width = `${rect.width / scaleX}px`;
-                img!.style.height = `${rect.height / scaleY}px`;
-                pdfBox.replaceChild(img!, pdfBox.children[0])
+
+        let scaleXs: number[] = [];
+        let scaleYs: number[] = [];
+        let xs: number[] = [];
+        let ys: number[] = [];
+
+        const docs: Document[] = dragData instanceof DocumentDragData ? dragData.draggedDocuments : [];
+        let dragElements = eles.map(ele => {
+            const w = ele.offsetWidth, h = ele.offsetHeight;
+            const rect = ele.getBoundingClientRect();
+            const scaleX = rect.width / w, scaleY = rect.height / h;
+            let x = rect.left, y = rect.top;
+            xs.push(x); ys.push(y);
+            scaleXs.push(scaleX); scaleYs.push(scaleY);
+            let dragElement = ele.cloneNode(true) as HTMLElement;
+            dragElement.style.opacity = "0.7";
+            dragElement.style.position = "absolute";
+            dragElement.style.bottom = "";
+            dragElement.style.left = "";
+            dragElement.style.transformOrigin = "0 0";
+            dragElement.style.zIndex = "1000";
+            dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
+            dragElement.style.width = `${rect.width / scaleX}px`;
+            dragElement.style.height = `${rect.height / scaleY}px`;
+
+            // bcz: PDFs don't show up if you clone them because they contain a canvas.
+            //      however, PDF's have a thumbnail field that contains an image of their canvas.
+            //      So we replace the pdf's canvas with the image thumbnail
+            if (docs.length) {
+                var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement;
+                let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
+                if (pdfBox && pdfBox.childElementCount && thumbnail) {
+                    let img = new Image();
+                    img!.src = thumbnail.toString();
+                    img!.style.position = "absolute";
+                    img!.style.width = `${rect.width / scaleX}px`;
+                    img!.style.height = `${rect.height / scaleY}px`;
+                    pdfBox.replaceChild(img!, pdfBox.children[0])
+                }
             }
-        }
 
-        dragDiv.appendChild(dragElement);
+            dragDiv.appendChild(dragElement);
+            return dragElement;
+        });
 
         let hideSource = false;
         if (options) {
@@ -177,62 +187,64 @@ export namespace DragManager {
                 hideSource = options.hideSource();
             }
         }
-        const wasHidden = ele.hidden;
-        if (hideSource) {
-            ele.hidden = true;
-        }
+        eles.map(ele => ele.hidden = hideSource);
+
         const moveHandler = (e: PointerEvent) => {
             e.stopPropagation();
             e.preventDefault();
-            x += e.movementX;
-            y += e.movementY;
             if (dragData instanceof DocumentDragData)
                 dragData.aliasOnDrop = e.ctrlKey || e.altKey;
             if (e.shiftKey) {
                 abortDrag();
-                CollectionDockingView.Instance.StartOtherDrag(doc, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 });
+                CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 });
             }
-            dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
+            dragElements.map((dragElement, i) => dragElement.style.transform = `translate(${xs[i] += e.movementX}px, ${ys[i] += e.movementY}px) scale(${scaleXs[i]}, ${scaleYs[i]})`);
         };
 
         const abortDrag = () => {
             document.removeEventListener("pointermove", moveHandler, true);
             document.removeEventListener("pointerup", upHandler);
-            dragDiv.removeChild(dragElement);
-            ele.hidden = false;
+            dragElements.map(dragElement => dragDiv.removeChild(dragElement));
+            eles.map(ele => ele.hidden = false);
         }
         const upHandler = (e: PointerEvent) => {
             abortDrag();
-            FinishDrag(ele, e, dragData, options, finishDrag);
+            FinishDrag(eles, e, dragData, options, finishDrag);
         };
         document.addEventListener("pointermove", moveHandler, true);
         document.addEventListener("pointerup", upHandler);
     }
 
-    function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) {
-        let parent = dragEle.parentElement;
-        if (parent)
-            parent.removeChild(dragEle);
+    function FinishDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) {
+        let removed = dragEles.map(dragEle => {
+            let parent = dragEle.parentElement;
+            if (parent)
+                parent.removeChild(dragEle);
+            return [dragEle, parent];
+        });
         const target = document.elementFromPoint(e.x, e.y);
-        if (parent)
-            parent.appendChild(dragEle);
-        if (!target) {
-            return;
-        }
-        if (finishDrag)
-            finishDrag(dragData);
-
-        target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", {
-            bubbles: true,
-            detail: {
-                x: e.x,
-                y: e.y,
-                data: dragData
+        removed.map(r => {
+            let dragEle: HTMLElement = r[0]!;
+            let parent: HTMLElement | null = r[1];
+            if (parent)
+                parent.appendChild(dragEle);
+        });
+        if (target) {
+            if (finishDrag)
+                finishDrag(dragData);
+
+            target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", {
+                bubbles: true,
+                detail: {
+                    x: e.x,
+                    y: e.y,
+                    data: dragData
+                }
+            }));
+
+            if (options) {
+                options.handlers.dragComplete({});
             }
-        }));
-
-        if (options) {
-            options.handlers.dragComplete({});
         }
         DocumentDecorations.Instance.Hidden = false;
     }
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 11595aa01..7a43f3087 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -32,6 +32,12 @@
     }
 }
 
+.documentDecorations-background {
+    background:lightblue;
+    position: absolute;
+    opacity: 0.1;
+}
+
 //     position: absolute;
 //     display: grid;
 //     z-index: 1000;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 47098c3b5..faba3b6ea 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,14 +1,14 @@
-import { observable, computed, action } from "mobx";
-import React = require("react");
-import { SelectionManager } from "../util/SelectionManager";
+import { action, computed, observable, trace } from "mobx";
 import { observer } from "mobx-react";
-import './DocumentDecorations.scss'
-import { KeyStore } from '../../fields/KeyStore'
+import { KeyStore } from '../../fields/KeyStore';
+import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
-import { props } from "bluebird";
 import { DragManager } from "../util/DragManager";
+import { SelectionManager } from "../util/SelectionManager";
+import { CollectionView } from "./collections/CollectionView";
+import './DocumentDecorations.scss';
 import { LinkMenu } from "./nodes/LinkMenu";
-import { ListField } from "../../fields/ListField";
+import React = require("react");
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -22,6 +22,7 @@ export class DocumentDecorations extends React.Component {
     private _resizeBorderWidth = 16;
     private _linkButton = React.createRef<HTMLDivElement>();
     @observable private _hidden = false;
+    @observable private _dragging = false;
 
     constructor(props: Readonly<{}>) {
         super(props)
@@ -50,6 +51,50 @@ export class DocumentDecorations extends React.Component {
     public get Hidden() { return this._hidden; }
     public set Hidden(value: boolean) { this._hidden = value; }
 
+    _lastDrag: number[] = [0, 0];
+    onBackgroundDown = (e: React.PointerEvent): void => {
+        document.removeEventListener("pointermove", this.onBackgroundMove);
+        document.addEventListener("pointermove", this.onBackgroundMove);
+        document.removeEventListener("pointerup", this.onBackgroundUp);
+        document.addEventListener("pointerup", this.onBackgroundUp);
+        this._lastDrag = [e.clientX, e.clientY]
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    @action
+    onBackgroundMove = (e: PointerEvent): void => {
+        let dragDocView = SelectionManager.SelectedDocuments()[0];
+        const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+        let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
+        dragData.aliasOnDrop = false;
+        dragData.xOffset = e.x - left;
+        dragData.yOffset = e.y - top;
+        dragData.removeDocument = (dropCollectionView: CollectionView) =>
+            dragData.draggedDocuments.map(d => {
+                if (dragDocView.props.RemoveDocument && dragDocView.props.ContainingCollectionView !== dropCollectionView) {
+                    dragDocView.props.RemoveDocument(d);
+                }
+            });
+        this._dragging = true;
+        document.removeEventListener("pointermove", this.onBackgroundMove);
+        document.removeEventListener("pointerup", this.onBackgroundUp);
+        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData, {
+            handlers: {
+                dragComplete: action(() => this._dragging = false),
+            },
+            hideSource: true
+        })
+        e.stopPropagation();
+    }
+
+    onBackgroundUp = (e: PointerEvent): void => {
+        document.removeEventListener("pointermove", this.onBackgroundMove);
+        document.removeEventListener("pointerup", this.onBackgroundUp);
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
     onPointerDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
         if (e.button === 0) {
@@ -191,7 +236,6 @@ export class DocumentDecorations extends React.Component {
     // buttonOnPointerUp = (e: React.PointerEvent): void => {
     //     e.stopPropagation();
     // }
-
     render() {
         var bounds = this.Bounds;
         if (this.Hidden) {
@@ -218,25 +262,36 @@ export class DocumentDecorations extends React.Component {
             </Flyout>);
         }
         return (
-            <div id="documentDecorations-container" style={{
-                width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
-                height: (bounds.b - bounds.y + this._resizeBorderWidth + 30) + "px",
-                left: bounds.x - this._resizeBorderWidth / 2,
-                top: bounds.y - this._resizeBorderWidth / 2,
-            }}>
-                <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                <div id="documentDecorations-leftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                <div id="documentDecorations-centerCont"></div>
-                <div id="documentDecorations-rightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-                <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-
-                <div title="View Links" className="linkFlyout" ref={this._linkButton}>{linkButton}</div>
-
-            </div >
+            <div className="documentDecorations">
+                <div className="documentDecorations-background" style={{
+                    width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
+                    height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px",
+                    left: bounds.x - this._resizeBorderWidth / 2,
+                    top: bounds.y - this._resizeBorderWidth / 2,
+                    pointerEvents: this._dragging ? "none" : "all",
+                    zIndex: SelectionManager.SelectedDocuments().length > 1 ? 1000 : 0,
+                }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation() }} >
+                </div>
+                <div id="documentDecorations-container" style={{
+                    width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
+                    height: (bounds.b - bounds.y + this._resizeBorderWidth + 30) + "px",
+                    left: bounds.x - this._resizeBorderWidth / 2,
+                    top: bounds.y - this._resizeBorderWidth / 2,
+                }}>
+                    <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                    <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                    <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                    <div id="documentDecorations-leftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                    <div id="documentDecorations-centerCont"></div>
+                    <div id="documentDecorations-rightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                    <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                    <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                    <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+
+                    <div title="View Links" className="linkFlyout" ref={this._linkButton}>{linkButton}</div>
+
+                </div >
+            </div>
         )
     }
 }
\ No newline at end of file
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 75855c3d1..6f66f8f38 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -218,7 +218,8 @@ export class Main extends React.Component {
     focusDocument = (doc: Document) => { }
     noScaling = () => 1;
 
-    get content() {
+    @computed
+    get mainContent() {
         return !this.mainContainer ? (null) :
             <DocumentView Document={this.mainContainer}
                 AddDocument={undefined}
@@ -311,17 +312,17 @@ export class Main extends React.Component {
         }
         return (
             <div id="main-div">
+                <DocumentDecorations />
                 <Measure onResize={(r: any) => runInAction(() => {
                     this.pwidth = r.entry.width;
                     this.pheight = r.entry.height;
                 })}>
                     {({ measureRef }) =>
                         <div ref={measureRef} id="mainContent-div">
-                            {this.content}
+                            {this.mainContent}
                         </div>
                     }
                 </Measure>
-                <DocumentDecorations />
                 <ContextMenu />
                 {this.nodesMenu}
                 {this.miscButtons}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f123149dd..c6cbc05e7 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -47,9 +47,10 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         (window as any).React = React;
         (window as any).ReactDOM = ReactDOM;
     }
-    public StartOtherDrag(dragDoc: Document, e: any) {
-        this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.
-            onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 })
+    public StartOtherDrag(dragDocs: Document[], e: any) {
+        dragDocs.map(dragDoc =>
+            this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.
+                onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }));
     }
 
     @action
@@ -199,7 +200,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             let tab = (e.target as any).parentElement as HTMLElement;
             Server.GetField(docid, action((f: Opt<Field>) => {
                 if (f instanceof Document)
-                    DragManager.StartDocumentDrag(tab, new DragManager.DocumentDragData(f as Document),
+                    DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]),
                         {
                             handlers: {
                                 dragComplete: action(() => { }),
@@ -265,6 +266,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     }
 
     render() {
+        trace();
         return (
             <div className="collectiondockingview-container" id="menuContainer"
                 onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef}
@@ -305,6 +307,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     }
 
     render() {
+        trace();
         if (!this._document)
             return (null);
         var content =
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index a1498e0ae..014aa1d8f 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -113,7 +113,7 @@ export class CollectionView extends React.Component<CollectionViewProps> {
         if (index !== -1) {
             value.splice(index, 1)
 
-            SelectionManager.DeselectAll()
+            //SelectionManager.DeselectAll()
             ContextMenu.Instance.clearItems()
             return true;
         }
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 987f3cb6c..316d20c9d 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -82,9 +82,9 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         if (de.data instanceof DragManager.DocumentDragData) {
             if (de.data.aliasOnDrop) {
                 [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key =>
-                    de.data.draggedDocument.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocument.SetNumber(key, f.Data) : null));
+                    de.data.draggedDocuments.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocument.SetNumber(key, f.Data) : null));
             }
-            let added = this.props.addDocument(de.data.droppedDocument, false);
+            let added = de.data.droppedDocuments.reduce((added, d) => this.props.addDocument(d, false), true);
             if (added && de.data.removeDocument && !de.data.aliasOnDrop) {
                 de.data.removeDocument(this.props.CollectionView);
             }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 60fb95ff5..c5178f69d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -77,13 +77,20 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 let screenX = de.x - (de.data.xOffset as number || 0);
                 let screenY = de.y - (de.data.yOffset as number || 0);
                 const [x, y] = this.getTransform().transformPoint(screenX, screenY);
-                de.data.droppedDocument.SetNumber(KeyStore.X, x);
-                de.data.droppedDocument.SetNumber(KeyStore.Y, y);
-                if (!de.data.droppedDocument.GetNumber(KeyStore.Width, 0)) {
-                    de.data.droppedDocument.SetNumber(KeyStore.Width, 300);
-                    de.data.droppedDocument.SetNumber(KeyStore.Height, 300);
-                }
-                this.bringToFront(de.data.droppedDocument);
+                let dragDoc = de.data.draggedDocuments[0];
+                let dragX = dragDoc.GetNumber(KeyStore.X, 0);
+                let dragY = dragDoc.GetNumber(KeyStore.Y, 0);
+                de.data.draggedDocuments.map(d => {
+                    let docX = d.GetNumber(KeyStore.X, 0);
+                    let docY = d.GetNumber(KeyStore.Y, 0);
+                    d.SetNumber(KeyStore.X, x + (docX - dragX));
+                    d.SetNumber(KeyStore.Y, y + (docY - dragY));
+                    if (!d.GetNumber(KeyStore.Width, 0)) {
+                        d.SetNumber(KeyStore.Width, 300);
+                        d.SetNumber(KeyStore.Height, 300);
+                    }
+                    this.bringToFront(d);
+                })
             }
             return true;
         }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 71613ca4f..1195128dc 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -106,7 +106,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             if (this.props.isTopMost) {
                 this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
             }
-            else CollectionDockingView.Instance.StartOtherDrag(this.props.Document, e);
+            else CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
             e.stopPropagation();
         } else {
             if (this.active && !e.isDefaultPrevented()) {
@@ -125,9 +125,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (this._mainCont.current) {
             this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } });
         }
-        runInAction(() => {
-            DocumentManager.Instance.DocumentViews.push(this);
-        })
+        runInAction(() => DocumentManager.Instance.DocumentViews.push(this))
         this._reactionDisposer = reaction(
             () => this.props.ContainingCollectionView && this.props.ContainingCollectionView.SelectedDocs.slice(),
             () => {
@@ -149,10 +147,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (this.dropDisposer) {
             this.dropDisposer();
         }
-        runInAction(() => {
-            DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1);
-
-        })
+        runInAction(() => DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1))
         if (this._reactionDisposer) {
             this._reactionDisposer();
         }
@@ -161,7 +156,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
         if (this._mainCont.current) {
             const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-            let dragData = new DragManager.DocumentDragData(this.props.Document);
+            let dragData = new DragManager.DocumentDragData([this.props.Document]);
             dragData.aliasOnDrop = dropAliasOfDraggedDoc;
             dragData.xOffset = x - left;
             dragData.yOffset = y - top;
@@ -170,7 +165,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                     this.props.RemoveDocument(this.props.Document);
                 }
             }
-            DragManager.StartDocumentDrag(this._mainCont.current, dragData, {
+            DragManager.StartDocumentDrag([this._mainCont.current], dragData, {
                 handlers: {
                     dragComplete: action(() => { }),
                 },
-- 
cgit v1.2.3-70-g09d2


From 3b456da9c1d90abcfcf33fc6fd762cad1dff7ca7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 3 Apr 2019 12:10:31 -0400
Subject: merged with changes to DocumentDecorations so you can
 minimize/maximize without menu

---
 src/client/views/DocumentDecorations.scss |  6 +++++-
 src/client/views/DocumentDecorations.tsx  | 25 ++++++++++++++++++++++++-
 src/client/views/nodes/DocumentView.tsx   | 14 +++++++-------
 3 files changed, 36 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index c72623546..befe175b5 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -39,12 +39,16 @@
     }
     .title{
         background: lightblue;
-        grid-column-start:1;
+        grid-column-start:2;
         grid-column-end: 4;
         pointer-events: auto;
     }
 }
 
+.documentDecorations-minimizeButton {
+    background: rgb(250, 57, 9);
+    pointer-events: all;
+}
 .documentDecorations-background {
     background: lightblue;
     position: absolute;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 572c265f3..b74737ec9 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -139,11 +139,33 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         e.preventDefault();
     }
 
+    onMinimizeDown = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+            document.removeEventListener("pointermove", this.onMinimizeMove);
+            document.addEventListener("pointermove", this.onMinimizeMove);
+            document.removeEventListener("pointerup", this.onMinimizeUp);
+            document.addEventListener("pointerup", this.onMinimizeUp);
+        }
+    }
+    onMinimizeMove = (e: PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+        }
+    }
+    onMinimizeUp = (e: PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+            SelectionManager.SelectedDocuments().map(dv => dv.minimize());
+            document.removeEventListener("pointermove", this.onMinimizeMove);
+            document.removeEventListener("pointerup", this.onMinimizeUp);
+        }
+    }
+
     onPointerDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
         if (e.button === 0) {
             this._isPointerDown = true;
-            console.log("Pointer down");
             this._resizer = e.currentTarget.id;
             document.removeEventListener("pointermove", this.onPointerMove);
             document.addEventListener("pointermove", this.onPointerMove);
@@ -339,6 +361,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
                 opacity: this._opacity
             }}>
+                <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>v</div>
                 <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2b9372e15..bc627015c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -70,18 +70,18 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
   let Keys: { [name: string]: any } = {};
   let Fields: { [name: string]: any } = {};
   for (const key of keys) {
-    let fn = () => {};
+    let fn = () => { };
     Object.defineProperty(fn, "name", { value: key + "Key" });
     Keys[key] = fn;
   }
   for (const field of fields) {
-    let fn = () => {};
+    let fn = () => { };
     Object.defineProperty(fn, "name", { value: field });
     Fields[field] = fn;
   }
   let args: JsxArgs = {
-    Document: function Document() {},
-    DocumentView: function DocumentView() {},
+    Document: function Document() { },
+    DocumentView: function DocumentView() { },
     Keys,
     Fields
   } as any;
@@ -115,7 +115,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     return (
       !this.props.ContainingCollectionView ||
       this.props.ContainingCollectionView.collectionViewType ==
-        CollectionViewType.Docking
+      CollectionViewType.Docking
     );
   }
   @computed get layout(): string {
@@ -233,7 +233,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
       };
       DragManager.StartDocumentDrag([this._mainCont.current], dragData, {
         handlers: {
-          dragComplete: action(() => {})
+          dragComplete: action(() => { })
         },
         hideSource: !dropAliasOfDraggedDoc
       });
@@ -307,7 +307,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
   };
 
   @action
-  minimize = (e: React.MouseEvent): void => {
+  public minimize = (): void => {
     this.props.Document.SetData(
       KeyStore.Minimized,
       true as boolean,
-- 
cgit v1.2.3-70-g09d2


From dc2a998acdae1545c8e7bf9ee9f4ca98bba82ac9 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Thu, 4 Apr 2019 01:30:01 -0400
Subject: Started adding linting

---
 package.json                                       |  2 +
 src/Utils.ts                                       |  2 +-
 src/client/Server.ts                               | 52 +++++++-------
 src/client/SocketStub.ts                           |  2 +-
 src/client/northstar/manager/Gateway.ts            | 24 +++----
 src/client/util/DocumentManager.ts                 | 10 +--
 src/client/util/DragManager.ts                     | 23 +++---
 src/client/util/Scripting.ts                       | 14 ++--
 src/client/util/SelectionManager.ts                |  5 +-
 src/client/util/Transform.ts                       | 50 ++++++-------
 src/client/util/TypedEvent.ts                      |  5 +-
 src/client/util/UndoManager.ts                     |  4 +-
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/EditableView.tsx                  |  4 +-
 src/client/views/InkingCanvas.tsx                  | 14 ++--
 src/client/views/InkingControl.tsx                 |  4 +-
 src/client/views/InkingStroke.tsx                  |  7 +-
 src/client/views/Main.tsx                          | 13 ++--
 .../views/collections/CollectionBaseView.tsx       |  4 +-
 .../views/collections/CollectionSchemaView.tsx     | 17 ++---
 .../views/collections/CollectionVideoView.tsx      |  2 +-
 .../views/collections/CollectionViewBase.tsx       |  5 +-
 .../CollectionFreeFormLinksView.tsx                | 18 ++---
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 12 ++--
 src/client/views/nodes/DocumentView.tsx            |  5 +-
 src/client/views/nodes/FieldView.tsx               |  5 +-
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 src/client/views/nodes/KeyValueBox.tsx             |  5 +-
 src/client/views/nodes/PDFBox.tsx                  | 36 +++++-----
 src/client/views/nodes/VideoBox.tsx                |  4 +-
 src/debug/Viewer.tsx                               |  7 +-
 src/fields/Document.ts                             | 14 ++--
 src/fields/WebField.ts                             |  2 +-
 src/mobile/ImageUpload.tsx                         |  5 +-
 .../authentication/controllers/WorkspacesMenu.tsx  |  2 +-
 .../authentication/controllers/user_controller.ts  | 12 ++--
 src/server/database.ts                             |  2 +-
 src/server/index.ts                                |  8 +--
 test/test.ts                                       |  2 +-
 tslint.json                                        | 56 +++++++++++++++
 webpack.config.js                                  | 83 ++++++++++++----------
 43 files changed, 292 insertions(+), 259 deletions(-)
 create mode 100644 tslint.json

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

diff --git a/package.json b/package.json
index 27b3eead1..4fc253834 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,8 @@
     "scss-loader": "0.0.1",
     "style-loader": "^0.23.1",
     "ts-node": "^7.0.1",
+    "tslint": "^5.15.0",
+    "tslint-loader": "^3.5.4",
     "typescript": "^3.3.3333",
     "webpack": "^4.29.6",
     "webpack-cli": "^3.2.3",
diff --git a/src/Utils.ts b/src/Utils.ts
index 3eb192eb8..8bd7f2f5c 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -18,7 +18,7 @@ export class Utils {
             return { scale: 1, translateX: 1, translateY: 1 }
         }
         const rect = ele.getBoundingClientRect();
-        const scale = ele.offsetWidth == 0 && rect.width == 0 ? 1 : rect.width / ele.offsetWidth;
+        const scale = ele.offsetWidth === 0 && rect.width === 0 ? 1 : rect.width / ele.offsetWidth;
         const translateX = rect.left;
         const translateY = rect.top;
 
diff --git a/src/client/Server.ts b/src/client/Server.ts
index c301b04d3..e3f4448cb 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -21,11 +21,11 @@ export class Server {
         let fn = (cb: (field: Opt<Field>) => void) => {
 
             let cached = this.ClientFieldsCached.get(fieldid);
-            if (!cached) {
+            if (cached === undefined) {
                 this.ClientFieldsCached.set(fieldid, FieldWaiting);
                 SocketStub.SEND_FIELD_REQUEST(fieldid, action((field: Field | undefined) => {
                     let cached = this.ClientFieldsCached.get(fieldid);
-                    if (cached != FieldWaiting)
+                    if (cached !== FieldWaiting)
                         cb(cached);
                     else {
                         if (field) {
@@ -36,23 +36,22 @@ export class Server {
                         cb(field)
                     }
                 }));
-            } else if (cached != FieldWaiting) {
+            } else if (cached !== FieldWaiting) {
                 setTimeout(() => cb(cached as Field), 0);
             } else {
-                reaction(() => {
-                    return this.ClientFieldsCached.get(fieldid);
-                }, (field, reaction) => {
-                    if (field !== FieldWaiting) {
-                        reaction.dispose()
-                        cb(field)
-                    }
-                })
+                reaction(() =>
+                    this.ClientFieldsCached.get(fieldid), (field, reaction) => {
+                        if (field !== FieldWaiting) {
+                            reaction.dispose()
+                            cb(field)
+                        }
+                    })
             }
         }
         if (callback) {
             fn(callback);
         } else {
-            return new Promise(res => fn(res));
+            return new Promise(fn);
         }
     }
 
@@ -92,24 +91,23 @@ export class Server {
                         }
                     }
                 }
-                reaction(() => {
-                    return waitingFieldIds.map(id => this.ClientFieldsCached.get(id));
-                }, (cachedFields, reaction) => {
-                    if (!cachedFields.some(field => !field || field === FieldWaiting)) {
-                        reaction.dispose();
-                        for (let field of cachedFields) {
-                            let realField = field as Field;
-                            existingFields[realField.Id] = realField;
+                reaction(() =>
+                    waitingFieldIds.map(id => this.ClientFieldsCached.get(id)), (cachedFields, reaction) => {
+                        if (!cachedFields.some(field => !field)) {
+                            reaction.dispose();
+                            for (let field of cachedFields) {
+                                let realField = field as Field;
+                                existingFields[realField.Id] = realField;
+                            }
+                            cb({ ...fields, ...existingFields })
                         }
-                        cb({ ...fields, ...existingFields })
-                    }
-                }, { fireImmediately: true })
+                    }, { fireImmediately: true })
             }));
         };
         if (callback) {
             fn(callback);
         } else {
-            return new Promise(res => fn(res));
+            return new Promise(fn);
         }
     }
 
@@ -153,19 +151,19 @@ export class Server {
     @action
     private static cacheField(clientField: Field) {
         var cached = this.ClientFieldsCached.get(clientField.Id);
-        if (!cached || cached == FieldWaiting) {
+        if (!cached || cached === FieldWaiting) {
             this.ClientFieldsCached.set(clientField.Id, clientField);
         } else {
             // probably should overwrite the values within any field that was already here...
         }
-        return this.ClientFieldsCached.get(clientField.Id) as Field;
+        return this.ClientFieldsCached.get(clientField.Id);
     }
 
     @action
     static updateField(field: { _id: string, data: any, type: Types }) {
         if (Server.ClientFieldsCached.has(field._id)) {
             var f = Server.ClientFieldsCached.get(field._id);
-            if (f && f != FieldWaiting) {
+            if (f && f !== FieldWaiting) {
                 // console.log("Applying        : " + field._id);
                 f.UpdateFromServer(field.data);
                 f.init(() => { });
diff --git a/src/client/SocketStub.ts b/src/client/SocketStub.ts
index 5045037c5..c3cd8bee6 100644
--- a/src/client/SocketStub.ts
+++ b/src/client/SocketStub.ts
@@ -55,7 +55,7 @@ export class SocketStub {
         if (callback) {
             fn(callback);
         } else {
-            return new Promise(res => fn(res))
+            return new Promise(fn)
         }
     }
 
diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts
index 5ae5e4f47..3e72a50ae 100644
--- a/src/client/northstar/manager/Gateway.ts
+++ b/src/client/northstar/manager/Gateway.ts
@@ -246,18 +246,18 @@ export class Settings {
         else {
             this.ServerUrl = environment["SERVER_URL"] ? environment["SERVER_URL"] : document.URL;
         }*/
-        this.ServerUrl = environment["SERVER_URL"] ? environment["SERVER_URL"] : document.URL;
-        this.ServerApiPath = environment["SERVER_API_PATH"];
-        this.SampleSize = environment["SAMPLE_SIZE"];
-        this.XBins = environment["X_BINS"];
-        this.YBins = environment["Y_BINS"];
-        this.SplashTimeInMS = environment["SPLASH_TIME_IN_MS"];
-        this.ShowFpsCounter = environment["SHOW_FPS_COUNTER"];
-        this.ShowShutdownButton = environment["SHOW_SHUTDOWN_BUTTON"];
-        this.IsMenuFixed = environment["IS_MENU_FIXED"];
-        this.IsDarpa = environment["IS_DARPA"];
-        this.IsIGT = environment["IS_IGT"];
-        this.DegreeOfParallelism = environment["DEGREE_OF_PARALLISM"];
+        this.ServerUrl = environment.SERVER_URL ? environment.SERVER_URL : document.URL;
+        this.ServerApiPath = environment.SERVER_API_PATH;
+        this.SampleSize = environment.SAMPLE_SIZE;
+        this.XBins = environment.X_BINS;
+        this.YBins = environment.Y_BINS;
+        this.SplashTimeInMS = environment.SPLASH_TIME_IN_MS;
+        this.ShowFpsCounter = environment.SHOW_FPS_COUNTER;
+        this.ShowShutdownButton = environment.SHOW_SHUTDOWN_BUTTON;
+        this.IsMenuFixed = environment.IS_MENU_FIXED;
+        this.IsDarpa = environment.IS_DARPA;
+        this.IsIGT = environment.IS_IGT;
+        this.DegreeOfParallelism = environment.DEGREE_OF_PARALLISM;
     }
 
     public static get Instance(): Settings {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index bf59fbb43..7cb368f47 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -29,7 +29,7 @@ export class DocumentManager {
 
     public getAllDocumentViews(collection: Document) {
         return this.DocumentViews.filter(dv =>
-            dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document == collection);
+            dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document === collection);
     }
 
     public getDocumentView(toFind: Document): DocumentView | null {
@@ -47,7 +47,7 @@ export class DocumentManager {
                 return;
             }
             let docSrc = doc.GetT(KeyStore.Prototype, Document);
-            if (docSrc && docSrc != FieldWaiting && Object.is(docSrc, toFind)) {
+            if (docSrc && docSrc !== FieldWaiting && Object.is(docSrc, toFind)) {
                 toReturn = view;
             }
         })
@@ -67,7 +67,7 @@ export class DocumentManager {
                 toReturn.push(view);
             } else {
                 let docSrc = doc.GetT(KeyStore.Prototype, Document);
-                if (docSrc && docSrc != FieldWaiting && Object.is(docSrc, toFind)) {
+                if (docSrc && docSrc !== FieldWaiting && Object.is(docSrc, toFind)) {
                     toReturn.push(view);
                 }
             }
@@ -80,11 +80,11 @@ export class DocumentManager {
     public get LinkedDocumentViews() {
         return DocumentManager.Instance.DocumentViews.reduce((pairs, dv) => {
             let linksList = dv.props.Document.GetT(KeyStore.LinkedToDocs, ListField);
-            if (linksList && linksList != FieldWaiting && linksList.Data.length) {
+            if (linksList && linksList !== FieldWaiting && linksList.Data.length) {
                 pairs.push(...linksList.Data.reduce((pairs, link) => {
                     if (link instanceof Document) {
                         let linkToDoc = link.GetT(KeyStore.LinkedToDocs, Document);
-                        if (linkToDoc && linkToDoc != FieldWaiting) {
+                        if (linkToDoc && linkToDoc !== FieldWaiting) {
                             DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => {
                                 pairs.push({ a: dv, b: docView1, l: link })
                             })
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 96c965c23..ff778302b 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -6,6 +6,7 @@ import { ImageField } from "../../fields/ImageField";
 import { KeyStore } from "../../fields/KeyStore";
 import { CollectionView } from "../views/collections/CollectionView";
 import { DocumentView } from "../views/nodes/DocumentView";
+import { emptyFunction } from "../../Utils";
 
 export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, removeFunc: (containingCollection: CollectionView) => void = () => { }) {
     let onRowMove = action((e: PointerEvent): void => {
@@ -24,7 +25,7 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
     });
     let onItemDown = (e: React.PointerEvent) => {
         // if (this.props.isSelected() || this.props.isTopMost) {
-        if (e.button == 0) {
+        if (e.button === 0) {
             e.stopPropagation();
             if (e.shiftKey) {
                 CollectionDockingView.Instance.StartOtherDrag([docFunc()], e);
@@ -88,7 +89,7 @@ export namespace DragManager {
         if ("canDrop" in element.dataset) {
             throw new Error("Element is already droppable, can't make it droppable again");
         }
-        element.dataset["canDrop"] = "true";
+        element.dataset.canDrop = "true";
         const handler = (e: Event) => {
             const ce = e as CustomEvent<DropEvent>;
             options.handlers.drop(e, ce.detail);
@@ -96,7 +97,7 @@ export namespace DragManager {
         element.addEventListener("dashOnDrop", handler);
         return () => {
             element.removeEventListener("dashOnDrop", handler);
-            delete element.dataset["canDrop"]
+            delete element.dataset.canDrop
         };
     }
 
@@ -167,11 +168,11 @@ export namespace DragManager {
                 let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
                 if (pdfBox && pdfBox.childElementCount && thumbnail) {
                     let img = new Image();
-                    img!.src = thumbnail.toString();
-                    img!.style.position = "absolute";
-                    img!.style.width = `${rect.width / scaleX}px`;
-                    img!.style.height = `${rect.height / scaleY}px`;
-                    pdfBox.replaceChild(img!, pdfBox.children[0])
+                    img.src = thumbnail.toString();
+                    img.style.position = "absolute";
+                    img.style.width = `${rect.width / scaleX}px`;
+                    img.style.height = `${rect.height / scaleY}px`;
+                    pdfBox.replaceChild(img, pdfBox.children[0])
                 }
             }
 
@@ -224,9 +225,9 @@ export namespace DragManager {
         });
         const target = document.elementFromPoint(e.x, e.y);
         removed.map(r => {
-            let dragEle: HTMLElement = r[0]!;
-            let parent: HTMLElement | null = r[1];
-            if (parent)
+            let dragEle = r[0];
+            let parent = r[1];
+            if (parent && dragEle)
                 parent.appendChild(dragEle);
         });
         if (target) {
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 4e97b9401..8aef44a3a 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -26,7 +26,7 @@ export interface ExecutableScript {
 }
 
 function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [name: string]: any }): ExecutableScript {
-    const compiled = !(diagnostics && diagnostics.some(diag => diag.category == ts.DiagnosticCategory.Error));
+    const compiled = !(diagnostics && diagnostics.some(diag => diag.category === ts.DiagnosticCategory.Error));
 
     let func: () => Opt<Field>;
     if (compiled && script) {
@@ -40,7 +40,7 @@ function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [
             paramNames.push(prop);
             params.push(scope[prop]);
         }
-        let thisParam = scope["this"];
+        let thisParam = scope.this;
         let compiledFunction = new Function(...paramNames, script);
         func = function (): Opt<Field> {
             return compiledFunction.apply(thisParam, params)
@@ -49,10 +49,8 @@ function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [
         func = () => undefined;
     }
 
-    return Object.assign(func,
-        {
-            compiled
-        });
+    Object.assign(func, { compiled });
+    return func as ExecutableScript;
 }
 
 interface File {
@@ -125,9 +123,9 @@ export function CompileScript(script: string, scope?: { [name: string]: any }, a
 }
 
 export function ToField(data: any): Opt<Field> {
-    if (typeof data == "string") {
+    if (typeof data === "string") {
         return new TextField(data);
-    } else if (typeof data == "number") {
+    } else if (typeof data === "number") {
         return new NumberField(data);
     }
     return undefined;
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 05810b61c..494420f0b 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -40,9 +40,8 @@ export namespace SelectionManager {
     export function DeselectAll(except?: Document): void {
         let found: DocumentView | undefined = undefined;
         if (except) {
-            for (let i = 0; i < manager.SelectedDocuments.length; i++) {
-                let view = manager.SelectedDocuments[i];
-                if (view.props.Document == except)
+            for (const view of manager.SelectedDocuments) {
+                if (view.props.Document === except)
                     found = view;
             }
         }
diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts
index 889134e3e..8608264a1 100644
--- a/src/client/util/Transform.ts
+++ b/src/client/util/Transform.ts
@@ -62,33 +62,26 @@ export class Transform {
         return this;
     }
 
-    translated = (x: number, y: number): Transform => {
-        return this.copy().translate(x, y);
-    }
+    translated = (x: number, y: number): Transform =>
+        this.copy().translate(x, y)
 
-    preTranslated = (x: number, y: number): Transform => {
-        return this.copy().preTranslate(x, y);
-    }
+    preTranslated = (x: number, y: number): Transform =>
+        this.copy().preTranslate(x, y)
 
-    scaled = (scale: number): Transform => {
-        return this.copy().scale(scale);
-    }
+    scaled = (scale: number): Transform =>
+        this.copy().scale(scale)
 
-    scaledAbout = (scale: number, x: number, y: number): Transform => {
-        return this.copy().scaleAbout(scale, x, y);
-    }
+    scaledAbout = (scale: number, x: number, y: number): Transform =>
+        this.copy().scaleAbout(scale, x, y)
 
-    preScaled = (scale: number): Transform => {
-        return this.copy().preScale(scale);
-    }
+    preScaled = (scale: number): Transform =>
+        this.copy().preScale(scale)
 
-    transformed = (transform: Transform): Transform => {
-        return this.copy().transform(transform);
-    }
+    transformed = (transform: Transform): Transform =>
+        this.copy().transform(transform)
 
-    preTransformed = (transform: Transform): Transform => {
-        return this.copy().preTransform(transform);
-    }
+    preTransformed = (transform: Transform): Transform =>
+        this.copy().preTransform(transform)
 
     transformPoint = (x: number, y: number): [number, number] => {
         x *= this._scale;
@@ -98,9 +91,8 @@ export class Transform {
         return [x, y];
     }
 
-    transformDirection = (x: number, y: number): [number, number] => {
-        return [x * this._scale, y * this._scale];
-    }
+    transformDirection = (x: number, y: number): [number, number] =>
+        [x * this._scale, y * this._scale]
 
     transformBounds(x: number, y: number, width: number, height: number): { x: number, y: number, width: number, height: number } {
         [x, y] = this.transformPoint(x, y);
@@ -108,12 +100,10 @@ export class Transform {
         return { x, y, width, height };
     }
 
-    inverse = () => {
-        return new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
-    }
+    inverse = () =>
+        new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
 
-    copy = () => {
-        return new Transform(this._translateX, this._translateY, this._scale);
-    }
+    copy = () =>
+        new Transform(this._translateX, this._translateY, this._scale)
 
 }
\ No newline at end of file
diff --git a/src/client/util/TypedEvent.ts b/src/client/util/TypedEvent.ts
index 0714a7f5c..c590d3734 100644
--- a/src/client/util/TypedEvent.ts
+++ b/src/client/util/TypedEvent.ts
@@ -36,7 +36,6 @@ export class TypedEvent<T> {
     this.listenersOncer = [];
   }
 
-  pipe = (te: TypedEvent<T>): Disposable => {
-    return this.on((e) => te.emit(e));
-  }
+  pipe = (te: TypedEvent<T>): Disposable =>
+    this.on((e) => te.emit(e))
 }
\ No newline at end of file
diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index 6d1b2f1b8..1e5028375 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -159,8 +159,8 @@ export namespace UndoManager {
         }
 
         undoing = true;
-        for (let i = 0; i < commands.length; i++) {
-            commands[i].redo();
+        for (const command of commands) {
+            command.redo();
         }
         undoing = false;
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index d0699e1ab..b0aa190e5 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -75,7 +75,7 @@ export class DocumentDecorations extends React.Component {
         this._dragging = true;
         document.removeEventListener("pointermove", this.onBackgroundMove);
         document.removeEventListener("pointerup", this.onBackgroundUp);
-        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData, {
+        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont.current), dragData, {
             handlers: {
                 dragComplete: action(() => this._dragging = false),
             },
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 29bf6add7..982aacdea 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -38,7 +38,7 @@ export class EditableView extends React.Component<EditableProps> {
 
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
-        if (e.key == "Enter") {
+        if (e.key === "Enter") {
             if (!e.ctrlKey) {
                 if (this.props.SetValue(e.currentTarget.value)) {
                     this.editing = false;
@@ -47,7 +47,7 @@ export class EditableView extends React.Component<EditableProps> {
                 this.props.OnFillDown(e.currentTarget.value);
                 this.editing = false;
             }
-        } else if (e.key == "Escape") {
+        } else if (e.key === "Escape") {
             this.editing = false;
         }
     }
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index cad4b74b1..a2956f1b6 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -56,7 +56,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
 
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.button != 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) {
+        if (e.button !== 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) {
             return;
         }
         document.addEventListener("pointermove", this.onPointerMove, true);
@@ -64,7 +64,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
         e.stopPropagation();
         e.preventDefault();
 
-        if (InkingControl.Instance.selectedTool != InkTool.Eraser) {
+        if (InkingControl.Instance.selectedTool !== InkTool.Eraser) {
             // start the new line, saves a uuid to represent the field of the stroke
             this._currentStrokeId = Utils.GenerateGuid();
             this.inkData.set(this._currentStrokeId, {
@@ -94,7 +94,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
     onPointerMove = (e: PointerEvent): void => {
         e.stopPropagation()
         e.preventDefault();
-        if (InkingControl.Instance.selectedTool != InkTool.Eraser) {
+        if (InkingControl.Instance.selectedTool !== InkTool.Eraser) {
             let data = this.inkData;  // add points to new line as it is being drawn
             let strokeData = data.get(this._currentStrokeId);
             if (strokeData) {
@@ -121,7 +121,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
     get drawnPaths() {
         let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1)
         let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => {
-            if (strokeData.page == -1 || strokeData.page == curPage)
+            if (strokeData.page === -1 || strokeData.page === curPage)
                 paths.push(<InkingStroke key={id} id={id} line={strokeData.pathData}
                     offsetX={this.maxCanvasDim - this.inkMidX}
                     offsetY={this.maxCanvasDim - this.inkMidY}
@@ -131,16 +131,16 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
         }, [] as JSX.Element[]);
         return [<svg className={`inkingCanvas-paths-markers`} key="Markers"
             style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }} >
-            {paths.filter(path => path.props.tool == InkTool.Highlighter)}
+            {paths.filter(path => path.props.tool === InkTool.Highlighter)}
         </svg>,
         <svg className={`inkingCanvas-paths-ink`} key="Pens"
             style={{ left: `-${this.inkMidX - this.maxCanvasDim}px`, top: `-${this.inkMidY - this.maxCanvasDim}px` }}>
-            {paths.filter(path => path.props.tool != InkTool.Highlighter)}
+            {paths.filter(path => path.props.tool !== InkTool.Highlighter)}
         </svg>];
     }
 
     render() {
-        let svgCanvasStyle = InkingControl.Instance.selectedTool != InkTool.None ? "canSelect" : "noSelect";
+        let svgCanvasStyle = InkingControl.Instance.selectedTool !== InkTool.None ? "canSelect" : "noSelect";
         return (
             <div className="inkingCanvas" >
                 <div className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} />
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index c1519dff8..13f0a0acc 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -36,9 +36,9 @@ export class InkingControl extends React.Component {
     @action
     switchColor = (color: ColorResult): void => {
         this._selectedColor = color.hex;
-        if (SelectionManager.SelectedDocuments().length == 1) {
+        if (SelectionManager.SelectedDocuments().length === 1) {
             var sdoc = SelectionManager.SelectedDocuments()[0];
-            if (sdoc.props.ContainingCollectionView && sdoc.props.ContainingCollectionView) {
+            if (sdoc.props.ContainingCollectionView) {
                 sdoc.props.Document.SetDataOnPrototype(KeyStore.BackgroundColor, color.hex, TextField);
             }
         }
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 615f8af7e..dbb79c0c6 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -29,9 +29,8 @@ export class InkingStroke extends React.Component<StrokeProps> {
         }
     }
 
-    parseData = (line: Array<{ x: number, y: number }>): string => {
-        return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ");
-    }
+    parseData = (line: Array<{ x: number, y: number }>): string =>
+        !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ")
 
     createStyle() {
         switch (this._strokeTool) {
@@ -49,7 +48,7 @@ export class InkingStroke extends React.Component<StrokeProps> {
         let pathStyle = this.createStyle();
         let pathData = this.parseData(this.props.line);
 
-        let pointerEvents: any = InkingControl.Instance.selectedTool == InkTool.Eraser ? "all" : "none";
+        let pointerEvents: any = InkingControl.Instance.selectedTool === InkTool.Eraser ? "all" : "none";
         return (
             <path d={pathData} style={{ ...pathStyle, pointerEvents: pointerEvents }} strokeLinejoin="round" strokeLinecap="round"
                 onPointerOver={this.deleteStroke} onPointerDown={this.deleteStroke} />
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 8f67c006d..446c3d55f 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -204,9 +204,7 @@ export class Main extends React.Component {
     @observable
     workspacesShown: boolean = false;
 
-    areWorkspacesShown = () => {
-        return this.workspacesShown;
-    }
+    areWorkspacesShown = () => this.workspacesShown
     @action
     toggleWorkspaces = () => {
         this.workspacesShown = !this.workspacesShown;
@@ -373,8 +371,7 @@ export class Main extends React.Component {
     }
 }
 
-Documents.initProtos().then(() => {
-    return CurrentUserUtils.loadCurrentUser()
-}).then(() => {
-    ReactDOM.render(<Main />, document.getElementById('root'));
-});
+Documents.initProtos().then(() =>
+    CurrentUserUtils.loadCurrentUser()).then(() => {
+        ReactDOM.render(<Main />, document.getElementById('root'));
+    });
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 301467d99..9b68ee06c 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
 import { FieldViewProps } from '../nodes/FieldView';
 import { KeyStore } from '../../../fields/KeyStore';
 import { NumberField } from '../../../fields/NumberField';
-import { FieldWaiting, Field } from '../../../fields/Field';
+import { FieldWaiting, Field, FieldValue } from '../../../fields/Field';
 import { ContextMenu } from '../ContextMenu';
 import { SelectionManager } from '../../util/SelectionManager';
 import { Document } from '../../../fields/Document';
@@ -72,7 +72,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             if (this.createsCycle(annots[i], containerDocument))
                 return true;
         }
-        for (let containerProto: any = containerDocument; containerProto && containerProto != FieldWaiting; containerProto = containerProto.GetPrototype()) {
+        for (let containerProto: FieldValue<Document> = containerDocument; containerProto && containerProto != FieldWaiting; containerProto = containerProto.GetPrototype()) {
             if (containerProto.Id == documentToAdd.Id)
                 return true;
         }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 78a813a99..ced46cc25 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -122,9 +122,7 @@ export class CollectionSchemaView extends CollectionViewBase {
                         }
                         return field || "";
                     }}
-                    SetValue={(value: string) => {
-                        return applyToDoc(props.Document, value);
-                    }}
+                    SetValue={(value: string) => applyToDoc(props.Document, value)}
                     OnFillDown={(value: string) => {
                         this.props.Document.GetTAsync<ListField<Document>>(this.props.fieldKey, ListField).then((val) => {
                             if (val) {
@@ -240,12 +238,8 @@ export class CollectionSchemaView extends CollectionViewBase {
     getContentScaling = (): number => this._contentScaling;
     getPanelWidth = (): number => this._panelWidth;
     getPanelHeight = (): number => this._panelHeight;
-    getTransform = (): Transform => {
-        return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
-    }
-    getPreviewTransform = (): Transform => {
-        return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
-    }
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling)
+    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling)
 
     focusDocument = (doc: Document) => { }
 
@@ -332,9 +326,8 @@ export class CollectionSchemaView extends CollectionViewBase {
                     <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.splitPercentage != 0} onChange={this.toggleExpander} />  Show Preview </div>
                     <h6 className="schema-options-subHeader" >Displayed Columns</h6>
                     <ul id="schema-col-checklist" >
-                        {Array.from(Object.keys(allKeys)).map(item => {
-                            return (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />)
-                        })}
+                        {Array.from(Object.keys(allKeys)).map(item =>
+                            (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />))}
                     </ul>
                     <input value={this.newKeyName} onChange={this.newKeyChange} />
                     <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 7cb461b4d..3ab6db5ef 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -43,7 +43,7 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
     @action
     mainCont = (ele: HTMLDivElement | null) => {
         if (ele) {
-            this._player = ele!.getElementsByTagName("video")[0];
+            this._player = ele.getElementsByTagName("video")[0];
             if (this.props.Document.GetNumber(KeyStore.CurPage, -1) >= 0) {
                 this._currentTimecode = this.props.Document.GetNumber(KeyStore.CurPage, -1);
             }
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 71a639137..51280275c 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -171,9 +171,8 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
                 fetch(upload, {
                     method: 'POST',
                     body: formData
-                }).then((res: Response) => {
-                    return res.json()
-                }).then(json => {
+                }).then((res: Response) =>
+                    res.json()).then(json => {
                     json.map((file: any) => {
                         let path = window.location.origin + file
                         runInAction(() => {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index eb20b3100..b682ab303 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -37,11 +37,11 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                             let srcTarg = (protoSrc ? protoSrc : srcDoc);
                             let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => {
                                 let bdocs = brush.GetList(KeyStore.BrushingDocs, [] as Document[]);
-                                return (bdocs.length == 0 || (bdocs[0] == dstTarg && bdocs[1] == srcTarg) || (bdocs[0] == srcTarg && bdocs[1] == dstTarg))
+                                return (bdocs.length === 0 || (bdocs[0] === dstTarg && bdocs[1] === srcTarg) || (bdocs[0] === srcTarg && bdocs[1] === dstTarg))
                             });
                             let brushAction = (field: ListField<Document>) => {
                                 let found = findBrush(field);
-                                if (found != -1)
+                                if (found !== -1)
                                     field.Data.splice(found, 1);
                             };
                             if (Math.abs(x1 + x1w - x2) < 20 || Math.abs(x2 + x2w - x1) < 20) {
@@ -50,7 +50,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                                 linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
                                 linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
 
-                                brushAction = brushAction = (field: ListField<Document>) => (findBrush(field) == -1) && field.Data.push(linkDoc);
+                                brushAction = brushAction = (field: ListField<Document>) => (findBrush(field) === -1) && field.Data.push(linkDoc);
                             }
                             dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
                             srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
@@ -63,10 +63,10 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
     documentAnchors(view: DocumentView) {
         let equalViews = [view];
         let containerDoc = view.props.Document.GetT(KeyStore.AnnotationOn, Document);
-        if (containerDoc && containerDoc != FieldWaiting && containerDoc instanceof Document) {
-            equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.GetPrototype() as Document)
+        if (containerDoc && containerDoc instanceof Document) {
+            equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.GetPrototype()!)
         }
-        return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document == this.props.Document);
+        return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document);
     }
 
     @computed
@@ -78,14 +78,14 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
             srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document })));
             possiblePairs.map(possiblePair => {
                 if (!drawnPairs.reduce((found, drawnPair) => {
-                    let match = (possiblePair.a == drawnPair.a && possiblePair.b == drawnPair.b);
+                    let match = (possiblePair.a === drawnPair.a && possiblePair.b === drawnPair.b);
                     if (match) {
-                        if (!drawnPair.l.reduce((found, link) => found || link.Id == connection.l.Id, false))
+                        if (!drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false))
                             drawnPair.l.push(connection.l);
                     }
                     return match || found;
                 }, false)) {
-                    drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] as Document[] });
+                    drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] });
                 }
             })
             return drawnPairs
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b04438ede..8c5d3f536 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -83,8 +83,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (super.drop(e, de)) {
             if (de.data instanceof DragManager.DocumentDragData) {
-                let screenX = de.x - (de.data.xOffset as number || 0);
-                let screenY = de.y - (de.data.yOffset as number || 0);
+                let screenX = de.x - (de.data.xOffset || 0);
+                let screenY = de.y - (de.data.yOffset || 0);
                 const [x, y] = this.getTransform().transformPoint(screenX, screenY);
                 let dragDoc = de.data.draggedDocuments[0];
                 let dragX = dragDoc.GetNumber(KeyStore.X, 0);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index e2239c8be..b068d49d0 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -146,7 +146,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             if (InkingCanvas.IntersectStrokeRect(value, this.Bounds)) {
                 idata.set(key,
                     {
-                        pathData: value.pathData.map(val => { return { x: val.x + centerShiftX, y: val.y + centerShiftY } }),
+                        pathData: value.pathData.map(val => ({ x: val.x + centerShiftX, y: val.y + centerShiftY })),
                         color: value.color,
                         width: value.width,
                         tool: value.tool,
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index d52b662bd..e6475ee2a 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -52,14 +52,12 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
         this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
     }
 
-    contentScaling = () => {
-        return this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
-    }
+    contentScaling = () =>
+        this.nativeWidth > 0 ? this.width / this.nativeWidth : 1
 
-    getTransform = (): Transform => {
-        return this.props.ScreenToLocalTransform().
-            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.contentScaling());
-    }
+    getTransform = (): Transform =>
+        this.props.ScreenToLocalTransform().
+            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.contentScaling())
 
     @computed
     get docView() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6c05f6924..34eb8919f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -287,9 +287,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
 
 
-    isSelected = () => {
-        return SelectionManager.IsSelected(this);
-    }
+    isSelected = () =>
+        SelectionManager.IsSelected(this)
 
     select = (ctrlPressed: boolean) => {
         SelectionManager.SelectDoc(this, ctrlPressed)
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 4c6062a2f..d6035a076 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -96,9 +96,8 @@ export class FieldView extends React.Component<FieldViewProps> {
         }
         else if (field instanceof ListField) {
             return (<div>
-                {(field as ListField<Field>).Data.map(f => {
-                    return f instanceof Document ? f.Title : f.GetValue().toString();
-                }).join(", ")}
+                {(field as ListField<Field>).Data.map(f =>
+                    f instanceof Document ? f.Title : f.GetValue().toString()).join(", ")}
             </div>)
         }
         // bcz: this belongs here, but it doesn't render well so taking it out for now
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 9b9dfe645..c5f29f7b0 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -104,7 +104,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
 
     render() {
         let field = this.props.Document.Get(this.props.fieldKey);
-        let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
+        let path = field === FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
             field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif";
         let nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 1);
         return (
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index a3478143d..9b067aeeb 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -103,14 +103,13 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         this._valueInput = e.currentTarget.value;
     }
 
-    newKeyValue = () => {
-        return (
+    newKeyValue = () =>
+        (
             <tr>
                 <td><input type="text" value={this._keyInput} placeholder="Key" onChange={this.keyChanged} /></td>
                 <td><input type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyPress={this.onEnterKey} /></td>
             </tr>
         )
-    }
 
     render() {
         return (<div className="keyValueBox-cont" onWheel={this.onPointerWheel}>
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3b5e3a570..66c9f477e 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -94,7 +94,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
         this._reactionDisposer = reaction(
             () => [this.curPage, this.thumbnailPage],
             () => {
-                if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage != this.thumbnailPage) {
+                if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage !== this.thumbnailPage) {
                     this.saveThumbnail();
                     this._interactive = true;
                 }
@@ -165,16 +165,16 @@ export class PDFBox extends React.Component<FieldViewProps> {
 
             let obj: Object = { parentDivs: [], spans: [] };
             //@ts-ignore
-            if (range.commonAncestorContainer.className == 'react-pdf__Page__textContent') { //multiline highlighting case
+            if (range.commonAncestorContainer.className === 'react-pdf__Page__textContent') { //multiline highlighting case
                 obj = this.highlightNodes(range.commonAncestorContainer.childNodes)
             } else { //single line highlighting case
                 let parentDiv = range.commonAncestorContainer.parentElement
                 if (parentDiv) {
-                    if (parentDiv.className == 'react-pdf__Page__textContent') { //when highlight is overwritten
+                    if (parentDiv.className === 'react-pdf__Page__textContent') { //when highlight is overwritten
                         obj = this.highlightNodes(parentDiv.childNodes)
                     } else {
                         parentDiv.childNodes.forEach((child) => {
-                            if (child.nodeName == 'SPAN') {
+                            if (child.nodeName === 'SPAN') {
                                 //@ts-ignore
                                 obj.parentDivs.push(parentDiv)
                                 //@ts-ignore
@@ -197,7 +197,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
         let temp = { parentDivs: [], spans: [] }
         nodes.forEach((div) => {
             div.childNodes.forEach((child) => {
-                if (child.nodeName == 'SPAN') {
+                if (child.nodeName === 'SPAN') {
                     //@ts-ignore
                     temp.parentDivs.push(div)
                     //@ts-ignore
@@ -221,7 +221,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
         let index: any;
         this._pageInfo.divs.forEach((obj: any) => {
             obj.spans.forEach((element: any) => {
-                if (element == span) {
+                if (element === span) {
                     if (!index) {
                         index = this._pageInfo.divs.indexOf(obj);
                     }
@@ -230,11 +230,11 @@ export class PDFBox extends React.Component<FieldViewProps> {
         })
 
         if (this._pageInfo.anno.length >= index + 1) {
-            if (this._currAnno.length == 0) {
+            if (this._currAnno.length === 0) {
                 this._currAnno.push(this._pageInfo.anno[index]);
             }
         } else {
-            if (this._currAnno.length == 0) { //if there are no current annotation
+            if (this._currAnno.length === 0) { //if there are no current annotation
                 let div = span.offsetParent;
                 //@ts-ignore
                 let divX = div.style.left
@@ -315,7 +315,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
      * starts drawing the line when user presses down. 
      */
     onDraw = () => {
-        if (this._currTool != null) {
+        if (this._currTool !== null) {
             this._currTool.style.backgroundColor = "grey";
         }
 
@@ -340,13 +340,13 @@ export class PDFBox extends React.Component<FieldViewProps> {
      * for changing color (for ink/pen)
      */
     onColorChange = (e: React.PointerEvent) => {
-        if (e.currentTarget.innerHTML == "Red") {
+        if (e.currentTarget.innerHTML === "Red") {
             this._currColor = "red";
-        } else if (e.currentTarget.innerHTML == "Blue") {
+        } else if (e.currentTarget.innerHTML === "Blue") {
             this._currColor = "blue";
-        } else if (e.currentTarget.innerHTML == "Green") {
+        } else if (e.currentTarget.innerHTML === "Green") {
             this._currColor = "green";
-        } else if (e.currentTarget.innerHTML == "Black") {
+        } else if (e.currentTarget.innerHTML === "Black") {
             this._currColor = "black";
         }
 
@@ -358,7 +358,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
      */
     onHighlight = () => {
         this._drawToolOn = false;
-        if (this._currTool != null) {
+        if (this._currTool !== null) {
             this._currTool.style.backgroundColor = "grey";
         }
         if (this._highlightTool.current) {
@@ -394,7 +394,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
     onLoaded = (page: any) => {
         if (this._mainDiv.current) {
             this._mainDiv.current.childNodes.forEach((element) => {
-                if (element.nodeName == "DIV") {
+                if (element.nodeName === "DIV") {
                     element.childNodes[0].childNodes.forEach((e) => {
 
                         if (e instanceof HTMLCanvasElement) {
@@ -410,7 +410,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
 
         // bcz: the number of pages should really be set when the document is imported.
         this.props.Document.SetNumber(KeyStore.NumPages, page._transport.numPages);
-        if (this._perPageInfo.length == 0) { //Makes sure it only runs once
+        if (this._perPageInfo.length === 0) { //Makes sure it only runs once
             this._perPageInfo = [...Array(page._transport.numPages)]
         }
         this._loaded = true;
@@ -455,7 +455,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
     get pdfRenderer() {
         let proxy = this._loaded ? (null) : this.imageProxyRenderer;
         let pdfUrl = this.props.Document.GetT(this.props.fieldKey, PDFField);
-        if ((!this._interactive && proxy) || !pdfUrl || pdfUrl == FieldWaiting) {
+        if ((!this._interactive && proxy) || !pdfUrl || pdfUrl === FieldWaiting) {
             return proxy;
         }
         return [
@@ -470,7 +470,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
     get imageProxyRenderer() {
         let thumbField = this.props.Document.Get(KeyStore.Thumbnail);
         if (thumbField) {
-            let path = thumbField == FieldWaiting || this.thumbnailPage != this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
+            let path = thumbField === FieldWaiting || this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
                 thumbField instanceof ImageField ? thumbField.Data.href : "http://cs.brown.edu/people/bcz/prairie.jpg";
             return <img src={path} width="100%" />;
         }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 72495a964..b4590df34 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -50,8 +50,8 @@ export class VideoBox extends React.Component<FieldViewProps> {
     @action
     setVideoRef = (vref: HTMLVideoElement | null) => {
         if (this.curPage >= 0 && vref) {
-            vref!.currentTime = this.curPage;
-            (vref! as any).AHackBecauseSomethingResetsTheVideoToZero = this.curPage;
+            vref.currentTime = this.curPage;
+            (vref as any).AHackBecauseSomethingResetsTheVideoToZero = this.curPage;
         }
     }
 
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index 7fdd77bf3..9f52d0ea6 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -87,7 +87,7 @@ class DocumentViewer extends React.Component<{ field: Document }> {
             return (
                 <div key={kv[0]}>
                     <b>({key ? key.Name : kv[0]}): </b>
-                    <DebugViewer fieldId={kv[1]!}></DebugViewer>
+                    <DebugViewer fieldId={kv[1]}></DebugViewer>
                 </div>
             )
         })
@@ -177,9 +177,8 @@ class Viewer extends React.Component {
                     onChange={this.inputOnChange}
                     onKeyDown={this.onKeyPress} />
                 <div>
-                    {this.ids.map(id => {
-                        return <DebugViewer fieldId={id} key={id}></DebugViewer>
-                    })}
+                    {this.ids.map(id =>
+                        <DebugViewer fieldId={id} key={id}></DebugViewer>)}
                 </div>
             </>
         )
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 85ff6ddcb..45e4f93f6 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -30,9 +30,9 @@ export class Document extends Field {
         }
     }
 
-    public Width = () => { return this.GetNumber(KeyStore.Width, 0) }
-    public Height = () => { return this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0) * this.GetNumber(KeyStore.Width, 0) : 0) }
-    public Scale = () => { return this.GetNumber(KeyStore.Scale, 1) }
+    public Width = () => this.GetNumber(KeyStore.Width, 0)
+    public Height = () => this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0) * this.GetNumber(KeyStore.Width, 0) : 0)
+    public Scale = () => this.GetNumber(KeyStore.Scale, 1)
 
     @computed
     public get Title(): string {
@@ -90,7 +90,7 @@ export class Document extends Field {
             }
         } else {
             let doc: FieldValue<Document> = this;
-            while (doc && doc != FieldWaiting && field != FieldWaiting) {
+            while (doc && doc !== FieldWaiting && field !== FieldWaiting) {
                 let curField = doc.fields.get(key.Id);
                 let curProxy = doc._proxies.get(key.Id);
                 if (!curField || (curProxy && curField.field.Id !== curProxy)) {
@@ -118,7 +118,7 @@ export class Document extends Field {
                     break;
                 }
             }
-            if (doc == FieldWaiting)
+            if (doc === FieldWaiting)
                 field = FieldWaiting;
         }
 
@@ -165,7 +165,7 @@ export class Document extends Field {
         if (callback) {
             fn(callback);
         } else {
-            return new Promise(res => fn(res));
+            return new Promise(fn);
         }
     }
 
@@ -356,7 +356,7 @@ export class Document extends Field {
         let fields: [string, string][] = []
         this._proxies.forEach((field, key) => {
             if (field) {
-                fields.push([key, field as string])
+                fields.push([key, field])
             }
         });
 
diff --git a/src/fields/WebField.ts b/src/fields/WebField.ts
index 6c4de5000..0cbcc6d33 100644
--- a/src/fields/WebField.ts
+++ b/src/fields/WebField.ts
@@ -4,7 +4,7 @@ import { Types } from "../server/Message";
 
 export class WebField extends BasicField<URL> {
     constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
-        super(data == undefined ? new URL("https://crossorigin.me/" + "https://cs.brown.edu/") : data, save, id);
+        super(data === undefined ? new URL("https://crossorigin.me/" + "https://cs.brown.edu/") : data, save, id);
     }
 
     toString(): string {
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index ae48dd2c6..c4d346876 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -33,9 +33,8 @@ const onFileLoad = (file: any) => {
             fetch(upload, {
                 method: 'POST',
                 body: formData
-            }).then((res: Response) => {
-                return res.json()
-            }).then(json => {
+            }).then((res: Response) =>
+                res.json()).then(json => {
                 json.map((file: any) => {
                     let path = window.location.origin + file
                     var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 })
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 8e14cf98e..835432c8e 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -73,7 +73,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                         <span>{i + 1} - </span>
                         <EditableView
                             display={"inline"}
-                            GetValue={() => { return s.Title }}
+                            GetValue={() => s.Title}
                             SetValue={(title: string): boolean => {
                                 s.SetText(KeyStore.Title, title);
                                 return true;
diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts
index e365b8dce..2bbb334b5 100644
--- a/src/server/authentication/controllers/user_controller.ts
+++ b/src/server/authentication/controllers/user_controller.ts
@@ -4,7 +4,7 @@ import * as passport from "passport";
 import { IVerifyOptions } from "passport-local";
 import "../config/passport";
 import * as request from "express-validator";
-const flash = require("express-flash");
+import flash = require("express-flash");
 import * as session from "express-session";
 import * as pug from 'pug';
 import * as async from 'async';
@@ -109,12 +109,12 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
     }
 
     passport.authenticate("local", (err: Error, user: DashUserModel, info: IVerifyOptions) => {
-        if (err) { return next(err); }
+        if (err) { next(err); return }
         if (!user) {
             return res.redirect(RouteStore.signup);
         }
         req.logIn(user, (err) => {
-            if (err) { return next(err); }
+            if (err) { next(err); return }
             res.redirect(RouteStore.home);
         });
     })(req, res, next);
@@ -158,7 +158,8 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio
             User.findOne({ email }, function (err, user: DashUserModel) {
                 if (!user) {
                     // NO ACCOUNT WITH SUBMITTED EMAIL
-                    return res.redirect(RouteStore.forgot);
+                    res.redirect(RouteStore.forgot);
+                    return
                 }
                 user.passwordResetToken = token;
                 user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 HOUR
@@ -228,7 +229,8 @@ export let postReset = function (req: Request, res: Response) {
 
                 user.save(function (err) {
                     if (err) {
-                        return res.redirect(RouteStore.login);
+                        res.redirect(RouteStore.login);
+                        return;
                     }
                     req.logIn(user, function (err) {
                         if (err) {
diff --git a/src/server/database.ts b/src/server/database.ts
index a42d29aac..87a0b3c70 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -27,7 +27,7 @@ export class Database {
                     console.log(err.errmsg);
                 }
                 if (res) {
-                    console.log(JSON.stringify(res.result));
+                    // console.log(JSON.stringify(res.result));
                 }
                 callback()
             });
diff --git a/src/server/index.ts b/src/server/index.ts
index 17d7432e0..0c61f6885 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -264,11 +264,9 @@ function deleteFields() {
 }
 
 function deleteAll() {
-    return Database.Instance.deleteAll().then(() => {
-        return Database.Instance.deleteAll('sessions')
-    }).then(() => {
-        return Database.Instance.deleteAll('users')
-    });
+    return Database.Instance.deleteAll().then(() =>
+        Database.Instance.deleteAll('sessions')).then(() =>
+            Database.Instance.deleteAll('users'));
 }
 
 function barReceived(guid: String) {
diff --git a/test/test.ts b/test/test.ts
index 0fa1ea15b..db24cae5f 100644
--- a/test/test.ts
+++ b/test/test.ts
@@ -152,7 +152,7 @@ describe("Reference", () => {
         let ran = false;
         reaction(() => {
             let field = doc2.GetT(key, NumberField);
-            if (field && field != FieldWaiting) {
+            if (field && field !== FieldWaiting) {
                 return field.Data;
             }
             return undefined;
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 000000000..54876916e
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,56 @@
+{
+    "rules": {
+        // "no-non-null-assertion": true,
+        "no-return-await": true,
+        "no-string-literal": true,
+        // "no-var-keyword": true,
+        // "no-var-requires": true,
+        "prefer-object-spread": true,
+        "prefer-for-of": true,
+        "no-unnecessary-type-assertion": true,
+        // "no-void-expression": [
+        //     true,
+        //     "ignore-arrow-function-shorthand"
+        // ],
+        "triple-equals": true,
+        // "prefer-const": true,
+        "no-unnecessary-callback-wrapper": true,
+        // "align": [
+        //     true,
+        //     "parameters",
+        //     "arguments",
+        //     "statements",
+        //     "members",
+        //     "elements"
+        // ],
+        "class-name": true,
+        "arrow-return-shorthand": true,
+        // "object-literal-shorthand": true,
+        // "object-literal-sort-keys": true,
+        // "semicolon": [
+        //     true,
+        //     "always"
+        // ],
+        // "curly": [
+        //     true,
+        //     "ignore-same-line"
+        // ],
+        // "quotemark": [
+        //     true,
+        //     "double",
+        //     "jsx-double",
+        //     "avoid-template",
+        //     "avoid-escape"
+        // ],
+        "no-tautology-expression": true,
+        "unnecessary-constructor": true
+        // "trailing-comma": [
+        //     true,
+        //     {
+        //         "multiline": "always",
+        //         "singleline": "never"
+        //     }
+        // ],
+        // "ordered-imports": true
+    }
+}
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index 5ba9dd4b5..50079255f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -28,44 +28,53 @@ module.exports = {
     extensions: ['.js', '.ts', '.tsx']
   },
   module: {
-    rules: [{
-      test: [/\.tsx?$/, /\.ts?$/,],
-      loader: "awesome-typescript-loader",
-      include: path.join(__dirname, 'src')
-    },
-    {
-      test: /\.scss|css$/,
-      use: [
-        {
-          loader: "style-loader"
-        },
-        {
-          loader: "css-loader"
-        },
-        {
-          loader: "sass-loader"
-        }
-      ]
-    },
-    {
-      test: /\.(jpg|png|pdf)$/,
-      use: [
-        {
-          loader: 'file-loader'
-        }
-      ]
-    },
-    {
-      test: /\.(png|jpg|gif)$/i,
-      use: [
-        {
-          loader: 'url-loader',
-          options: {
-            limit: 8192
+    rules: [
+      {
+        test: [/\.tsx?$/, /\.ts?$/,],
+        enforce: 'pre',
+        use: [
+          {
+            loader: "tslint-loader",
           }
-        }
-      ]
-    }]
+        ]
+      }, {
+        test: [/\.tsx?$/, /\.ts?$/,],
+        loader: "awesome-typescript-loader",
+        include: path.join(__dirname, 'src')
+      },
+      {
+        test: /\.scss|css$/,
+        use: [
+          {
+            loader: "style-loader"
+          },
+          {
+            loader: "css-loader"
+          },
+          {
+            loader: "sass-loader"
+          }
+        ]
+      },
+      {
+        test: /\.(jpg|png|pdf)$/,
+        use: [
+          {
+            loader: 'file-loader'
+          }
+        ]
+      },
+      {
+        test: /\.(png|jpg|gif)$/i,
+        use: [
+          {
+            loader: 'url-loader',
+            options: {
+              limit: 8192
+            }
+          }
+        ]
+      }]
   },
   plugins: [
     new CopyWebpackPlugin([{ from: "deploy", to: path.join(__dirname, "build") }]),
-- 
cgit v1.2.3-70-g09d2


From b78aff5115862cbfa5e704422cb738aa7fd73c64 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 4 Apr 2019 14:13:29 -0400
Subject: fixed a number of smaller issues related to linking

---
 src/client/northstar/dash-nodes/HistogramBox.scss  |   5 +
 src/client/util/DragManager.ts                     | 533 +++++++-------
 src/client/util/SelectionManager.ts                |  74 +-
 src/client/views/DocumentDecorations.scss          |  61 +-
 src/client/views/DocumentDecorations.tsx           |  81 ++-
 src/client/views/InkingCanvas.scss                 |   2 +
 src/client/views/Main.scss                         |   7 +
 .../views/collections/CollectionDockingView.scss   |   2 +-
 .../views/collections/CollectionPDFView.scss       |   2 +
 .../views/collections/CollectionVideoView.scss     |   2 +
 .../views/collections/CollectionViewBase.tsx       |  20 +
 .../CollectionFreeFormLinkView.tsx                 |   8 +-
 .../CollectionFreeFormLinksView.scss               |   2 +
 .../collectionFreeForm/CollectionFreeFormView.scss |   6 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  13 +-
 .../collectionFreeForm/MarqueeView.scss            |   2 +
 .../collectionFreeForm/PreviewCursor.scss          |   4 +
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   4 +
 src/client/views/nodes/DocumentView.scss           |   2 +
 src/client/views/nodes/PDFBox.scss                 |   4 +
 src/client/views/nodes/WebBox.scss                 |   2 +
 src/fields/Document.ts                             | 773 +++++++++++----------
 22 files changed, 882 insertions(+), 727 deletions(-)

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

diff --git a/src/client/northstar/dash-nodes/HistogramBox.scss b/src/client/northstar/dash-nodes/HistogramBox.scss
index b11840a65..94da36e29 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.scss
+++ b/src/client/northstar/dash-nodes/HistogramBox.scss
@@ -1,6 +1,8 @@
 .histogrambox-container {
     padding: 0vw;
     position: absolute;
+    top: 0;
+    left:0;
     text-align: center;
     width: 100%;
     height: 100%;
@@ -8,6 +10,7 @@
   }
   .histogrambox-xaxislabel {
     position:absolute;
+    left:0;
     width:100%;
     text-align: center;
     bottom:0;
@@ -19,11 +22,13 @@
     position:absolute;
     height:100%;
     width: 25px;
+    left:0;
     bottom:0;
     background: lightgray;
   }
   .histogrambox-yaxislabel-text {
     position:absolute;
+    left:0;
     transform-origin: left;
     transform: rotate(-90deg);
     text-align: center;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index c0f482e18..e8f8cce7c 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -8,304 +8,307 @@ import { CollectionView } from "../views/collections/CollectionView";
 import { DocumentView } from "../views/nodes/DocumentView";
 
 export function setupDrag(
-  _reference: React.RefObject<HTMLDivElement>,
-  docFunc: () => Document,
-  removeFunc: (containingCollection: CollectionView) => void = () => {}
+    _reference: React.RefObject<HTMLDivElement>,
+    docFunc: () => Document,
+    removeFunc: (containingCollection: CollectionView) => void = () => { }
 ) {
-  let onRowMove = action(
-    (e: PointerEvent): void => {
-      e.stopPropagation();
-      e.preventDefault();
+    let onRowMove = action(
+        (e: PointerEvent): void => {
+            e.stopPropagation();
+            e.preventDefault();
 
-      document.removeEventListener("pointermove", onRowMove);
-      document.removeEventListener("pointerup", onRowUp);
-      var dragData = new DragManager.DocumentDragData([docFunc()]);
-      dragData.removeDocument = removeFunc;
-      DragManager.StartDocumentDrag([_reference.current!], dragData);
-    }
-  );
-  let onRowUp = action(
-    (e: PointerEvent): void => {
-      document.removeEventListener("pointermove", onRowMove);
-      document.removeEventListener("pointerup", onRowUp);
-    }
-  );
-  let onItemDown = (e: React.PointerEvent) => {
-    // if (this.props.isSelected() || this.props.isTopMost) {
-    if (e.button == 0) {
-      e.stopPropagation();
-      if (e.shiftKey) {
-        CollectionDockingView.Instance.StartOtherDrag([docFunc()], e);
-      } else {
-        document.addEventListener("pointermove", onRowMove);
-        document.addEventListener("pointerup", onRowUp);
-      }
-    }
-    //}
-  };
-  return onItemDown;
+            document.removeEventListener("pointermove", onRowMove);
+            document.removeEventListener("pointerup", onRowUp);
+            var dragData = new DragManager.DocumentDragData([docFunc()]);
+            dragData.removeDocument = removeFunc;
+            DragManager.StartDocumentDrag([_reference.current!], dragData);
+        }
+    );
+    let onRowUp = action(
+        (e: PointerEvent): void => {
+            document.removeEventListener("pointermove", onRowMove);
+            document.removeEventListener("pointerup", onRowUp);
+        }
+    );
+    let onItemDown = (e: React.PointerEvent) => {
+        // if (this.props.isSelected() || this.props.isTopMost) {
+        if (e.button == 0) {
+            e.stopPropagation();
+            if (e.shiftKey) {
+                CollectionDockingView.Instance.StartOtherDrag([docFunc()], e);
+            } else {
+                document.addEventListener("pointermove", onRowMove);
+                document.addEventListener("pointerup", onRowUp);
+            }
+        }
+        //}
+    };
+    return onItemDown;
 }
 
 export namespace DragManager {
-  export function Root() {
-    const root = document.getElementById("root");
-    if (!root) {
-      throw new Error("No root element found");
+    export function Root() {
+        const root = document.getElementById("root");
+        if (!root) {
+            throw new Error("No root element found");
+        }
+        return root;
     }
-    return root;
-  }
 
-  let dragDiv: HTMLDivElement;
+    let dragDiv: HTMLDivElement;
 
-  export enum DragButtons {
-    Left = 1,
-    Right = 2,
-    Both = Left | Right
-  }
+    export enum DragButtons {
+        Left = 1,
+        Right = 2,
+        Both = Left | Right
+    }
 
-  interface DragOptions {
-    handlers: DragHandlers;
+    interface DragOptions {
+        handlers: DragHandlers;
 
-    hideSource: boolean | (() => boolean);
-  }
+        hideSource: boolean | (() => boolean);
+    }
 
-  export interface DragDropDisposer {
-    (): void;
-  }
+    export interface DragDropDisposer {
+        (): void;
+    }
 
-  export class DragCompleteEvent {}
+    export class DragCompleteEvent { }
 
-  export interface DragHandlers {
-    dragComplete: (e: DragCompleteEvent) => void;
-  }
+    export interface DragHandlers {
+        dragComplete: (e: DragCompleteEvent) => void;
+    }
 
-  export interface DropOptions {
-    handlers: DropHandlers;
-  }
-  export class DropEvent {
-    constructor(
-      readonly x: number,
-      readonly y: number,
-      readonly data: { [id: string]: any }
-    ) {}
-  }
+    export interface DropOptions {
+        handlers: DropHandlers;
+    }
+    export class DropEvent {
+        constructor(
+            readonly x: number,
+            readonly y: number,
+            readonly data: { [id: string]: any }
+        ) { }
+    }
 
-  export interface DropHandlers {
-    drop: (e: Event, de: DropEvent) => void;
-  }
+    export interface DropHandlers {
+        drop: (e: Event, de: DropEvent) => void;
+    }
 
-  export function MakeDropTarget(
-    element: HTMLElement,
-    options: DropOptions
-  ): DragDropDisposer {
-    if ("canDrop" in element.dataset) {
-      throw new Error(
-        "Element is already droppable, can't make it droppable again"
-      );
+    export function MakeDropTarget(
+        element: HTMLElement,
+        options: DropOptions
+    ): DragDropDisposer {
+        if ("canDrop" in element.dataset) {
+            throw new Error(
+                "Element is already droppable, can't make it droppable again"
+            );
+        }
+        element.dataset["canDrop"] = "true";
+        const handler = (e: Event) => {
+            const ce = e as CustomEvent<DropEvent>;
+            options.handlers.drop(e, ce.detail);
+        };
+        element.addEventListener("dashOnDrop", handler);
+        return () => {
+            element.removeEventListener("dashOnDrop", handler);
+            delete element.dataset["canDrop"];
+        };
     }
-    element.dataset["canDrop"] = "true";
-    const handler = (e: Event) => {
-      const ce = e as CustomEvent<DropEvent>;
-      options.handlers.drop(e, ce.detail);
-    };
-    element.addEventListener("dashOnDrop", handler);
-    return () => {
-      element.removeEventListener("dashOnDrop", handler);
-      delete element.dataset["canDrop"];
-    };
-  }
 
-  export class DocumentDragData {
-    constructor(dragDoc: Document[]) {
-      this.draggedDocuments = dragDoc;
-      this.droppedDocuments = dragDoc;
+    export class DocumentDragData {
+        constructor(dragDoc: Document[]) {
+            this.draggedDocuments = dragDoc;
+            this.droppedDocuments = dragDoc;
+        }
+        draggedDocuments: Document[];
+        droppedDocuments: Document[];
+        xOffset?: number;
+        yOffset?: number;
+        aliasOnDrop?: boolean;
+        removeDocument?: (collectionDrop: CollectionView) => void;
+        [id: string]: any;
     }
-    draggedDocuments: Document[];
-    droppedDocuments: Document[];
-    xOffset?: number;
-    yOffset?: number;
-    aliasOnDrop?: boolean;
-    removeDocument?: (collectionDrop: CollectionView) => void;
-    [id: string]: any;
-  }
 
-  export function StartDocumentDrag(
-    eles: HTMLElement[],
-    dragData: DocumentDragData,
-    options?: DragOptions
-  ) {
-    StartDrag(
-      eles,
-      dragData,
-      options,
-      (dropData: { [id: string]: any }) =>
-        (dropData.droppedDocuments = dragData.aliasOnDrop
-          ? dragData.draggedDocuments.map(d => d.CreateAlias())
-          : dragData.draggedDocuments)
-    );
-  }
+    export function StartDocumentDrag(
+        eles: HTMLElement[],
+        dragData: DocumentDragData,
+        options?: DragOptions
+    ) {
+        StartDrag(
+            eles,
+            dragData,
+            options,
+            (dropData: { [id: string]: any }) =>
+                (dropData.droppedDocuments = dragData.aliasOnDrop
+                    ? dragData.draggedDocuments.map(d => d.CreateAlias())
+                    : dragData.draggedDocuments)
+        );
+    }
 
-  export class LinkDragData {
-    constructor(linkSourceDoc: DocumentView) {
-      this.linkSourceDocumentView = linkSourceDoc;
+    export class LinkDragData {
+        constructor(linkSourceDoc: DocumentView) {
+            this.linkSourceDocumentView = linkSourceDoc;
+        }
+        droppedDocuments: Document[] = [];
+        linkSourceDocumentView: DocumentView;
+        [id: string]: any;
     }
-    linkSourceDocumentView: DocumentView;
-    [id: string]: any;
-  }
-  export function StartLinkDrag(
-    ele: HTMLElement,
-    dragData: LinkDragData,
-    options?: DragOptions
-  ) {
-    StartDrag([ele], dragData, options);
-  }
-  function StartDrag(
-    eles: HTMLElement[],
-    dragData: { [id: string]: any },
-    options?: DragOptions,
-    finishDrag?: (dropData: { [id: string]: any }) => void
-  ) {
-    if (!dragDiv) {
-      dragDiv = document.createElement("div");
-      dragDiv.className = "dragManager-dragDiv";
-      DragManager.Root().appendChild(dragDiv);
+    export function StartLinkDrag(
+        ele: HTMLElement,
+        dragData: LinkDragData,
+        options?: DragOptions
+    ) {
+        StartDrag([ele], dragData, options);
     }
+    function StartDrag(
+        eles: HTMLElement[],
+        dragData: { [id: string]: any },
+        options?: DragOptions,
+        finishDrag?: (dropData: { [id: string]: any }) => void
+    ) {
+        if (!dragDiv) {
+            dragDiv = document.createElement("div");
+            dragDiv.className = "dragManager-dragDiv";
+            DragManager.Root().appendChild(dragDiv);
+        }
 
-    let scaleXs: number[] = [];
-    let scaleYs: number[] = [];
-    let xs: number[] = [];
-    let ys: number[] = [];
+        let scaleXs: number[] = [];
+        let scaleYs: number[] = [];
+        let xs: number[] = [];
+        let ys: number[] = [];
 
-    const docs: Document[] =
-      dragData instanceof DocumentDragData ? dragData.draggedDocuments : [];
-    let dragElements = eles.map(ele => {
-      const w = ele.offsetWidth,
-        h = ele.offsetHeight;
-      const rect = ele.getBoundingClientRect();
-      const scaleX = rect.width / w,
-        scaleY = rect.height / h;
-      let x = rect.left,
-        y = rect.top;
-      xs.push(x);
-      ys.push(y);
-      scaleXs.push(scaleX);
-      scaleYs.push(scaleY);
-      let dragElement = ele.cloneNode(true) as HTMLElement;
-      dragElement.style.opacity = "0.7";
-      dragElement.style.position = "absolute";
-      dragElement.style.bottom = "";
-      dragElement.style.left = "";
-      dragElement.style.transformOrigin = "0 0";
-      dragElement.style.zIndex = "1000";
-      dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
-      dragElement.style.width = `${rect.width / scaleX}px`;
-      dragElement.style.height = `${rect.height / scaleY}px`;
+        const docs: Document[] =
+            dragData instanceof DocumentDragData ? dragData.draggedDocuments : [];
+        let dragElements = eles.map(ele => {
+            const w = ele.offsetWidth,
+                h = ele.offsetHeight;
+            const rect = ele.getBoundingClientRect();
+            const scaleX = rect.width / w,
+                scaleY = rect.height / h;
+            let x = rect.left,
+                y = rect.top;
+            xs.push(x);
+            ys.push(y);
+            scaleXs.push(scaleX);
+            scaleYs.push(scaleY);
+            let dragElement = ele.cloneNode(true) as HTMLElement;
+            dragElement.style.opacity = "0.7";
+            dragElement.style.position = "absolute";
+            dragElement.style.margin = "0";
+            dragElement.style.top = "0";
+            dragElement.style.bottom = "";
+            dragElement.style.left = "0";
+            dragElement.style.transformOrigin = "0 0";
+            dragElement.style.zIndex = "1000";
+            dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
+            dragElement.style.width = `${rect.width / scaleX}px`;
+            dragElement.style.height = `${rect.height / scaleY}px`;
 
-      // bcz: PDFs don't show up if you clone them because they contain a canvas.
-      //      however, PDF's have a thumbnail field that contains an image of their canvas.
-      //      So we replace the pdf's canvas with the image thumbnail
-      if (docs.length) {
-        var pdfBox = dragElement.getElementsByClassName(
-          "pdfBox-cont"
-        )[0] as HTMLElement;
-        let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
-        if (pdfBox && pdfBox.childElementCount && thumbnail) {
-          let img = new Image();
-          img!.src = thumbnail.toString();
-          img!.style.position = "absolute";
-          img!.style.width = `${rect.width / scaleX}px`;
-          img!.style.height = `${rect.height / scaleY}px`;
-          pdfBox.replaceChild(img!, pdfBox.children[0]);
+            // bcz: PDFs don't show up if you clone them because they contain a canvas.
+            //      however, PDF's have a thumbnail field that contains an image of their canvas.
+            //      So we replace the pdf's canvas with the image thumbnail
+            if (docs.length) {
+                var pdfBox = dragElement.getElementsByClassName(
+                    "pdfBox-cont"
+                )[0] as HTMLElement;
+                let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
+                if (pdfBox && pdfBox.childElementCount && thumbnail) {
+                    let img = new Image();
+                    img!.src = thumbnail.toString();
+                    img!.style.position = "absolute";
+                    img!.style.width = `${rect.width / scaleX}px`;
+                    img!.style.height = `${rect.height / scaleY}px`;
+                    pdfBox.replaceChild(img!, pdfBox.children[0]);
+                }
+            }
+
+            dragDiv.appendChild(dragElement);
+            return dragElement;
+        });
+
+        let hideSource = false;
+        if (options) {
+            if (typeof options.hideSource === "boolean") {
+                hideSource = options.hideSource;
+            } else {
+                hideSource = options.hideSource();
+            }
         }
-      }
+        eles.map(ele => (ele.hidden = hideSource));
 
-      dragDiv.appendChild(dragElement);
-      return dragElement;
-    });
+        const moveHandler = (e: PointerEvent) => {
+            e.stopPropagation();
+            e.preventDefault();
+            if (dragData instanceof DocumentDragData)
+                dragData.aliasOnDrop = e.ctrlKey || e.altKey;
+            if (e.shiftKey) {
+                abortDrag();
+                CollectionDockingView.Instance.StartOtherDrag(docs, {
+                    pageX: e.pageX,
+                    pageY: e.pageY,
+                    preventDefault: () => { },
+                    button: 0
+                });
+            }
+            dragElements.map(
+                (dragElement, i) =>
+                    (dragElement.style.transform = `translate(${(xs[i] +=
+                        e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${
+                        scaleXs[i]
+                        }, ${scaleYs[i]})`)
+            );
+        };
 
-    let hideSource = false;
-    if (options) {
-      if (typeof options.hideSource === "boolean") {
-        hideSource = options.hideSource;
-      } else {
-        hideSource = options.hideSource();
-      }
+        const abortDrag = () => {
+            document.removeEventListener("pointermove", moveHandler, true);
+            document.removeEventListener("pointerup", upHandler);
+            dragElements.map(dragElement => dragDiv.removeChild(dragElement));
+            eles.map(ele => (ele.hidden = false));
+        };
+        const upHandler = (e: PointerEvent) => {
+            abortDrag();
+            FinishDrag(eles, e, dragData, options, finishDrag);
+        };
+        document.addEventListener("pointermove", moveHandler, true);
+        document.addEventListener("pointerup", upHandler);
     }
-    eles.map(ele => (ele.hidden = hideSource));
 
-    const moveHandler = (e: PointerEvent) => {
-      e.stopPropagation();
-      e.preventDefault();
-      if (dragData instanceof DocumentDragData)
-        dragData.aliasOnDrop = e.ctrlKey || e.altKey;
-      if (e.shiftKey) {
-        abortDrag();
-        CollectionDockingView.Instance.StartOtherDrag(docs, {
-          pageX: e.pageX,
-          pageY: e.pageY,
-          preventDefault: () => {},
-          button: 0
+    function FinishDrag(
+        dragEles: HTMLElement[],
+        e: PointerEvent,
+        dragData: { [index: string]: any },
+        options?: DragOptions,
+        finishDrag?: (dragData: { [index: string]: any }) => void
+    ) {
+        let removed = dragEles.map(dragEle => {
+            let parent = dragEle.parentElement;
+            if (parent) parent.removeChild(dragEle);
+            return [dragEle, parent];
         });
-      }
-      dragElements.map(
-        (dragElement, i) =>
-          (dragElement.style.transform = `translate(${(xs[i] +=
-            e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${
-            scaleXs[i]
-          }, ${scaleYs[i]})`)
-      );
-    };
-
-    const abortDrag = () => {
-      document.removeEventListener("pointermove", moveHandler, true);
-      document.removeEventListener("pointerup", upHandler);
-      dragElements.map(dragElement => dragDiv.removeChild(dragElement));
-      eles.map(ele => (ele.hidden = false));
-    };
-    const upHandler = (e: PointerEvent) => {
-      abortDrag();
-      FinishDrag(eles, e, dragData, options, finishDrag);
-    };
-    document.addEventListener("pointermove", moveHandler, true);
-    document.addEventListener("pointerup", upHandler);
-  }
-
-  function FinishDrag(
-    dragEles: HTMLElement[],
-    e: PointerEvent,
-    dragData: { [index: string]: any },
-    options?: DragOptions,
-    finishDrag?: (dragData: { [index: string]: any }) => void
-  ) {
-    let removed = dragEles.map(dragEle => {
-      let parent = dragEle.parentElement;
-      if (parent) parent.removeChild(dragEle);
-      return [dragEle, parent];
-    });
-    const target = document.elementFromPoint(e.x, e.y);
-    removed.map(r => {
-      let dragEle: HTMLElement = r[0]!;
-      let parent: HTMLElement | null = r[1];
-      if (parent) parent.appendChild(dragEle);
-    });
-    if (target) {
-      if (finishDrag) finishDrag(dragData);
+        const target = document.elementFromPoint(e.x, e.y);
+        removed.map(r => {
+            let dragEle: HTMLElement = r[0]!;
+            let parent: HTMLElement | null = r[1];
+            if (parent) parent.appendChild(dragEle);
+        });
+        if (target) {
+            if (finishDrag) finishDrag(dragData);
 
-      target.dispatchEvent(
-        new CustomEvent<DropEvent>("dashOnDrop", {
-          bubbles: true,
-          detail: {
-            x: e.x,
-            y: e.y,
-            data: dragData
-          }
-        })
-      );
+            target.dispatchEvent(
+                new CustomEvent<DropEvent>("dashOnDrop", {
+                    bubbles: true,
+                    detail: {
+                        x: e.x,
+                        y: e.y,
+                        data: dragData
+                    }
+                })
+            );
 
-      if (options) {
-        options.handlers.dragComplete({});
-      }
+            if (options) {
+                options.handlers.dragComplete({});
+            }
+        }
+        DocumentDecorations.Instance.Hidden = false;
     }
-    DocumentDecorations.Instance.Hidden = false;
-  }
 }
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 438659108..958c14491 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -3,48 +3,46 @@ import { DocumentView } from "../views/nodes/DocumentView";
 import { Document } from "../../fields/Document";
 
 export namespace SelectionManager {
-  class Manager {
-    @observable
-    SelectedDocuments: Array<DocumentView> = [];
-
-    @action
-    SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
-      // if doc is not in SelectedDocuments, add it
-      if (!ctrlPressed) {
-        manager.SelectedDocuments = [];
-      }
-
-      if (manager.SelectedDocuments.indexOf(doc) === -1) {
-        manager.SelectedDocuments.push(doc);
-      }
+    class Manager {
+        @observable
+        SelectedDocuments: Array<DocumentView> = [];
+
+        @action
+        SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
+            // if doc is not in SelectedDocuments, add it
+            if (!ctrlPressed) {
+                manager.SelectedDocuments = [];
+            }
+
+            if (manager.SelectedDocuments.indexOf(doc) === -1) {
+                manager.SelectedDocuments.push(doc);
+            }
+        }
     }
-  }
 
-  const manager = new Manager();
+    const manager = new Manager();
 
-  export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
-    if (!doc.isMinimized()) {
-      manager.SelectDoc(doc, ctrlPressed);
+    export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
+        manager.SelectDoc(doc, ctrlPressed);
     }
-  }
-
-  export function IsSelected(doc: DocumentView): boolean {
-    return manager.SelectedDocuments.indexOf(doc) !== -1;
-  }
-
-  export function DeselectAll(except?: Document): void {
-    let found: DocumentView | undefined = undefined;
-    if (except) {
-      for (let i = 0; i < manager.SelectedDocuments.length; i++) {
-        let view = manager.SelectedDocuments[i];
-        if (view.props.Document == except) found = view;
-      }
+
+    export function IsSelected(doc: DocumentView): boolean {
+        return manager.SelectedDocuments.indexOf(doc) !== -1;
+    }
+
+    export function DeselectAll(except?: Document): void {
+        let found: DocumentView | undefined = undefined;
+        if (except) {
+            for (let i = 0; i < manager.SelectedDocuments.length; i++) {
+                let view = manager.SelectedDocuments[i];
+                if (view.props.Document == except) found = view;
+            }
+        }
+        manager.SelectedDocuments.length = 0;
+        if (found) manager.SelectedDocuments.push(found);
     }
-    manager.SelectedDocuments.length = 0;
-    if (found) manager.SelectedDocuments.push(found);
-  }
 
-  export function SelectedDocuments(): Array<DocumentView> {
-    return manager.SelectedDocuments;
-  }
+    export function SelectedDocuments(): Array<DocumentView> {
+        return manager.SelectedDocuments;
+    }
 }
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index befe175b5..080c9fa1e 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -2,13 +2,16 @@
 
 #documentDecorations-container {
     position: absolute;
+    top: 0;
+    left:0;
     display: grid;
     z-index: 1000;
     grid-template-rows: 20px 8px 1fr 8px;
-    grid-template-columns: 8px 1fr 8px;
+    grid-template-columns: 8px 8px 1fr 8px;
     pointer-events: none;
 
     #documentDecorations-centerCont {
+        grid-column:3;
         background: none;
     }
 
@@ -18,6 +21,24 @@
         opacity: 0.8;
     }
 
+    #documentDecorations-topLeftResizer,
+    #documentDecorations-leftResizer,
+    #documentDecorations-bottomLeftResizer {
+        grid-column: 1
+    }
+
+    #documentDecorations-topResizer,
+    #documentDecorations-bottomResizer {
+        grid-column-start: 2;
+        grid-column-end: 4;
+    }
+
+    #documentDecorations-bottomRightResizer,
+    #documentDecorations-topRightResizer,
+    #documentDecorations-rightResizer {
+        grid-column:4
+    }
+
     #documentDecorations-topLeftResizer,
     #documentDecorations-bottomRightResizer {
         cursor: nwse-resize;
@@ -39,15 +60,19 @@
     }
     .title{
         background: lightblue;
-        grid-column-start:2;
-        grid-column-end: 4;
+        grid-column-start:3;
+        grid-column-end: 5;
         pointer-events: auto;
     }
 }
 
 .documentDecorations-minimizeButton {
-    background: rgb(250, 57, 9);
+    background:$alt-accent;
+    opacity: 0.8;
+    grid-column-start: 1;
+    grid-column-end: 3;
     pointer-events: all;
+    text-align: center;
 }
 .documentDecorations-background {
     background: lightblue;
@@ -87,7 +112,8 @@
 //     }
 // }
 .linkFlyout {
-    grid-column: 1/4
+    grid-column: 1/4;
+    margin-left: 25px;
 }
 
 .linkButton-empty:hover {
@@ -102,6 +128,31 @@
     cursor: pointer;
 }
 
+.linkButton-linker {
+    position:absolute;
+    bottom:0px;
+    left: 0px;
+    height: 20px;
+    width: 20px;
+    margin-top: 10px;
+    margin-right: 5px;
+    border-radius: 50%;
+    opacity: 0.9;
+    pointer-events: auto;
+    color: $dark-color;
+    border: $dark-color 1px solid;
+    text-transform: uppercase;
+    letter-spacing: 2px;
+    font-size: 75%;
+    transition: transform 0.2s;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.linkButton-tray {
+    grid-column: 1/4;
+}
 .linkButton-empty {
     height: 20px;
     width: 20px;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b74737ec9..a46087c9a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,10 +1,11 @@
-import { action, computed, observable } from "mobx";
+import { action, computed, observable, trace, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { Key } from "../../fields/Key";
 //import ContentEditable from 'react-contenteditable'
 import { KeyStore } from "../../fields/KeyStore";
 import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
+import { Document } from "../../fields/Document";
 import { TextField } from "../../fields/TextField";
 import { DragManager } from "../util/DragManager";
 import { SelectionManager } from "../util/SelectionManager";
@@ -13,6 +14,7 @@ import './DocumentDecorations.scss';
 import { DocumentView } from "./nodes/DocumentView";
 import { LinkMenu } from "./nodes/LinkMenu";
 import React = require("react");
+import { FieldWaiting } from "../../fields/Field";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -28,6 +30,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     private _linkBoxHeight = 30;
     private _titleHeight = 20;
     private _linkButton = React.createRef<HTMLDivElement>();
+    private _linkerButton = React.createRef<HTMLDivElement>();
     //@observable private _title: string = this._documents[0].props.Document.Title;
     @observable private _title: string = this._documents.length > 0 ? this._documents[0].props.Document.Title : "";
     @observable private _fieldKey: Key = KeyStore.Title;
@@ -174,18 +177,40 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }
     }
 
-    onLinkButtonDown = (e: React.PointerEvent): void => {
-        // if ()
-        // let linkMenu = new LinkMenu(SelectionManager.SelectedDocuments()[0]);
-        // linkMenu.Hidden = false;
-        console.log("down");
+    onLinkerButtonDown = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        document.removeEventListener("pointermove", this.onLinkerButtonMoved)
+        document.addEventListener("pointermove", this.onLinkerButtonMoved);
+        document.removeEventListener("pointerup", this.onLinkerButtonUp)
+        document.addEventListener("pointerup", this.onLinkerButtonUp);
+    }
+    onLinkerButtonUp = (e: PointerEvent): void => {
+        document.removeEventListener("pointermove", this.onLinkerButtonMoved)
+        document.removeEventListener("pointerup", this.onLinkerButtonUp)
+        e.stopPropagation();
+    }
 
+    onLinkerButtonMoved = (e: PointerEvent): void => {
+        if (this._linkerButton.current != null) {
+            document.removeEventListener("pointermove", this.onLinkerButtonMoved)
+            document.removeEventListener("pointerup", this.onLinkerButtonUp)
+            let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
+            DragManager.StartLinkDrag(this._linkerButton.current, dragData, {
+                handlers: {
+                    dragComplete: action(() => { }),
+                },
+                hideSource: false
+            })
+        }
+        e.stopPropagation();
+    }
+
+    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 => {
@@ -194,18 +219,32 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         e.stopPropagation();
     }
 
-
     onLinkButtonMoved = (e: PointerEvent): void => {
         if (this._linkButton.current != null) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved)
-            document.removeEventListener("pointerup", this.onLinkButtonUp)
-            let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
-            DragManager.StartLinkDrag(this._linkButton.current, dragData, {
-                handlers: {
-                    dragComplete: action(() => { }),
-                },
-                hideSource: false
-            })
+            document.removeEventListener("pointerup", this.onLinkButtonUp);
+
+            let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document;
+            let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
+            let draggedDocs = (srcTarg && srcTarg != FieldWaiting) ?
+                srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
+                    (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
+            let draggedFromDocs = (srcTarg && srcTarg != FieldWaiting) ?
+                srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
+                    (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
+            draggedDocs.push(...draggedFromDocs);
+            if (draggedDocs.length) {
+                let dragData = new DragManager.DocumentDragData(draggedDocs.map(d => {
+                    let annot = d.GetT(KeyStore.AnnotationOn, Document); // bcz: ... needs to change ... the annotationOn document may not have been retrieved yet...
+                    return annot && annot != FieldWaiting ? annot : d;
+                }));
+                DragManager.StartDocumentDrag([this._linkButton.current], dragData, {
+                    handlers: {
+                        dragComplete: action(() => { }),
+                    },
+                    hideSource: false
+                })
+            }
         }
         e.stopPropagation();
     }
@@ -298,7 +337,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     getValue = (): string => {
-        console.log("value watched");
         if (this._title === "changed" && this._documents.length > 0) {
             let field = this._documents[0].props.Document.Get(this._fieldKey);
             if (field instanceof TextField) {
@@ -338,8 +376,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             linkButton = (<Flyout
                 anchorPoint={anchorPoints.RIGHT_TOP}
                 content={
-                    <LinkMenu docView={selFirst} changeFlyout={this.changeFlyoutContent}>
-                    </LinkMenu>
+                    <LinkMenu docView={selFirst} changeFlyout={this.changeFlyoutContent} />
                 }>
                 <div className={"linkButton-" + (selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length ? "nonempty" : "empty")} onPointerDown={this.onLinkButtonDown} >{linkCount}</div>
             </Flyout>);
@@ -361,7 +398,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
                 opacity: this._opacity
             }}>
-                <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>v</div>
+                <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>...</div>
                 <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
@@ -373,8 +410,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
 
-                <div title="View Links" className="linkFlyout" ref={this._linkButton}>{linkButton}</div>
-
+                <div title="View Links" className="linkFlyout" ref={this._linkButton}> {linkButton}  </div>
+                <div className="linkButton-linker" ref={this._linkerButton} onPointerDown={this.onLinkerButtonDown}>∞</div>
             </div >
         </div>
         )
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index 35c8ee942..c5a2a50cb 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -2,6 +2,8 @@
 
 .inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect {
     position: absolute;
+    top: 0;
+    left:0;
     width: 8192px;
     height: 8192px;
     cursor:"crosshair";
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 698a9c617..594803aab 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -7,6 +7,9 @@ body {
     overflow: hidden;
     font-family: $sans-serif;
     margin: 0;
+    position:absolute;
+    top: 0;
+    left:0;
 }
 
 #dash-title {
@@ -158,11 +161,15 @@ button:hover {
     width:100%;
     height:100%;
     position:absolute;
+    top: 0;
+    left:0;
 }
 #mainContent-div {
     width:100%;
     height:100%;
     position:absolute;
+    top: 0;
+    left:0;
 }
 #add-options-content {
     display: table;
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 2706c3272..583d50c5b 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -3,7 +3,7 @@
 }
 
 .collectiondockingview-container {
-    position: relative;
+    position: absolute;
     top: 0;
     left: 0;
     overflow: hidden;
diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss
index 0144625c1..0eca3f1cd 100644
--- a/src/client/views/collections/CollectionPDFView.scss
+++ b/src/client/views/collections/CollectionPDFView.scss
@@ -9,6 +9,8 @@
     width: 100%;
     height: 100%;
     position: absolute; 
+    top: 0;
+    left:0;
     
 }
 .collectionPdfView-backward {
diff --git a/src/client/views/collections/CollectionVideoView.scss b/src/client/views/collections/CollectionVideoView.scss
index cbb981b13..ed56ad268 100644
--- a/src/client/views/collections/CollectionVideoView.scss
+++ b/src/client/views/collections/CollectionVideoView.scss
@@ -3,6 +3,8 @@
     width: 100%;
     height: 100%;
     position: absolute;
+    top: 0;
+    left:0;
  
 }
 .collectionVideoView-time{
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 2b0689800..daeca69e2 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -17,6 +17,8 @@ import { NumberField } from "../../../fields/NumberField";
 import request = require("request");
 import { ServerUtils } from "../../../server/ServerUtil";
 import { Server } from "../../Server";
+import { CollectionDockingView } from "./CollectionDockingView";
+import { runReactions } from "mobx/lib/internal";
 
 export interface CollectionViewProps {
     fieldKey: Key;
@@ -92,6 +94,24 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             e.stopPropagation();
             return added;
         }
+        if (de.data instanceof DragManager.LinkDragData) {
+            let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
+            if (sourceDoc) runInAction(() => {
+                let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
+                if (srcTarg && srcTarg != FieldWaiting) {
+                    let linkDocs = srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]);
+                    linkDocs.map(linkDoc => {
+                        let targDoc = linkDoc.GetT(KeyStore.LinkedToDocs, Document);
+                        if (targDoc && targDoc != FieldWaiting) {
+                            let dropdoc = targDoc.MakeDelegate();
+                            de.data.droppedDocuments.push(dropdoc);
+                            this.props.addDocument(dropdoc, false);
+                        }
+                    })
+                }
+            })
+            return true;
+        }
         return false;
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index e84f0c5ad..3dfd74ec8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -23,10 +23,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
         let l = this.props.LinkDocs;
         let a = this.props.A;
         let b = this.props.B;
-        let x1 = a.GetNumber(KeyStore.X, 0) + a.GetNumber(KeyStore.Width, 0) / 2;
-        let y1 = a.GetNumber(KeyStore.Y, 0) + a.GetNumber(KeyStore.Height, 0) / 2;
-        let x2 = b.GetNumber(KeyStore.X, 0) + b.GetNumber(KeyStore.Width, 0) / 2;
-        let y2 = b.GetNumber(KeyStore.Y, 0) + b.GetNumber(KeyStore.Height, 0) / 2;
+        let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.Minimized, false) ? 5 : a.GetNumber(KeyStore.Width, 0) / 2);
+        let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.Minimized, false) ? 5 : a.GetNumber(KeyStore.Height, 0) / 2);
+        let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.Minimized, false) ? 5 : b.GetNumber(KeyStore.Width, 0) / 2);
+        let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.Minimized, false) ? 5 : b.GetNumber(KeyStore.Height, 0) / 2);
         return (
             <line key={Utils.GenerateGuid()} className="collectionfreeformlinkview-linkLine" onPointerDown={this.onPointerDown}
                 style={{ strokeWidth: `${l.length * 5}` }}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss
index 4341c82f7..30e158603 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss
@@ -1,6 +1,8 @@
 .collectionfreeformlinksview-svgCanvas{
     transform: translate(-10000px,-10000px);
     position: absolute;
+    top: 0;
+    left: 0;
     width: 20000px; 
     height: 20000px;
     pointer-events: none;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 81d21d89a..79d520069 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -26,7 +26,7 @@
   border: 0px solid $light-color-secondary;
   border-radius: $border-radius;
   box-sizing: border-box;
-  position: relative;
+  position: absolute;
   overflow: hidden;
   top: 0;
   left: 0;
@@ -41,12 +41,12 @@
   .formattedTextBox-cont {
     background: $light-color-secondary;
   }
-
+ 
   opacity: 0.99;
   border: 0px solid transparent;
   border-radius: $border-radius;
   box-sizing: border-box;
-  position:relative;
+  position:absolute;
   overflow: hidden;
   top: 0;
   left: 0;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c5178f69d..3484e963e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -73,14 +73,17 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (super.drop(e, de)) {
-            if (de.data instanceof DragManager.DocumentDragData) {
-                let screenX = de.x - (de.data.xOffset as number || 0);
-                let screenY = de.y - (de.data.yOffset as number || 0);
+            let droppedDocs = de.data.droppedDocuments as Document[];
+            let xoff = de.data.xOffset as number || 0;
+            let yoff = de.data.yOffset as number || 0;
+            if (droppedDocs && droppedDocs.length) {
+                let screenX = de.x - xoff;
+                let screenY = de.y - yoff;
                 const [x, y] = this.getTransform().transformPoint(screenX, screenY);
-                let dragDoc = de.data.draggedDocuments[0];
+                let dragDoc = de.data.droppedDocuments[0];
                 let dragX = dragDoc.GetNumber(KeyStore.X, 0);
                 let dragY = dragDoc.GetNumber(KeyStore.Y, 0);
-                de.data.draggedDocuments.map(d => {
+                droppedDocs.map(d => {
                     let docX = d.GetNumber(KeyStore.X, 0);
                     let docY = d.GetNumber(KeyStore.Y, 0);
                     d.SetNumber(KeyStore.X, x + (docX - dragX));
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
index 1ee3b244b..0b406e722 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
@@ -1,6 +1,8 @@
 
 .marqueeView {
     position: absolute;
+    top:0;
+    left:0;
     width:100%;
     height:100%;
 }
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss
index 21210be2b..7a67c29bf 100644
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss
+++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss
@@ -3,9 +3,13 @@
     color: black;
     position: absolute;
     transform-origin: left top;
+    top: 0;
+    left:0;
     pointer-events: none;
 }
 .previewCursorView {
+    top: 0;
+    left:0;
     position: absolute;
     width:100%;
     height:100%;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index d52b662bd..1a0f0cbbd 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -66,8 +66,12 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
         return <DocumentView {...this.props}
             ContentScaling={this.contentScaling}
             ScreenToLocalTransform={this.getTransform}
+            PanelWidth={this.panelWidth}
+            PanelHeight={this.panelHeight}
         />
     }
+    panelWidth = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelWidth();
+    panelHeight = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelHeight();
 
     render() {
         return (
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 127a6b535..5126e69f9 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -2,6 +2,8 @@
 
 .documentView-node {
   position: absolute;
+  top: 0;
+  left:0;
   background: $light-color; //overflow: hidden;
 
   &.minimized {
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index ad947afd5..830dfe6c6 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -1,12 +1,16 @@
 .react-pdf__Page {
     transform-origin: left top;
     position: absolute;
+    top: 0;
+    left:0;
 }
 .react-pdf__Document {
     position: absolute;
 }
 .pdfBox-buttonTray {
     position:absolute;
+    top: 0;
+    left:0;
     z-index: 25;
 }
 .pdfBox-contentContainer {
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index a535b2638..c73bc0c47 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -2,6 +2,8 @@
 .webBox-cont {
     padding: 0vw;
     position: absolute;
+    top: 0;
+    left:0;
     width: 100%;
     height: 100%;
     overflow: scroll;
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 8e71019a4..92d03d765 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -9,415 +9,420 @@ import { Server } from "../client/Server";
 import { Types } from "../server/Message";
 import { UndoManager } from "../client/util/UndoManager";
 import { HtmlField } from "./HtmlField";
+import { BooleanField } from "./BooleanField";
 
 export class Document extends Field {
-  //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field
-  public fields: ObservableMap<
-    string,
-    { key: Key; field: Field }
-  > = new ObservableMap();
-  public _proxies: ObservableMap<string, FieldId> = new ObservableMap();
-
-  constructor(id?: string, save: boolean = true) {
-    super(id);
-
-    if (save) {
-      Server.UpdateField(this);
+    //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field
+    public fields: ObservableMap<
+        string,
+        { key: Key; field: Field }
+    > = new ObservableMap();
+    public _proxies: ObservableMap<string, FieldId> = new ObservableMap();
+
+    constructor(id?: string, save: boolean = true) {
+        super(id);
+
+        if (save) {
+            Server.UpdateField(this);
+        }
     }
-  }
 
-  UpdateFromServer(data: [string, string][]) {
-    for (const key in data) {
-      const element = data[key];
-      this._proxies.set(element[0], element[1]);
-    }
-  }
-
-  public Width = () => {
-    return this.GetNumber(KeyStore.Width, 0);
-  };
-  public Height = () => {
-    return this.GetNumber(
-      KeyStore.Height,
-      this.GetNumber(KeyStore.NativeWidth, 0)
-        ? (this.GetNumber(KeyStore.NativeHeight, 0) /
-            this.GetNumber(KeyStore.NativeWidth, 0)) *
-            this.GetNumber(KeyStore.Width, 0)
-        : 0
-    );
-  };
-  public Scale = () => {
-    return this.GetNumber(KeyStore.Scale, 1);
-  };
-
-  @computed
-  public get Title(): string {
-    let title = this.Get(KeyStore.Title, true);
-    if (title)
-      if (title != FieldWaiting && title instanceof TextField)
-        return title.Data;
-      else return "-waiting-";
-    let parTitle = this.GetT(KeyStore.Title, TextField);
-    if (parTitle)
-      if (parTitle != FieldWaiting) return parTitle.Data + ".alias";
-      else return "-waiting-.alias";
-    return "-untitled-";
-  }
-
-  @computed
-  public get Fields() {
-    return this.fields;
-  }
-
-  /**
-   * Get the field in the document associated with the given key. If the
-   * associated field has not yet been filled in from the server, a request
-   * to the server will automatically be sent, the value will be filled in
-   * when the request is completed, and {@link Field.ts#FieldWaiting} will be returned.
-   * @param key - The key of the value to get
-   * @param ignoreProto - If true, ignore any prototype this document
-   * might have and only search for the value on this immediate document.
-   * If false (default), search up the prototype chain, starting at this document,
-   * for a document that has a field associated with the given key, and return the first
-   * one found.
-   *
-   * @returns If the document does not have a field associated with the given key, returns `undefined`.
-   * If the document does have an associated field, but the field has not been fetched from the server, returns {@link Field.ts#FieldWaiting}.
-   * If the document does have an associated field, and the field has not been fetched from the server, returns the associated field.
-   */
-  Get(key: Key, ignoreProto: boolean = false): FieldValue<Field> {
-    let field: FieldValue<Field>;
-    if (ignoreProto) {
-      if (this.fields.has(key.Id)) {
-        field = this.fields.get(key.Id)!.field;
-      } else if (this._proxies.has(key.Id)) {
-        Server.GetDocumentField(this, key);
-        /*
-                The field might have been instantly filled from the cache
-                Maybe we want to just switch back to returning the value
-                from Server.GetDocumentField if it's in the cache
-                */
-        if (this.fields.has(key.Id)) {
-          field = this.fields.get(key.Id)!.field;
-        } else {
-          field = FieldWaiting;
+    UpdateFromServer(data: [string, string][]) {
+        for (const key in data) {
+            const element = data[key];
+            this._proxies.set(element[0], element[1]);
         }
-      }
-    } else {
-      let doc: FieldValue<Document> = this;
-      while (doc && doc != FieldWaiting && field != FieldWaiting) {
-        let curField = doc.fields.get(key.Id);
-        let curProxy = doc._proxies.get(key.Id);
-        if (!curField || (curProxy && curField.field.Id !== curProxy)) {
-          if (curProxy) {
-            Server.GetDocumentField(doc, key);
-            /*
+    }
+
+    public Width = () => {
+        return this.GetNumber(KeyStore.Width, 0);
+    };
+    public Height = () => {
+        return this.GetNumber(
+            KeyStore.Height,
+            this.GetNumber(KeyStore.NativeWidth, 0)
+                ? (this.GetNumber(KeyStore.NativeHeight, 0) /
+                    this.GetNumber(KeyStore.NativeWidth, 0)) *
+                this.GetNumber(KeyStore.Width, 0)
+                : 0
+        );
+    };
+    public Scale = () => {
+        return this.GetNumber(KeyStore.Scale, 1);
+    };
+
+    @computed
+    public get Title(): string {
+        let title = this.Get(KeyStore.Title, true);
+        if (title)
+            if (title != FieldWaiting && title instanceof TextField)
+                return title.Data;
+            else return "-waiting-";
+        let parTitle = this.GetT(KeyStore.Title, TextField);
+        if (parTitle)
+            if (parTitle != FieldWaiting) return parTitle.Data + ".alias";
+            else return "-waiting-.alias";
+        return "-untitled-";
+    }
+
+    @computed
+    public get Fields() {
+        return this.fields;
+    }
+
+    /**
+     * Get the field in the document associated with the given key. If the
+     * associated field has not yet been filled in from the server, a request
+     * to the server will automatically be sent, the value will be filled in
+     * when the request is completed, and {@link Field.ts#FieldWaiting} will be returned.
+     * @param key - The key of the value to get
+     * @param ignoreProto - If true, ignore any prototype this document
+     * might have and only search for the value on this immediate document.
+     * If false (default), search up the prototype chain, starting at this document,
+     * for a document that has a field associated with the given key, and return the first
+     * one found.
+     *
+     * @returns If the document does not have a field associated with the given key, returns `undefined`.
+     * If the document does have an associated field, but the field has not been fetched from the server, returns {@link Field.ts#FieldWaiting}.
+     * If the document does have an associated field, and the field has not been fetched from the server, returns the associated field.
+     */
+    Get(key: Key, ignoreProto: boolean = false): FieldValue<Field> {
+        let field: FieldValue<Field>;
+        if (ignoreProto) {
+            if (this.fields.has(key.Id)) {
+                field = this.fields.get(key.Id)!.field;
+            } else if (this._proxies.has(key.Id)) {
+                Server.GetDocumentField(this, key);
+                /*
                         The field might have been instantly filled from the cache
                         Maybe we want to just switch back to returning the value
                         from Server.GetDocumentField if it's in the cache
                         */
-            if (this.fields.has(key.Id)) {
-              field = this.fields.get(key.Id)!.field;
-            } else {
-              field = FieldWaiting;
+                if (this.fields.has(key.Id)) {
+                    field = this.fields.get(key.Id)!.field;
+                } else {
+                    field = FieldWaiting;
+                }
             }
-            break;
-          }
-          if (
-            doc.fields.has(KeyStore.Prototype.Id) ||
-            doc._proxies.has(KeyStore.Prototype.Id)
-          ) {
-            doc = doc.GetPrototype();
-          } else {
-            break;
-          }
         } else {
-          field = curField.field;
-          break;
+            let doc: FieldValue<Document> = this;
+            while (doc && doc != FieldWaiting && field != FieldWaiting) {
+                let curField = doc.fields.get(key.Id);
+                let curProxy = doc._proxies.get(key.Id);
+                if (!curField || (curProxy && curField.field.Id !== curProxy)) {
+                    if (curProxy) {
+                        Server.GetDocumentField(doc, key);
+                        /*
+                                    The field might have been instantly filled from the cache
+                                    Maybe we want to just switch back to returning the value
+                                    from Server.GetDocumentField if it's in the cache
+                                    */
+                        if (this.fields.has(key.Id)) {
+                            field = this.fields.get(key.Id)!.field;
+                        } else {
+                            field = FieldWaiting;
+                        }
+                        break;
+                    }
+                    if (
+                        doc.fields.has(KeyStore.Prototype.Id) ||
+                        doc._proxies.has(KeyStore.Prototype.Id)
+                    ) {
+                        doc = doc.GetPrototype();
+                    } else {
+                        break;
+                    }
+                } else {
+                    field = curField.field;
+                    break;
+                }
+            }
+            if (doc == FieldWaiting) field = FieldWaiting;
         }
-      }
-      if (doc == FieldWaiting) field = FieldWaiting;
+
+        return field;
     }
 
-    return field;
-  }
-
-  /**
-   * Tries to get the field associated with the given key, and if there is an
-   * associated field, calls the given callback with that field.
-   * @param key - The key of the value to get
-   * @param callback - A function that will be called with the associated field, if it exists,
-   * once it is fetched from the server (this may be immediately if the field has already been fetched).
-   * Note: The callback will not be called if there is no associated field.
-   * @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise
-   */
-  GetAsync(key: Key, callback: (field: Opt<Field>) => void): void {
-    //TODO: This currently doesn't deal with prototypes
-    let field = this.fields.get(key.Id);
-    if (field && field.field) {
-      callback(field.field);
-    } else if (this._proxies.has(key.Id)) {
-      Server.GetDocumentField(this, key, callback);
-    } else if (this._proxies.has(KeyStore.Prototype.Id)) {
-      this.GetTAsync(KeyStore.Prototype, Document, proto => {
-        if (proto) {
-          proto.GetAsync(key, callback);
+    /**
+     * Tries to get the field associated with the given key, and if there is an
+     * associated field, calls the given callback with that field.
+     * @param key - The key of the value to get
+     * @param callback - A function that will be called with the associated field, if it exists,
+     * once it is fetched from the server (this may be immediately if the field has already been fetched).
+     * Note: The callback will not be called if there is no associated field.
+     * @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise
+     */
+    GetAsync(key: Key, callback: (field: Opt<Field>) => void): void {
+        //TODO: This currently doesn't deal with prototypes
+        let field = this.fields.get(key.Id);
+        if (field && field.field) {
+            callback(field.field);
+        } else if (this._proxies.has(key.Id)) {
+            Server.GetDocumentField(this, key, callback);
+        } else if (this._proxies.has(KeyStore.Prototype.Id)) {
+            this.GetTAsync(KeyStore.Prototype, Document, proto => {
+                if (proto) {
+                    proto.GetAsync(key, callback);
+                } else {
+                    callback(undefined);
+                }
+            });
         } else {
-          callback(undefined);
+            callback(undefined);
         }
-      });
-    } else {
-      callback(undefined);
     }
-  }
-
-  GetTAsync<T extends Field>(key: Key, ctor: { new (): T }): Promise<Opt<T>>;
-  GetTAsync<T extends Field>(
-    key: Key,
-    ctor: { new (): T },
-    callback: (field: Opt<T>) => void
-  ): void;
-  GetTAsync<T extends Field>(
-    key: Key,
-    ctor: { new (): T },
-    callback?: (field: Opt<T>) => void
-  ): Promise<Opt<T>> | void {
-    let fn = (cb: (field: Opt<T>) => void) => {
-      return this.GetAsync(key, field => {
-        cb(Cast(field, ctor));
-      });
-    };
-    if (callback) {
-      fn(callback);
-    } else {
-      return new Promise(res => fn(res));
+
+    GetTAsync<T extends Field>(key: Key, ctor: { new(): T }): Promise<Opt<T>>;
+    GetTAsync<T extends Field>(
+        key: Key,
+        ctor: { new(): T },
+        callback: (field: Opt<T>) => void
+    ): void;
+    GetTAsync<T extends Field>(
+        key: Key,
+        ctor: { new(): T },
+        callback?: (field: Opt<T>) => void
+    ): Promise<Opt<T>> | void {
+        let fn = (cb: (field: Opt<T>) => void) => {
+            return this.GetAsync(key, field => {
+                cb(Cast(field, ctor));
+            });
+        };
+        if (callback) {
+            fn(callback);
+        } else {
+            return new Promise(res => fn(res));
+        }
     }
-  }
-
-  /**
-   * Same as {@link Document#GetAsync}, except a field of the given type
-   * will be created if there is no field associated with the given key,
-   * or the field associated with the given key is not of the given type.
-   * @param ctor - Constructor of the field type to get. E.g., TextField, ImageField, etc.
-   */
-  GetOrCreateAsync<T extends Field>(
-    key: Key,
-    ctor: { new (): T },
-    callback: (field: T) => void
-  ): void {
-    //This currently doesn't deal with prototypes
-    if (this._proxies.has(key.Id)) {
-      Server.GetDocumentField(this, key, field => {
-        if (field && field instanceof ctor) {
-          callback(field);
+
+    /**
+     * Same as {@link Document#GetAsync}, except a field of the given type
+     * will be created if there is no field associated with the given key,
+     * or the field associated with the given key is not of the given type.
+     * @param ctor - Constructor of the field type to get. E.g., TextField, ImageField, etc.
+     */
+    GetOrCreateAsync<T extends Field>(
+        key: Key,
+        ctor: { new(): T },
+        callback: (field: T) => void
+    ): void {
+        //This currently doesn't deal with prototypes
+        if (this._proxies.has(key.Id)) {
+            Server.GetDocumentField(this, key, field => {
+                if (field && field instanceof ctor) {
+                    callback(field);
+                } else {
+                    let newField = new ctor();
+                    this.Set(key, newField);
+                    callback(newField);
+                }
+            });
         } else {
-          let newField = new ctor();
-          this.Set(key, newField);
-          callback(newField);
+            let newField = new ctor();
+            this.Set(key, newField);
+            callback(newField);
         }
-      });
-    } else {
-      let newField = new ctor();
-      this.Set(key, newField);
-      callback(newField);
     }
-  }
-
-  /**
-   * Same as {@link Document#Get}, except that it will additionally
-   * check if the field is of the given type.
-   * @param ctor - Constructor of the field type to get. E.g., `TextField`, `ImageField`, etc.
-   * @returns Same as {@link Document#Get}, except will return `undefined`
-   * if there is an associated field but it is of the wrong type.
-   */
-  GetT<T extends Field = Field>(
-    key: Key,
-    ctor: { new (...args: any[]): T },
-    ignoreProto: boolean = false
-  ): FieldValue<T> {
-    var getfield = this.Get(key, ignoreProto);
-    if (getfield != FieldWaiting) {
-      return Cast(getfield, ctor);
+
+    /**
+     * Same as {@link Document#Get}, except that it will additionally
+     * check if the field is of the given type.
+     * @param ctor - Constructor of the field type to get. E.g., `TextField`, `ImageField`, etc.
+     * @returns Same as {@link Document#Get}, except will return `undefined`
+     * if there is an associated field but it is of the wrong type.
+     */
+    GetT<T extends Field = Field>(
+        key: Key,
+        ctor: { new(...args: any[]): T },
+        ignoreProto: boolean = false
+    ): FieldValue<T> {
+        var getfield = this.Get(key, ignoreProto);
+        if (getfield != FieldWaiting) {
+            return Cast(getfield, ctor);
+        }
+        return FieldWaiting;
     }
-    return FieldWaiting;
-  }
-
-  GetOrCreate<T extends Field>(
-    key: Key,
-    ctor: { new (): T },
-    ignoreProto: boolean = false
-  ): T {
-    const field = this.GetT(key, ctor, ignoreProto);
-    if (field && field != FieldWaiting) {
-      return field;
+
+    GetOrCreate<T extends Field>(
+        key: Key,
+        ctor: { new(): T },
+        ignoreProto: boolean = false
+    ): T {
+        const field = this.GetT(key, ctor, ignoreProto);
+        if (field && field != FieldWaiting) {
+            return field;
+        }
+        const newField = new ctor();
+        this.Set(key, newField);
+        return newField;
     }
-    const newField = new ctor();
-    this.Set(key, newField);
-    return newField;
-  }
-
-  GetData<T, U extends Field & { Data: T }>(
-    key: Key,
-    ctor: { new (): U },
-    defaultVal: T
-  ): T {
-    let val = this.Get(key);
-    let vval = val && val instanceof ctor ? val.Data : defaultVal;
-    return vval;
-  }
-
-  GetHtml(key: Key, defaultVal: string): string {
-    return this.GetData(key, HtmlField, defaultVal);
-  }
-
-  GetNumber(key: Key, defaultVal: number): number {
-    return this.GetData(key, NumberField, defaultVal);
-  }
-
-  GetText(key: Key, defaultVal: string): string {
-    return this.GetData(key, TextField, defaultVal);
-  }
-
-  GetList<T extends Field>(key: Key, defaultVal: T[]): T[] {
-    return this.GetData<T[], ListField<T>>(key, ListField, defaultVal);
-  }
-
-  @action
-  Set(key: Key, field: Field | undefined, setOnPrototype = false): void {
-    let old = this.fields.get(key.Id);
-    let oldField = old ? old.field : undefined;
-    if (setOnPrototype) {
-      this.SetOnPrototype(key, field);
-    } else {
-      if (field) {
-        this.fields.set(key.Id, { key, field });
-        this._proxies.set(key.Id, field.Id);
-        // Server.AddDocumentField(this, key, field);
-      } else {
-        this.fields.delete(key.Id);
-        this._proxies.delete(key.Id);
-        // Server.DeleteDocumentField(this, key);
-      }
-      Server.UpdateField(this);
+
+    GetData<T, U extends Field & { Data: T }>(
+        key: Key,
+        ctor: { new(): U },
+        defaultVal: T
+    ): T {
+        let val = this.Get(key);
+        let vval = val && val instanceof ctor ? val.Data : defaultVal;
+        return vval;
     }
-    if (oldField || field) {
-      UndoManager.AddEvent({
-        undo: () => this.Set(key, oldField, setOnPrototype),
-        redo: () => this.Set(key, field, setOnPrototype)
-      });
+
+    GetHtml(key: Key, defaultVal: string): string {
+        return this.GetData(key, HtmlField, defaultVal);
     }
-  }
-
-  @action
-  SetOnPrototype(key: Key, field: Field | undefined): void {
-    this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
-      f && f.Set(key, field);
-    });
-  }
-
-  @action
-  SetDataOnPrototype<T, U extends Field & { Data: T }>(
-    key: Key,
-    value: T,
-    ctor: { new (): U },
-    replaceWrongType = true
-  ) {
-    this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
-      f && f.SetData(key, value, ctor);
-    });
-  }
-
-  @action
-  SetData<T, U extends Field & { Data: T }>(
-    key: Key,
-    value: T,
-    ctor: { new (data: T): U },
-    replaceWrongType = true
-  ) {
-    let field = this.Get(key, true);
-    if (field instanceof ctor) {
-      field.Data = value;
-    } else if (!field || replaceWrongType) {
-      let newField = new ctor(value);
-      // newField.Data = value;
-      this.Set(key, newField);
+
+    GetBoolean(key: Key, defaultVal: boolean): boolean {
+        return this.GetData(key, BooleanField, defaultVal);
     }
-  }
-
-  @action
-  SetText(key: Key, value: string, replaceWrongType = true) {
-    this.SetData(key, value, TextField, replaceWrongType);
-  }
-
-  @action
-  SetNumber(key: Key, value: number, replaceWrongType = true) {
-    this.SetData(key, value, NumberField, replaceWrongType);
-  }
-
-  GetPrototype(): FieldValue<Document> {
-    return this.GetT(KeyStore.Prototype, Document, true);
-  }
-
-  GetAllPrototypes(): Document[] {
-    let protos: Document[] = [];
-    let doc: FieldValue<Document> = this;
-    while (doc && doc != FieldWaiting) {
-      protos.push(doc);
-      doc = doc.GetPrototype();
+
+    GetNumber(key: Key, defaultVal: number): number {
+        return this.GetData(key, NumberField, defaultVal);
+    }
+
+    GetText(key: Key, defaultVal: string): string {
+        return this.GetData(key, TextField, defaultVal);
+    }
+
+    GetList<T extends Field>(key: Key, defaultVal: T[]): T[] {
+        return this.GetData<T[], ListField<T>>(key, ListField, defaultVal);
+    }
+
+    @action
+    Set(key: Key, field: Field | undefined, setOnPrototype = false): void {
+        let old = this.fields.get(key.Id);
+        let oldField = old ? old.field : undefined;
+        if (setOnPrototype) {
+            this.SetOnPrototype(key, field);
+        } else {
+            if (field) {
+                this.fields.set(key.Id, { key, field });
+                this._proxies.set(key.Id, field.Id);
+                // Server.AddDocumentField(this, key, field);
+            } else {
+                this.fields.delete(key.Id);
+                this._proxies.delete(key.Id);
+                // Server.DeleteDocumentField(this, key);
+            }
+            Server.UpdateField(this);
+        }
+        if (oldField || field) {
+            UndoManager.AddEvent({
+                undo: () => this.Set(key, oldField, setOnPrototype),
+                redo: () => this.Set(key, field, setOnPrototype)
+            });
+        }
+    }
+
+    @action
+    SetOnPrototype(key: Key, field: Field | undefined): void {
+        this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+            f && f.Set(key, field);
+        });
+    }
+
+    @action
+    SetDataOnPrototype<T, U extends Field & { Data: T }>(
+        key: Key,
+        value: T,
+        ctor: { new(): U },
+        replaceWrongType = true
+    ) {
+        this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+            f && f.SetData(key, value, ctor);
+        });
+    }
+
+    @action
+    SetData<T, U extends Field & { Data: T }>(
+        key: Key,
+        value: T,
+        ctor: { new(data: T): U },
+        replaceWrongType = true
+    ) {
+        let field = this.Get(key, true);
+        if (field instanceof ctor) {
+            field.Data = value;
+        } else if (!field || replaceWrongType) {
+            let newField = new ctor(value);
+            // newField.Data = value;
+            this.Set(key, newField);
+        }
+    }
+
+    @action
+    SetText(key: Key, value: string, replaceWrongType = true) {
+        this.SetData(key, value, TextField, replaceWrongType);
+    }
+
+    @action
+    SetNumber(key: Key, value: number, replaceWrongType = true) {
+        this.SetData(key, value, NumberField, replaceWrongType);
+    }
+
+    GetPrototype(): FieldValue<Document> {
+        return this.GetT(KeyStore.Prototype, Document, true);
+    }
+
+    GetAllPrototypes(): Document[] {
+        let protos: Document[] = [];
+        let doc: FieldValue<Document> = this;
+        while (doc && doc != FieldWaiting) {
+            protos.push(doc);
+            doc = doc.GetPrototype();
+        }
+        return protos;
+    }
+
+    CreateAlias(id?: string): Document {
+        let alias = new Document(id);
+        this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+            f && alias.Set(KeyStore.Prototype, f);
+        });
+
+        return alias;
+    }
+
+    MakeDelegate(id?: string): Document {
+        let delegate = new Document(id);
+
+        delegate.Set(KeyStore.Prototype, this);
+
+        return delegate;
+    }
+
+    ToScriptString(): string {
+        return "";
+    }
+
+    TrySetValue(value: any): boolean {
+        throw new Error("Method not implemented.");
+    }
+    GetValue() {
+        return this.Title;
+        var title =
+            (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) +
+            "(" +
+            this.Id +
+            ")";
+        return title;
+        //throw new Error("Method not implemented.");
+    }
+    Copy(): Field {
+        throw new Error("Method not implemented.");
+    }
+
+    ToJson(): { type: Types; data: [string, string][]; _id: string } {
+        let fields: [string, string][] = [];
+        this._proxies.forEach((field, key) => {
+            if (field) {
+                fields.push([key, field as string]);
+            }
+        });
+
+        return {
+            type: Types.Document,
+            data: fields,
+            _id: this.Id
+        };
     }
-    return protos;
-  }
-
-  CreateAlias(id?: string): Document {
-    let alias = new Document(id);
-    this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
-      f && alias.Set(KeyStore.Prototype, f);
-    });
-
-    return alias;
-  }
-
-  MakeDelegate(id?: string): Document {
-    let delegate = new Document(id);
-
-    delegate.Set(KeyStore.Prototype, this);
-
-    return delegate;
-  }
-
-  ToScriptString(): string {
-    return "";
-  }
-
-  TrySetValue(value: any): boolean {
-    throw new Error("Method not implemented.");
-  }
-  GetValue() {
-    return this.Title;
-    var title =
-      (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) +
-      "(" +
-      this.Id +
-      ")";
-    return title;
-    //throw new Error("Method not implemented.");
-  }
-  Copy(): Field {
-    throw new Error("Method not implemented.");
-  }
-
-  ToJson(): { type: Types; data: [string, string][]; _id: string } {
-    let fields: [string, string][] = [];
-    this._proxies.forEach((field, key) => {
-      if (field) {
-        fields.push([key, field as string]);
-      }
-    });
-
-    return {
-      type: Types.Document,
-      data: fields,
-      _id: this.Id
-    };
-  }
 }
-- 
cgit v1.2.3-70-g09d2


From e70be930dc7c8ff1e999bf163bcbb511a60bae6f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 4 Apr 2019 17:46:33 -0400
Subject: added close button and fixed some async stuff.

---
 src/client/views/DocumentDecorations.scss          | 17 +++++++---
 src/client/views/DocumentDecorations.tsx           | 38 +++++++++++++++++++---
 .../views/collections/CollectionViewBase.tsx       |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  9 +++--
 .../collections/collectionFreeForm/MarqueeView.tsx |  1 +
 src/client/views/nodes/PDFBox.tsx                  | 10 +++---
 6 files changed, 60 insertions(+), 17 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 080c9fa1e..d7137d7a2 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -7,7 +7,7 @@
     display: grid;
     z-index: 1000;
     grid-template-rows: 20px 8px 1fr 8px;
-    grid-template-columns: 8px 8px 1fr 8px;
+    grid-template-columns: 8px 8px 1fr 8px 8px;
     pointer-events: none;
 
     #documentDecorations-centerCont {
@@ -30,13 +30,14 @@
     #documentDecorations-topResizer,
     #documentDecorations-bottomResizer {
         grid-column-start: 2;
-        grid-column-end: 4;
+        grid-column-end: 5;
     }
 
     #documentDecorations-bottomRightResizer,
     #documentDecorations-topRightResizer,
     #documentDecorations-rightResizer {
-        grid-column:4
+        grid-column-start:5;
+        grid-column-end:7;
     }
 
     #documentDecorations-topLeftResizer,
@@ -61,11 +62,19 @@
     .title{
         background: lightblue;
         grid-column-start:3;
-        grid-column-end: 5;
+        grid-column-end: 4;
         pointer-events: auto;
     }
 }
 
+.documentDecorations-closeButton {
+    background:$alt-accent;
+    opacity: 0.8;
+    grid-column-start: 4;
+    grid-column-end: 6;
+    pointer-events: all;
+    text-align: center;
+}
 .documentDecorations-minimizeButton {
     background:$alt-accent;
     opacity: 0.8;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index a46087c9a..8bf1a42d1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -142,6 +142,30 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         e.preventDefault();
     }
 
+    onCloseDown = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+            document.removeEventListener("pointermove", this.onCloseMove);
+            document.addEventListener("pointermove", this.onCloseMove);
+            document.removeEventListener("pointerup", this.onCloseUp);
+            document.addEventListener("pointerup", this.onCloseUp);
+        }
+    }
+    onCloseMove = (e: PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+        }
+    }
+    @action
+    onCloseUp = (e: PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+            SelectionManager.SelectedDocuments().map(dv => dv.props.RemoveDocument && dv.props.RemoveDocument(dv.props.Document));
+            SelectionManager.DeselectAll();
+            document.removeEventListener("pointermove", this.onCloseMove);
+            document.removeEventListener("pointerup", this.onCloseUp);
+        }
+    }
     onMinimizeDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
         if (e.button === 0) {
@@ -219,7 +243,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         e.stopPropagation();
     }
 
-    onLinkButtonMoved = (e: PointerEvent): void => {
+    onLinkButtonMoved = async (e: PointerEvent) => {
         if (this._linkButton.current != null) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved)
             document.removeEventListener("pointerup", this.onLinkButtonUp);
@@ -234,10 +258,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
             draggedDocs.push(...draggedFromDocs);
             if (draggedDocs.length) {
-                let dragData = new DragManager.DocumentDragData(draggedDocs.map(d => {
-                    let annot = d.GetT(KeyStore.AnnotationOn, Document); // bcz: ... needs to change ... the annotationOn document may not have been retrieved yet...
-                    return annot && annot != FieldWaiting ? annot : d;
-                }));
+                let moddrag = [] as Document[];
+                for (let i = 0; i < draggedDocs.length; i++) {
+                    let doc = await draggedDocs[i].GetTAsync(KeyStore.AnnotationOn, Document);
+                    if (doc)
+                        moddrag.push(doc);
+                }
+                let dragData = new DragManager.DocumentDragData(moddrag);
                 DragManager.StartDocumentDrag([this._linkButton.current], dragData, {
                     handlers: {
                         dragComplete: action(() => { }),
@@ -400,6 +427,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             }}>
                 <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>...</div>
                 <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
+                <div className="documentDecorations-closeButton" onPointerDown={this.onCloseDown}>X</div>
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index daeca69e2..9eee23a1d 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -128,6 +128,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         }
         if (type.indexOf("pdf") !== -1) {
             ctor = Documents.PdfDocument;
+            options.nativeWidth = 600;
         }
         if (type.indexOf("html") !== -1) {
             if (path.includes('localhost')) {
@@ -177,7 +178,6 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             let item = e.dataTransfer.items[i];
             if (item.kind === "string" && item.type.indexOf("uri") != -1) {
                 e.dataTransfer.items[i].getAsString(action((s: string) => {
-                    let document: Document;
                     request.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s), (err, res, body) => {
                         let type = res.headers["content-type"];
                         if (type) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3484e963e..1ddb84a99 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -20,6 +20,7 @@ import React = require("react");
 import v5 = require("uuid/v5");
 import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
 import { PreviewCursor } from "./PreviewCursor";
+import { NumberField } from "../../../../fields/NumberField";
 
 @observer
 export class CollectionFreeFormView extends CollectionViewBase {
@@ -83,13 +84,17 @@ export class CollectionFreeFormView extends CollectionViewBase {
                 let dragDoc = de.data.droppedDocuments[0];
                 let dragX = dragDoc.GetNumber(KeyStore.X, 0);
                 let dragY = dragDoc.GetNumber(KeyStore.Y, 0);
-                droppedDocs.map(d => {
+                droppedDocs.map(async d => {
                     let docX = d.GetNumber(KeyStore.X, 0);
                     let docY = d.GetNumber(KeyStore.Y, 0);
                     d.SetNumber(KeyStore.X, x + (docX - dragX));
                     d.SetNumber(KeyStore.Y, y + (docY - dragY));
-                    if (!d.GetNumber(KeyStore.Width, 0)) {
+                    let docW = await d.GetTAsync(KeyStore.Width, NumberField);
+                    let docH = await d.GetTAsync(KeyStore.Height, NumberField);
+                    if (!docW) {
                         d.SetNumber(KeyStore.Width, 300);
+                    }
+                    if (!docH) {
                         d.SetNumber(KeyStore.Height, 300);
                     }
                     this.bringToFront(d);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index e2239c8be..df150a045 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -135,6 +135,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             this.marqueeInkDelete(inkData);
             // }, 100);
             this.cleanupInteractions();
+            SelectionManager.DeselectAll();
         }
     }
     @action
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3cb3cf782..c9fed7f66 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,5 +1,5 @@
 import * as htmlToImage from "html-to-image";
-import { action, computed, observable, reaction, IReactionDisposer, trace, keys } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from "mobx-react";
 import 'react-image-lightbox/style.css';
 import Measure from "react-measure";
@@ -10,6 +10,7 @@ import { FieldWaiting, Opt } from '../../../fields/Field';
 import { ImageField } from '../../../fields/ImageField';
 import { KeyStore } from '../../../fields/KeyStore';
 import { PDFField } from '../../../fields/PDFField';
+import { RouteStore } from "../../../server/RouteStore";
 import { Utils } from '../../../Utils';
 import { Annotation } from './Annotation';
 import { FieldView, FieldViewProps } from './FieldView';
@@ -17,8 +18,6 @@ import "./ImageBox.scss";
 import "./PDFBox.scss";
 import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here
 import React = require("react")
-import { RouteStore } from "../../../server/RouteStore";
-import { NumberField } from "../../../fields/NumberField";
 
 /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
  * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, 
@@ -378,8 +377,9 @@ export class PDFBox extends React.Component<FieldViewProps> {
     saveThumbnail = () => {
         setTimeout(() => {
             var me = this;
-            htmlToImage.toPng(this._mainDiv.current!,
-                { width: me.props.doc.GetNumber(KeyStore.NativeWidth, 0), height: me.props.doc.GetNumber(KeyStore.NativeHeight, 0), quality: 0.5 })
+            let nwidth = me.props.doc.GetNumber(KeyStore.NativeWidth, 0);
+            let nheight = me.props.doc.GetNumber(KeyStore.NativeHeight, 0);
+            htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 })
                 .then(function (dataUrl: string) {
                     me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField);
                     me.props.doc.SetNumber(KeyStore.ThumbnailPage, me.props.doc.GetNumber(KeyStore.CurPage, -1));
-- 
cgit v1.2.3-70-g09d2


From 93bed89512baa506c1b5ed2223ffc83fa6b5390e Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Thu, 4 Apr 2019 18:26:33 -0400
Subject: Changed linter stuff

---
 src/client/Server.ts                               | 12 ++---
 src/client/util/DocumentManager.ts                 |  4 +-
 src/client/util/Transform.ts                       | 30 ++++--------
 src/client/util/TypedEvent.ts                      |  3 +-
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/InkingStroke.tsx                  |  5 +-
 src/client/views/Main.tsx                          |  9 ++--
 .../views/collections/CollectionViewBase.tsx       | 13 +++---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 10 ++--
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  8 ++--
 src/client/views/nodes/DocumentView.tsx            |  6 ++-
 src/client/views/nodes/FieldView.tsx               |  5 +-
 src/debug/Viewer.tsx                               |  3 +-
 src/fields/Document.ts                             |  2 +-
 src/mobile/ImageUpload.tsx                         | 54 +++++++++++-----------
 src/server/index.ts                                |  8 ++--
 16 files changed, 82 insertions(+), 92 deletions(-)

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

diff --git a/src/client/Server.ts b/src/client/Server.ts
index e3f4448cb..45c7144ca 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -39,8 +39,8 @@ export class Server {
             } else if (cached !== FieldWaiting) {
                 setTimeout(() => cb(cached as Field), 0);
             } else {
-                reaction(() =>
-                    this.ClientFieldsCached.get(fieldid), (field, reaction) => {
+                reaction(() => this.ClientFieldsCached.get(fieldid),
+                    (field, reaction) => {
                         if (field !== FieldWaiting) {
                             reaction.dispose()
                             cb(field)
@@ -91,8 +91,8 @@ export class Server {
                         }
                     }
                 }
-                reaction(() =>
-                    waitingFieldIds.map(id => this.ClientFieldsCached.get(id)), (cachedFields, reaction) => {
+                reaction(() => waitingFieldIds.map(id => this.ClientFieldsCached.get(id)),
+                    (cachedFields, reaction) => {
                         if (!cachedFields.some(field => !field)) {
                             reaction.dispose();
                             for (let field of cachedFields) {
@@ -151,7 +151,7 @@ export class Server {
     @action
     private static cacheField(clientField: Field) {
         var cached = this.ClientFieldsCached.get(clientField.Id);
-        if (!cached || cached === FieldWaiting) {
+        if (!cached) {
             this.ClientFieldsCached.set(clientField.Id, clientField);
         } else {
             // probably should overwrite the values within any field that was already here...
@@ -163,7 +163,7 @@ export class Server {
     static updateField(field: { _id: string, data: any, type: Types }) {
         if (Server.ClientFieldsCached.has(field._id)) {
             var f = Server.ClientFieldsCached.get(field._id);
-            if (f && f !== FieldWaiting) {
+            if (f) {
                 // console.log("Applying        : " + field._id);
                 f.UpdateFromServer(field.data);
                 f.init(() => { });
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 7cb368f47..fb489edb6 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -42,7 +42,7 @@ export class DocumentManager {
             let doc = view.props.Document;
             // if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) {
 
-            if (Object.is(doc, toFind)) {
+            if (doc === toFind) {
                 toReturn = view;
                 return;
             }
@@ -63,7 +63,7 @@ export class DocumentManager {
             let doc = view.props.Document;
             // if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) {
 
-            if (Object.is(doc, toFind)) {
+            if (doc === toFind) {
                 toReturn.push(view);
             } else {
                 let docSrc = doc.GetT(KeyStore.Prototype, Document);
diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts
index 8608264a1..54effd512 100644
--- a/src/client/util/Transform.ts
+++ b/src/client/util/Transform.ts
@@ -62,26 +62,19 @@ export class Transform {
         return this;
     }
 
-    translated = (x: number, y: number): Transform =>
-        this.copy().translate(x, y)
+    translated = (x: number, y: number): Transform => this.copy().translate(x, y)
 
-    preTranslated = (x: number, y: number): Transform =>
-        this.copy().preTranslate(x, y)
+    preTranslated = (x: number, y: number): Transform => this.copy().preTranslate(x, y)
 
-    scaled = (scale: number): Transform =>
-        this.copy().scale(scale)
+    scaled = (scale: number): Transform => this.copy().scale(scale)
 
-    scaledAbout = (scale: number, x: number, y: number): Transform =>
-        this.copy().scaleAbout(scale, x, y)
+    scaledAbout = (scale: number, x: number, y: number): Transform => this.copy().scaleAbout(scale, x, y)
 
-    preScaled = (scale: number): Transform =>
-        this.copy().preScale(scale)
+    preScaled = (scale: number): Transform => this.copy().preScale(scale)
 
-    transformed = (transform: Transform): Transform =>
-        this.copy().transform(transform)
+    transformed = (transform: Transform): Transform => this.copy().transform(transform)
 
-    preTransformed = (transform: Transform): Transform =>
-        this.copy().preTransform(transform)
+    preTransformed = (transform: Transform): Transform => this.copy().preTransform(transform)
 
     transformPoint = (x: number, y: number): [number, number] => {
         x *= this._scale;
@@ -91,8 +84,7 @@ export class Transform {
         return [x, y];
     }
 
-    transformDirection = (x: number, y: number): [number, number] =>
-        [x * this._scale, y * this._scale]
+    transformDirection = (x: number, y: number): [number, number] => [x * this._scale, y * this._scale]
 
     transformBounds(x: number, y: number, width: number, height: number): { x: number, y: number, width: number, height: number } {
         [x, y] = this.transformPoint(x, y);
@@ -100,10 +92,8 @@ export class Transform {
         return { x, y, width, height };
     }
 
-    inverse = () =>
-        new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
+    inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
 
-    copy = () =>
-        new Transform(this._translateX, this._translateY, this._scale)
+    copy = () => new Transform(this._translateX, this._translateY, this._scale)
 
 }
\ No newline at end of file
diff --git a/src/client/util/TypedEvent.ts b/src/client/util/TypedEvent.ts
index c590d3734..1b251da25 100644
--- a/src/client/util/TypedEvent.ts
+++ b/src/client/util/TypedEvent.ts
@@ -36,6 +36,5 @@ export class TypedEvent<T> {
     this.listenersOncer = [];
   }
 
-  pipe = (te: TypedEvent<T>): Disposable =>
-    this.on((e) => te.emit(e))
+  pipe = (te: TypedEvent<T>): Disposable => this.on((e) => te.emit(e))
 }
\ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b0aa190e5..a6117dfa0 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -75,7 +75,7 @@ export class DocumentDecorations extends React.Component {
         this._dragging = true;
         document.removeEventListener("pointermove", this.onBackgroundMove);
         document.removeEventListener("pointerup", this.onBackgroundUp);
-        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont.current), dragData, {
+        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => docView.ContentRef.current!), dragData, {
             handlers: {
                 dragComplete: action(() => this._dragging = false),
             },
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index dbb79c0c6..12b15a3f0 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -29,8 +29,9 @@ export class InkingStroke extends React.Component<StrokeProps> {
         }
     }
 
-    parseData = (line: Array<{ x: number, y: number }>): string =>
-        !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ")
+    parseData = (line: Array<{ x: number, y: number }>): string => {
+        return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ")
+    }
 
     createStyle() {
         switch (this._strokeTool) {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 446c3d55f..33759d38a 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -371,7 +371,8 @@ export class Main extends React.Component {
     }
 }
 
-Documents.initProtos().then(() =>
-    CurrentUserUtils.loadCurrentUser()).then(() => {
-        ReactDOM.render(<Main />, document.getElementById('root'));
-    });
+(async () => {
+    await Documents.initProtos()
+    await CurrentUserUtils.loadCurrentUser()
+    ReactDOM.render(<Main />, document.getElementById('root'));
+})()
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 51280275c..2b858789f 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -134,7 +134,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         e.stopPropagation()
         e.preventDefault()
 
-        if (html && html.indexOf("<img") != 0 && !html.startsWith("<a")) {
+        if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
             console.log("not good");
             let htmlDoc = Documents.HtmlDocument(html, { ...options, width: 300, height: 300 });
             htmlDoc.SetText(KeyStore.DocumentText, text);
@@ -142,10 +142,11 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             return;
         }
 
+        // tslint:disable-next-line:prefer-for-of
         for (let i = 0; i < e.dataTransfer.items.length; i++) {
             const upload = window.location.origin + RouteStore.upload;
             let item = e.dataTransfer.items[i];
-            if (item.kind === "string" && item.type.indexOf("uri") != -1) {
+            if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
                 e.dataTransfer.items[i].getAsString(action((s: string) => {
                     request.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s), (err, res, body) => {
                         let type = res.headers["content-type"];
@@ -160,7 +161,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
                 }))
             }
             let type = item.type
-            if (item.kind == "file") {
+            if (item.kind === "file") {
                 let file = item.getAsFile();
                 let formData = new FormData()
 
@@ -171,15 +172,15 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
                 fetch(upload, {
                     method: 'POST',
                     body: formData
-                }).then((res: Response) =>
-                    res.json()).then(json => {
+                }).then(async (res: Response) => {
+                    const json = await res.json();
                     json.map((file: any) => {
                         let path = window.location.origin + file
                         runInAction(() => {
                             let doc = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300 })
 
                             let docs = this.props.Document.GetT(KeyStore.Data, ListField);
-                            if (docs != FieldWaiting) {
+                            if (docs !== FieldWaiting) {
                                 if (!docs) {
                                     docs = new ListField<Document>();
                                     this.props.Document.Set(KeyStore.Data, docs)
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 8c5d3f536..f03205739 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -54,7 +54,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
         return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).reduce((active, doc) => {
             var page = doc.GetNumber(KeyStore.Page, -1);
-            if (page == curPage || page == -1) {
+            if (page === curPage || page === -1) {
                 active.push(doc);
             }
             return active;
@@ -115,7 +115,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling != 1)) || e.button == 0) && this.props.active()) {
+        if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling !== 1)) || e.button === 0) && this.props.active()) {
             document.removeEventListener("pointermove", this.onPointerMove);
             document.addEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
@@ -137,7 +137,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     onPointerMove = (e: PointerEvent): void => {
         if (!e.cancelBubble && this.props.active()) {
-            if ((!this.isAnnotationOverlay || this.zoomScaling != 1) && !e.shiftKey) {
+            if ((!this.isAnnotationOverlay || this.zoomScaling !== 1) && !e.shiftKey) {
                 let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
                 let y = this.props.Document.GetNumber(KeyStore.PanY, 0);
                 let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
@@ -247,7 +247,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
             removeDocument: this.props.removeDocument,
             ScreenToLocalTransform: this.getTransform,
             isTopMost: false,
-            selectOnLoad: document.Id == this._selectOnLoaded,
+            selectOnLoad: document.Id === this._selectOnLoaded,
             PanelWidth: document.Width,
             PanelHeight: document.Height,
             ContentScaling: this.noScaling,
@@ -263,7 +263,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
         return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => {
             var page = doc.GetNumber(KeyStore.Page, -1);
-            if (page == curPage || page == -1)
+            if (page === curPage || page === -1)
                 prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />);
             return prev;
         }, [] as JSX.Element[])
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index e6475ee2a..ce453b4af 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -52,12 +52,12 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
         this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
     }
 
-    contentScaling = () =>
-        this.nativeWidth > 0 ? this.width / this.nativeWidth : 1
+    contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1
 
     getTransform = (): Transform =>
-        this.props.ScreenToLocalTransform().
-            translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0)).scale(1 / this.contentScaling())
+        this.props.ScreenToLocalTransform()
+            .translate(-this.props.Document.GetNumber(KeyStore.X, 0), -this.props.Document.GetNumber(KeyStore.Y, 0))
+            .scale(1 / this.contentScaling())
 
     @computed
     get docView() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 34eb8919f..3b146654c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -85,6 +85,9 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
 @observer
 export class DocumentView extends React.Component<DocumentViewProps> {
     private _mainCont = React.createRef<HTMLDivElement>();
+    public get ContentRef() {
+        return this._mainCont;
+    }
     private _downX: number = 0;
     private _downY: number = 0;
     @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); }
@@ -287,8 +290,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
 
 
-    isSelected = () =>
-        SelectionManager.IsSelected(this)
+    isSelected = () => SelectionManager.IsSelected(this)
 
     select = (ctrlPressed: boolean) => {
         SelectionManager.SelectDoc(this, ctrlPressed)
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index d6035a076..d9422ae9b 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -96,8 +96,7 @@ export class FieldView extends React.Component<FieldViewProps> {
         }
         else if (field instanceof ListField) {
             return (<div>
-                {(field as ListField<Field>).Data.map(f =>
-                    f instanceof Document ? f.Title : f.GetValue().toString()).join(", ")}
+                {(field as ListField<Field>).Data.map(f => f instanceof Document ? f.Title : f.GetValue().toString()).join(", ")}
             </div>)
         }
         // bcz: this belongs here, but it doesn't render well so taking it out for now
@@ -107,7 +106,7 @@ export class FieldView extends React.Component<FieldViewProps> {
         else if (field instanceof NumberField) {
             return <p>{field.Data}</p>
         }
-        else if (field != FieldWaiting) {
+        else if (field !== FieldWaiting) {
             return <p>{JSON.stringify(field.GetValue())}</p>
         }
         else
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index 9f52d0ea6..f13cccd24 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -177,8 +177,7 @@ class Viewer extends React.Component {
                     onChange={this.inputOnChange}
                     onKeyDown={this.onKeyPress} />
                 <div>
-                    {this.ids.map(id =>
-                        <DebugViewer fieldId={id} key={id}></DebugViewer>)}
+                    {this.ids.map(id => <DebugViewer fieldId={id} key={id}></DebugViewer>)}
                 </div>
             </>
         )
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 45e4f93f6..6d13c96b8 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -90,7 +90,7 @@ export class Document extends Field {
             }
         } else {
             let doc: FieldValue<Document> = this;
-            while (doc && doc !== FieldWaiting && field !== FieldWaiting) {
+            while (doc && field !== FieldWaiting) {
                 let curField = doc.fields.get(key.Id);
                 let curProxy = doc._proxies.get(key.Id);
                 if (!curField || (curProxy && curField.field.Id !== curProxy)) {
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index c4d346876..c3684a0eb 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -9,6 +9,7 @@ import { RouteStore } from '../server/RouteStore';
 import { ServerUtils } from '../server/ServerUtil';
 import "./ImageUpload.scss";
 import React = require('react');
+import { Opt } from '../fields/Field';
 
 
 
@@ -20,47 +21,44 @@ import React = require('react');
 //     }
 // }
 
-const onFileLoad = (file: any) => {
+const onFileLoad = async (file: any) => {
     let imgPrev = document.getElementById("img_preview")
     if (imgPrev) {
         let files: File[] = file.target.files;
-        if (files.length != 0) {
+        if (files.length !== 0) {
             console.log(files[0]);
             let formData = new FormData();
             formData.append("file", files[0]);
 
             const upload = window.location.origin + "/upload"
-            fetch(upload, {
+            const res = await fetch(upload, {
                 method: 'POST',
                 body: formData
-            }).then((res: Response) =>
-                res.json()).then(json => {
-                json.map((file: any) => {
-                    let path = window.location.origin + file
-                    var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 })
+            });
+            const json = await res.json();
+            json.map(async (file: any) => {
+                let path = window.location.origin + file
+                var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 })
 
-                    rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(res => {
-                        if (res) {
-                            return Server.GetField(res);
-                        }
-                        throw new Error("No user id returned");
-                    }).then(field => {
-                        if (field instanceof Document) {
-                            return field.GetTAsync(KeyStore.OptionalRightCollection, Document)
-                        }
-                    }).then(pending => {
-                        if (pending) {
-                            pending.GetOrCreateAsync(KeyStore.Data, ListField, list => {
-                                list.Data.push(doc);
-                            })
-                        }
-                    });
+                const res = await rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId));
+                if (!res) {
+                    throw new Error("No user id returned");
+                }
+                const field = await Server.GetField(res);
+                let pending: Opt<Document>;
+                if (field instanceof Document) {
+                    pending = await field.GetTAsync(KeyStore.OptionalRightCollection, Document)
+                }
+                if (pending) {
+                    pending.GetOrCreateAsync(KeyStore.Data, ListField, list => {
+                        list.Data.push(doc);
+                    })
+                }
+            });
 
-                    // console.log(window.location.origin + file[0])
+            // console.log(window.location.origin + file[0])
 
-                    //imgPrev.setAttribute("src", window.location.origin + files[0].name)
-                })
-            })
+            //imgPrev.setAttribute("src", window.location.origin + files[0].name)
         }
     }
 }
diff --git a/src/server/index.ts b/src/server/index.ts
index 0c61f6885..ce8bbefe8 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -263,10 +263,10 @@ function deleteFields() {
     return Database.Instance.deleteAll();
 }
 
-function deleteAll() {
-    return Database.Instance.deleteAll().then(() =>
-        Database.Instance.deleteAll('sessions')).then(() =>
-            Database.Instance.deleteAll('users'));
+async function deleteAll() {
+    await Database.Instance.deleteAll();
+    await Database.Instance.deleteAll('sessions');
+    await Database.Instance.deleteAll('users');
 }
 
 function barReceived(guid: String) {
-- 
cgit v1.2.3-70-g09d2


From dc20420e4757824974ba4b2ea3926d541f5e8b60 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Thu, 4 Apr 2019 20:13:19 -0400
Subject: fixed merge

---
 src/client/views/DocumentDecorations.tsx | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 99588480d..11bf24505 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -55,9 +55,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     enterPressed = (e: any) => {
         var key = e.keyCode || e.which;
         // enter pressed
-        if (key == 13) {
+        if (key === 13) {
             var text = e.target.value;
-            if (text[0] == '#') {
+            if (text[0] === '#') {
                 let command = text.slice(1, text.length);
                 this._fieldKey = new Key(command)
                 // if (command == "Title" || command == "title") {
@@ -156,7 +156,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     onCloseUp = (e: PointerEvent): void => {
         e.stopPropagation();
         if (e.button === 0) {
-            SelectionManager.SelectedDocuments().map(dv => dv.props.RemoveDocument && dv.props.RemoveDocument(dv.props.Document));
+            SelectionManager.SelectedDocuments().map(dv => dv.props.removeDocument && dv.props.removeDocument(dv.props.Document));
             SelectionManager.DeselectAll();
             document.removeEventListener("pointermove", this.onCloseMove);
             document.removeEventListener("pointerup", this.onCloseUp);
@@ -211,7 +211,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     onLinkerButtonMoved = (e: PointerEvent): void => {
-        if (this._linkerButton.current != null) {
+        if (this._linkerButton.current !== null) {
             document.removeEventListener("pointermove", this.onLinkerButtonMoved)
             document.removeEventListener("pointerup", this.onLinkerButtonUp)
             let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
@@ -240,25 +240,24 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     onLinkButtonMoved = async (e: PointerEvent) => {
-        if (this._linkButton.current != null) {
+        if (this._linkButton.current !== null) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved)
             document.removeEventListener("pointerup", this.onLinkButtonUp);
 
             let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document;
             let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
-            let draggedDocs = (srcTarg && srcTarg != FieldWaiting) ?
+            let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
                 srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
                     (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
-            let draggedFromDocs = (srcTarg && srcTarg != FieldWaiting) ?
+            let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
                 srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
                     (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
             draggedDocs.push(...draggedFromDocs);
             if (draggedDocs.length) {
                 let moddrag = [] as Document[];
-                for (let i = 0; i < draggedDocs.length; i++) {
-                    let doc = await draggedDocs[i].GetTAsync(KeyStore.AnnotationOn, Document);
-                    if (doc)
-                        moddrag.push(doc);
+                for (const draggedDoc of draggedDocs) {
+                    let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
+                    if (doc) moddrag.push(doc);
                 }
                 let dragData = new DragManager.DocumentDragData(moddrag);
                 DragManager.StartDocumentDrag([this._linkButton.current], dragData, {
-- 
cgit v1.2.3-70-g09d2


From 0403ee1f31d3f127a44aaabdfd21785d7efa6430 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 5 Apr 2019 01:17:41 -0400
Subject: Fixed remaining linter warnings

---
 src/client/northstar/core/BaseObject.ts            |   2 +-
 .../northstar/core/attribute/AttributeModel.ts     |   4 +-
 .../core/attribute/AttributeTransformationModel.ts |   2 +-
 .../core/attribute/CalculatedAttributeModel.ts     |   4 +-
 src/client/northstar/core/filter/FilterModel.ts    |   6 +-
 .../northstar/core/filter/ValueComparision.ts      |   8 +-
 src/client/northstar/dash-fields/HistogramField.ts |   8 +-
 .../dash-nodes/HistogramBinPrimitiveCollection.ts  |  46 ++++-----
 src/client/northstar/dash-nodes/HistogramBox.tsx   |  12 +--
 .../dash-nodes/HistogramBoxPrimitives.tsx          |  18 ++--
 .../dash-nodes/HistogramLabelPrimitives.tsx        |  10 +-
 src/client/northstar/manager/Gateway.ts            |   8 +-
 src/client/northstar/model/ModelExtensions.ts      |  14 +--
 src/client/northstar/model/ModelHelpers.ts         |  10 +-
 .../model/binRanges/DateTimeVisualBinRange.ts      |  24 ++---
 .../northstar/model/binRanges/VisualBinRange.ts    |   4 -
 .../model/binRanges/VisualBinRangeHelper.ts        |   7 +-
 .../northstar/model/idea/MetricTypeMapping.ts      |  28 +++---
 src/client/northstar/operations/BaseOperation.ts   |   8 +-
 .../northstar/operations/HistogramOperation.ts     |   2 +-
 src/client/northstar/utils/ArrayUtil.ts            |  14 +--
 src/client/northstar/utils/GeometryUtil.ts         |   2 +-
 src/client/northstar/utils/MathUtil.ts             |  12 +--
 src/client/northstar/utils/SizeConverter.ts        |   4 +-
 src/client/northstar/utils/Utils.ts                |  12 +--
 src/client/views/DocumentDecorations.tsx           |   4 +-
 src/client/views/Main.tsx                          |   4 +-
 .../views/collections/CollectionBaseView.tsx       |   8 +-
 .../views/collections/CollectionDockingView.tsx    |  30 +++---
 src/client/views/collections/CollectionPDFView.tsx |   2 +-
 .../views/collections/CollectionSchemaView.tsx     |   2 +-
 .../views/collections/CollectionVideoView.tsx      |   4 +-
 src/client/views/collections/CollectionView.tsx    |   2 +-
 .../views/collections/CollectionViewBase.tsx       |   4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   4 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  12 +--
 .../collectionFreeForm/PreviewCursor.tsx           |   2 +-
 src/client/views/nodes/Annotation.tsx              | 108 ++++++++++-----------
 src/client/views/nodes/AudioBox.tsx                |   2 +-
 src/client/views/nodes/DocumentContentsView.tsx    |   2 +-
 src/client/views/nodes/KeyValueBox.tsx             |   6 +-
 src/client/views/nodes/LinkBox.tsx                 |   2 +-
 src/client/views/nodes/LinkMenu.tsx                |   2 +-
 src/client/views/nodes/VideoBox.tsx                |   2 +-
 src/client/views/nodes/WebBox.tsx                  |   2 +-
 src/fields/AudioField.ts                           |   2 +-
 src/fields/BasicField.ts                           |   2 +-
 src/fields/ImageField.ts                           |   2 +-
 src/fields/ListField.ts                            |  10 +-
 src/fields/PDFField.ts                             |   2 +-
 src/fields/VideoField.ts                           |   2 +-
 src/server/index.ts                                |   2 +-
 52 files changed, 245 insertions(+), 250 deletions(-)

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

diff --git a/src/client/northstar/core/BaseObject.ts b/src/client/northstar/core/BaseObject.ts
index e9e766e31..f1761e643 100644
--- a/src/client/northstar/core/BaseObject.ts
+++ b/src/client/northstar/core/BaseObject.ts
@@ -4,7 +4,7 @@ import { IDisposable } from '../utils/IDisposable'
 export class BaseObject implements IEquatable, IDisposable {
 
     public Equals(other: Object): boolean {
-        return this == other;
+        return this === other;
     }
 
     public Dispose(): void {
diff --git a/src/client/northstar/core/attribute/AttributeModel.ts b/src/client/northstar/core/attribute/AttributeModel.ts
index 124a5b45a..230bfecc8 100644
--- a/src/client/northstar/core/attribute/AttributeModel.ts
+++ b/src/client/northstar/core/attribute/AttributeModel.ts
@@ -34,7 +34,7 @@ export class ColumnAttributeModel extends AttributeModel {
     }
 
     public Equals(other: ColumnAttributeModel): boolean {
-        return this.Attribute.rawName == other.Attribute.rawName;
+        return this.Attribute.rawName === other.Attribute.rawName;
     }
 }
 
@@ -105,7 +105,7 @@ export class BackendAttributeModel extends AttributeModel {
     }
 
     public Equals(other: BackendAttributeModel): boolean {
-        return this.Id == other.Id;
+        return this.Id === other.Id;
     }
 
 }
\ No newline at end of file
diff --git a/src/client/northstar/core/attribute/AttributeTransformationModel.ts b/src/client/northstar/core/attribute/AttributeTransformationModel.ts
index cc5aa7154..f50b78d51 100644
--- a/src/client/northstar/core/attribute/AttributeTransformationModel.ts
+++ b/src/client/northstar/core/attribute/AttributeTransformationModel.ts
@@ -41,7 +41,7 @@ export class AttributeTransformationModel implements IEquatable {
     }
 
     public Equals(other: AttributeTransformationModel): boolean {
-        return this.AggregateFunction == other.AggregateFunction &&
+        return this.AggregateFunction === other.AggregateFunction &&
             this.AttributeModel.Equals(other.AttributeModel);
     }
 }
\ No newline at end of file
diff --git a/src/client/northstar/core/attribute/CalculatedAttributeModel.ts b/src/client/northstar/core/attribute/CalculatedAttributeModel.ts
index ab96c794d..0b8e0d12c 100644
--- a/src/client/northstar/core/attribute/CalculatedAttributeModel.ts
+++ b/src/client/northstar/core/attribute/CalculatedAttributeModel.ts
@@ -11,7 +11,7 @@ export class CalculatedAttributeManager {
     public static CreateBackendAttributeModel(id: string, dataType: DataType, displayName: string, codeName: string, visualizationHints: VisualizationHint[]): BackendAttributeModel {
         var filtered = this.AllCalculatedAttributes.filter(am => {
             if (am instanceof BackendAttributeModel &&
-                am.Id == id) {
+                am.Id === id) {
                 return true;
             }
             return false;
@@ -27,7 +27,7 @@ export class CalculatedAttributeManager {
     public static CreateCodeAttributeModel(code: string, codeName: string, visualizationHints: VisualizationHint[]): CodeAttributeModel {
         var filtered = this.AllCalculatedAttributes.filter(am => {
             if (am instanceof CodeAttributeModel &&
-                am.CodeName == codeName) {
+                am.CodeName === codeName) {
                 return true;
             }
             return false;
diff --git a/src/client/northstar/core/filter/FilterModel.ts b/src/client/northstar/core/filter/FilterModel.ts
index aee99d2b6..20fca77f5 100644
--- a/src/client/northstar/core/filter/FilterModel.ts
+++ b/src/client/northstar/core/filter/FilterModel.ts
@@ -46,16 +46,16 @@ export class FilterModel {
         let filtered = baseOperation.FilterModels.filter(fm => fm && fm.ValueComparisons.length > 0);
         if (!isFirst && filtered.length > 0) {
             filterModels.push(...filtered);
-            ret = "(" + baseOperation.FilterModels.filter(fm => fm != null).map(fm => fm.ToPythonString()).join(" || ") + ")";
+            ret = "(" + baseOperation.FilterModels.filter(fm => fm !== null).map(fm => fm.ToPythonString()).join(" || ") + ")";
         }
         if (Utils.isBaseFilterConsumer(baseOperation) && baseOperation.Links) {
             let children = new Array<string>();
             let linkedGraphNodes = baseOperation.Links;
             linkedGraphNodes.map(linkVm => {
                 let filterDoc = linkVm.Get(KeyStore.LinkedFromDocs);
-                if (filterDoc && filterDoc != FieldWaiting && filterDoc instanceof Document) {
+                if (filterDoc && filterDoc !== FieldWaiting && filterDoc instanceof Document) {
                     let filterHistogram = filterDoc.GetT(KeyStore.Data, HistogramField);
-                    if (filterHistogram && filterHistogram != FieldWaiting) {
+                    if (filterHistogram && filterHistogram !== FieldWaiting) {
                         if (!visitedFilterProviders.has(filterHistogram.Data)) {
                             let child = FilterModel.GetFilterModelsRecursive(filterHistogram.Data, visitedFilterProviders, filterModels, false);
                             if (child !== "") {
diff --git a/src/client/northstar/core/filter/ValueComparision.ts b/src/client/northstar/core/filter/ValueComparision.ts
index 1e729d06e..1a3e461f5 100644
--- a/src/client/northstar/core/filter/ValueComparision.ts
+++ b/src/client/northstar/core/filter/ValueComparision.ts
@@ -20,7 +20,7 @@ export class ValueComparison {
         if (this.Predicate !== (other as ValueComparison).Predicate)
             return false;
         let isComplex = (typeof this.Value === "object");
-        if (!isComplex && this.Value != (other as ValueComparison).Value)
+        if (!isComplex && this.Value !== (other as ValueComparison).Value)
             return false;
         if (isComplex && !this.Value.Equals((other as ValueComparison).Value))
             return false;
@@ -58,13 +58,13 @@ export class ValueComparison {
         var rawName = this.attributeModel.CodeName;
         switch (this.Predicate) {
             case Predicate.STARTS_WITH:
-                ret += rawName + " != null && " + rawName + ".StartsWith(" + val + ") ";
+                ret += rawName + " !== null && " + rawName + ".StartsWith(" + val + ") ";
                 return ret;
             case Predicate.ENDS_WITH:
-                ret += rawName + " != null && " + rawName + ".EndsWith(" + val + ") ";
+                ret += rawName + " !== null && " + rawName + ".EndsWith(" + val + ") ";
                 return ret;
             case Predicate.CONTAINS:
-                ret += rawName + " != null && " + rawName + ".Contains(" + val + ") ";
+                ret += rawName + " !== null && " + rawName + ".Contains(" + val + ") ";
                 return ret;
             default:
                 ret += rawName + " " + op + " " + val + " ";
diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts
index 90be70b80..f939ccd83 100644
--- a/src/client/northstar/dash-fields/HistogramField.ts
+++ b/src/client/northstar/dash-fields/HistogramField.ts
@@ -16,7 +16,7 @@ export class HistogramField extends BasicField<HistogramOperation> {
     omitKeys(obj: any, keys: any) {
         var dup: any = {};
         for (var key in obj) {
-            if (keys.indexOf(key) == -1) {
+            if (keys.indexOf(key) === -1) {
                 dup[key] = obj[key];
             }
         }
@@ -54,13 +54,13 @@ export class HistogramField extends BasicField<HistogramOperation> {
         let schema = CurrentUserUtils.GetNorthstarSchema(jp.SchemaName);
         if (schema) {
             CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
-                if (attr.displayName == jp.X.AttributeModel.Attribute.DisplayName) {
+                if (attr.displayName === jp.X.AttributeModel.Attribute.DisplayName) {
                     X = new AttributeTransformationModel(new ColumnAttributeModel(attr), jp.X.AggregateFunction);
                 }
-                if (attr.displayName == jp.Y.AttributeModel.Attribute.DisplayName) {
+                if (attr.displayName === jp.Y.AttributeModel.Attribute.DisplayName) {
                     Y = new AttributeTransformationModel(new ColumnAttributeModel(attr), jp.Y.AggregateFunction);
                 }
-                if (attr.displayName == jp.V.AttributeModel.Attribute.DisplayName) {
+                if (attr.displayName === jp.V.AttributeModel.Attribute.DisplayName) {
                     V = new AttributeTransformationModel(new ColumnAttributeModel(attr), jp.V.AggregateFunction);
                 }
             });
diff --git a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
index 43e768c62..cdae90c8b 100644
--- a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
+++ b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
@@ -48,28 +48,28 @@ export class HistogramBinPrimitiveCollection {
 
         // adjust brush rects (stacking or not)
         var allBrushIndex = ModelHelpers.AllBrushIndex(this.histoResult);
-        var filteredBinPrims = this.BinPrimitives.filter(b => b.BrushIndex != allBrushIndex && b.DataValue != 0.0);
+        var filteredBinPrims = this.BinPrimitives.filter(b => b.BrushIndex !== allBrushIndex && b.DataValue !== 0.0);
         filteredBinPrims.reduce((sum, fbp) => {
-            if (histoBox.ChartType == ChartType.VerticalBar) {
-                if (this.histoOp.Y.AggregateFunction == AggregateFunction.Count) {
+            if (histoBox.ChartType === ChartType.VerticalBar) {
+                if (this.histoOp.Y.AggregateFunction === AggregateFunction.Count) {
                     fbp.Rect = new PIXIRectangle(fbp.Rect.x, fbp.Rect.y - sum, fbp.Rect.width, fbp.Rect.height);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x, fbp.MarginRect.y - sum, fbp.MarginRect.width, fbp.MarginRect.height);
                     return sum + fbp.Rect.height;
                 }
-                if (this.histoOp.Y.AggregateFunction == AggregateFunction.Avg) {
+                if (this.histoOp.Y.AggregateFunction === AggregateFunction.Avg) {
                     var w = fbp.Rect.width / 2.0;
                     fbp.Rect = new PIXIRectangle(fbp.Rect.x + sum, fbp.Rect.y, fbp.Rect.width / filteredBinPrims.length, fbp.Rect.height);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x - w + sum + (fbp.Rect.width / 2.0), fbp.MarginRect.y, fbp.MarginRect.width, fbp.MarginRect.height);
                     return sum + fbp.Rect.width;
                 }
             }
-            else if (histoBox.ChartType == ChartType.HorizontalBar) {
-                if (this.histoOp.X.AggregateFunction == AggregateFunction.Count) {
+            else if (histoBox.ChartType === ChartType.HorizontalBar) {
+                if (this.histoOp.X.AggregateFunction === AggregateFunction.Count) {
                     fbp.Rect = new PIXIRectangle(fbp.Rect.x + sum, fbp.Rect.y, fbp.Rect.width, fbp.Rect.height);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x + sum, fbp.MarginRect.y, fbp.MarginRect.width, fbp.MarginRect.height);
                     return sum + fbp.Rect.width;
                 }
-                if (this.histoOp.X.AggregateFunction == AggregateFunction.Avg) {
+                if (this.histoOp.X.AggregateFunction === AggregateFunction.Avg) {
                     var h = fbp.Rect.height / 2.0;
                     fbp.Rect = new PIXIRectangle(fbp.Rect.x, fbp.Rect.y + sum, fbp.Rect.width, fbp.Rect.height / filteredBinPrims.length);
                     fbp.MarginRect = new PIXIRectangle(fbp.MarginRect.x, fbp.MarginRect.y - h + sum + (fbp.Rect.height / 2.0), fbp.MarginRect.width, fbp.MarginRect.height);
@@ -79,19 +79,19 @@ export class HistogramBinPrimitiveCollection {
             return 0;
         }, 0);
         this.BinPrimitives = this.BinPrimitives.reverse();
-        var f = this.BinPrimitives.filter(b => b.BrushIndex == allBrushIndex);
+        var f = this.BinPrimitives.filter(b => b.BrushIndex === allBrushIndex);
         this.HitGeom = f.length > 0 ? f[0].Rect : PIXIRectangle.EMPTY;
     }
 
     private setupBrushing(bin: Bin, normalization: number) {
         var overlapBrushIndex = ModelHelpers.OverlapBrushIndex(this.histoResult);
         var orderedBrushes = [this.histoResult.brushes![0], this.histoResult.brushes![overlapBrushIndex]];
-        this.histoResult.brushes!.map(brush => brush.brushIndex != 0 && brush.brushIndex != overlapBrushIndex && orderedBrushes.push(brush));
+        this.histoResult.brushes!.map(brush => brush.brushIndex !== 0 && brush.brushIndex !== overlapBrushIndex && orderedBrushes.push(brush));
         return {
             orderedBrushes,
             maxAxis: orderedBrushes.reduce((prev, Brush) => {
                 let aggResult = this.getBinValue(normalization, bin, Brush.brushIndex!);
-                return aggResult != undefined && aggResult > prev ? aggResult : prev;
+                return aggResult !== undefined && aggResult > prev ? aggResult : prev;
             }, Number.MIN_VALUE)
         };
     }
@@ -99,7 +99,7 @@ export class HistogramBinPrimitiveCollection {
     private createHeatmapBinPrimitives(bin: Bin, brush: Brush, brushFactorSum: number): number {
 
         let unNormalizedValue = this.getBinValue(2, bin, brush.brushIndex!);
-        if (unNormalizedValue == undefined)
+        if (unNormalizedValue === undefined)
             return brushFactorSum;
 
         var normalizedValue = (unNormalizedValue - this._histoBox.ValueRange[0]) / (Math.abs((this._histoBox.ValueRange[1] - this._histoBox.ValueRange[0])) < HistogramBinPrimitiveCollection.TOLERANCE ?
@@ -112,7 +112,7 @@ export class HistogramBinPrimitiveCollection {
         let [yFrom, yTo] = this.sizeConverter.DataToScreenYAxisRange(this._histoBox.VisualBinRanges, 1, bin);
 
         var returnBrushFactorSum = brushFactorSum;
-        if (allUnNormalizedValue != undefined) {
+        if (allUnNormalizedValue !== undefined) {
             var brushFactor = (unNormalizedValue / allUnNormalizedValue);
             returnBrushFactorSum += brushFactor;
             returnBrushFactorSum = Math.min(returnBrushFactorSum, 1.0);
@@ -141,11 +141,11 @@ export class HistogramBinPrimitiveCollection {
 
     private createSinglePointChartBinPrimitives(bin: Bin, brush: Brush): number {
         let unNormalizedValue = this.getBinValue(2, bin, brush.brushIndex!);
-        if (unNormalizedValue != undefined) {
+        if (unNormalizedValue !== undefined) {
             let [xFrom, xTo] = this.sizeConverter.DataToScreenPointRange(0, bin, ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, this.histoOp.X, this.histoResult, brush.brushIndex!));
             let [yFrom, yTo] = this.sizeConverter.DataToScreenPointRange(1, bin, ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, this.histoOp.Y, this.histoResult, brush.brushIndex!));
 
-            if (xFrom != undefined && yFrom != undefined && xTo != undefined && yTo != undefined)
+            if (xFrom !== undefined && yFrom !== undefined && xTo !== undefined && yTo !== undefined)
                 this.createBinPrimitive(-1, brush, PIXIRectangle.EMPTY, 0, xFrom, xTo, yFrom, yTo, this.baseColorFromBrush(brush), 1, unNormalizedValue);
         }
         return 0;
@@ -153,7 +153,7 @@ export class HistogramBinPrimitiveCollection {
 
     private createVerticalBarChartBinPrimitives(bin: Bin, brush: Brush, binBrushMaxAxis: number, normalization: number): number {
         let dataValue = this.getBinValue(1, bin, brush.brushIndex!);
-        if (dataValue != undefined) {
+        if (dataValue !== undefined) {
             let [yFrom, yValue, yTo] = this.sizeConverter.DataToScreenNormalizedRange(dataValue, normalization, 1, binBrushMaxAxis);
             let [xFrom, xTo] = this.sizeConverter.DataToScreenXAxisRange(this._histoBox.VisualBinRanges, 0, bin);
 
@@ -163,14 +163,14 @@ export class HistogramBinPrimitiveCollection {
                 this.sizeConverter.DataToScreenY(yValue - yMarginAbsolute) - this.sizeConverter.DataToScreenY(yValue + yMarginAbsolute));
 
             this.createBinPrimitive(1, brush, marginRect, 0, xFrom, xTo, yFrom, yTo,
-                this.baseColorFromBrush(brush), normalization != 0 ? 1 : 0.6 * binBrushMaxAxis / this.sizeConverter.DataRanges[1] + 0.4, dataValue);
+                this.baseColorFromBrush(brush), normalization !== 0 ? 1 : 0.6 * binBrushMaxAxis / this.sizeConverter.DataRanges[1] + 0.4, dataValue);
         }
         return 0;
     }
 
     private createHorizontalBarChartBinPrimitives(bin: Bin, brush: Brush, binBrushMaxAxis: number, normalization: number): number {
         let dataValue = this.getBinValue(0, bin, brush.brushIndex!);
-        if (dataValue != undefined) {
+        if (dataValue !== undefined) {
             let [xFrom, xValue, xTo] = this.sizeConverter.DataToScreenNormalizedRange(dataValue, normalization, 0, binBrushMaxAxis);
             let [yFrom, yTo] = this.sizeConverter.DataToScreenYAxisRange(this._histoBox.VisualBinRanges, 1, bin);
 
@@ -181,15 +181,15 @@ export class HistogramBinPrimitiveCollection {
                 2.0);
 
             this.createBinPrimitive(0, brush, marginRect, 0, xFrom, xTo, yFrom, yTo,
-                this.baseColorFromBrush(brush), normalization != 1 ? 1 : 0.6 * binBrushMaxAxis / this.sizeConverter.DataRanges[0] + 0.4, dataValue);
+                this.baseColorFromBrush(brush), normalization !== 1 ? 1 : 0.6 * binBrushMaxAxis / this.sizeConverter.DataRanges[0] + 0.4, dataValue);
         }
         return 0;
     }
 
     public getBinValue(axis: number, bin: Bin, brushIndex: number) {
-        var aggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, axis == 0 ? this.histoOp.X : axis == 1 ? this.histoOp.Y : this.histoOp.V, this.histoResult, brushIndex);
+        var aggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, axis === 0 ? this.histoOp.X : axis === 1 ? this.histoOp.Y : this.histoOp.V, this.histoResult, brushIndex);
         let dataValue = ModelHelpers.GetAggregateResult(bin, aggregateKey) as DoubleValueAggregateResult;
-        return dataValue != null && dataValue.hasResult ? dataValue.result : undefined;
+        return dataValue !== null && dataValue.hasResult ? dataValue.result : undefined;
     }
 
     private getMargin(bin: Bin, brush: Brush, axis: AttributeTransformationModel) {
@@ -218,13 +218,13 @@ export class HistogramBinPrimitiveCollection {
 
     private baseColorFromBrush(brush: Brush): number {
         let bc = StyleConstants.BRUSH_COLORS;
-        if (brush.brushIndex == ModelHelpers.RestBrushIndex(this.histoResult)) {
+        if (brush.brushIndex === ModelHelpers.RestBrushIndex(this.histoResult)) {
             return StyleConstants.HIGHLIGHT_COLOR;
         }
-        else if (brush.brushIndex == ModelHelpers.OverlapBrushIndex(this.histoResult)) {
+        else if (brush.brushIndex === ModelHelpers.OverlapBrushIndex(this.histoResult)) {
             return StyleConstants.OVERLAP_COLOR;
         }
-        else if (brush.brushIndex == ModelHelpers.AllBrushIndex(this.histoResult)) {
+        else if (brush.brushIndex === ModelHelpers.AllBrushIndex(this.histoResult)) {
             return 0x00ff00;
         }
         else if (bc.length > 0) {
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index 5938bf9b1..c9658d741 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -55,7 +55,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
     dropX = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.DocumentDragData) {
             let h = de.data.draggedDocuments[0].GetT(KeyStore.Data, HistogramField);
-            if (h && h != FieldWaiting) {
+            if (h && h !== FieldWaiting) {
                 this.HistoOp.X = h.Data.X;
             }
             e.stopPropagation();
@@ -66,7 +66,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
     dropY = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.DocumentDragData) {
             let h = de.data.draggedDocuments[0].GetT(KeyStore.Data, HistogramField);
-            if (h && h != FieldWaiting) {
+            if (h && h !== FieldWaiting) {
                 this.HistoOp.Y = h.Data.X;
             }
             e.stopPropagation();
@@ -76,11 +76,11 @@ export class HistogramBox extends React.Component<FieldViewProps> {
 
     @action
     xLabelPointerDown = (e: React.PointerEvent) => {
-        this.HistoOp.X = new AttributeTransformationModel(this.HistoOp.X.AttributeModel, this.HistoOp.X.AggregateFunction == AggregateFunction.None ? AggregateFunction.Count : AggregateFunction.None);
+        this.HistoOp.X = new AttributeTransformationModel(this.HistoOp.X.AttributeModel, this.HistoOp.X.AggregateFunction === AggregateFunction.None ? AggregateFunction.Count : AggregateFunction.None);
     }
     @action
     yLabelPointerDown = (e: React.PointerEvent) => {
-        this.HistoOp.Y = new AttributeTransformationModel(this.HistoOp.Y.AttributeModel, this.HistoOp.Y.AggregateFunction == AggregateFunction.None ? AggregateFunction.Count : AggregateFunction.None);
+        this.HistoOp.Y = new AttributeTransformationModel(this.HistoOp.Y.AttributeModel, this.HistoOp.Y.AggregateFunction === AggregateFunction.None ? AggregateFunction.Count : AggregateFunction.None);
     }
 
     componentDidMount() {
@@ -119,7 +119,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
         if (catalog) {
             this.props.Document.GetTAsync(this.props.fieldKey, HistogramField).then((histoOp: Opt<HistogramField>) => runInAction(() => {
                 this.HistoOp = histoOp ? histoOp.Data : HistogramOperation.Empty;
-                if (this.HistoOp != HistogramOperation.Empty) {
+                if (this.HistoOp !== HistogramOperation.Empty) {
                     reaction(() => this.props.Document.GetList(KeyStore.LinkedFromDocs, []), (docs: Document[]) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true });
                     reaction(() => this.props.Document.GetList(KeyStore.BrushingDocs, []).length,
                         () => {
@@ -128,7 +128,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
                             this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => {
                                 brush.SetNumber(KeyStore.BackgroundColor, StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]);
                                 let brushed = brush.GetList(KeyStore.BrushingDocs, [] as Document[]);
-                                return { l: brush, b: brushed[0].Id == proto.Id ? brushed[1] : brushed[0] }
+                                return { l: brush, b: brushed[0].Id === proto.Id ? brushed[1] : brushed[0] }
                             }));
                         }, { fireImmediately: true });
                     reaction(() => this.createOperationParamsCache, () => this.HistoOp.Update(), { fireImmediately: true });
diff --git a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
index e9adb3ce5..66d31846c 100644
--- a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
@@ -44,7 +44,7 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
     }
 
     private getSelectionToggle(binPrimitives: HistogramBinPrimitive[], allBrushIndex: number, filterModel: FilterModel) {
-        let allBrushPrim = ArrayUtil.FirstOrDefault(binPrimitives, bp => bp.BrushIndex == allBrushIndex);
+        let allBrushPrim = ArrayUtil.FirstOrDefault(binPrimitives, bp => bp.BrushIndex === allBrushIndex);
         return !allBrushPrim ? () => { } : () => runInAction(() => {
             if (ArrayUtil.Contains(this.histoOp.FilterModels, filterModel)) {
                 this._selectedPrims.splice(this._selectedPrims.indexOf(allBrushPrim!), 1);
@@ -63,9 +63,9 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
         let labels = this.props.HistoBox.VisualBinRanges[axis].GetLabels();
         return labels.reduce((prims, binLabel, i) => {
             let r = this.props.HistoBox.SizeConverter.DataToScreenRange(binLabel.minValue!, binLabel.maxValue!, axis);
-            prims.push(this.drawLine(r.xFrom, r.yFrom, axis == 0 ? 0 : r.xTo - r.xFrom, axis == 0 ? r.yTo - r.yFrom : 0));
-            if (i == labels.length - 1)
-                prims.push(this.drawLine(axis == 0 ? r.xTo : r.xFrom, axis == 0 ? r.yFrom : r.yTo, axis == 0 ? 0 : r.xTo - r.xFrom, axis == 0 ? r.yTo - r.yFrom : 0));
+            prims.push(this.drawLine(r.xFrom, r.yFrom, axis === 0 ? 0 : r.xTo - r.xFrom, axis === 0 ? r.yTo - r.yFrom : 0));
+            if (i === labels.length - 1)
+                prims.push(this.drawLine(axis === 0 ? r.xTo : r.xFrom, axis === 0 ? r.yFrom : r.yTo, axis === 0 ? 0 : r.xTo - r.xFrom, axis === 0 ? r.yTo - r.yFrom : 0));
             return prims;
         }, [] as JSX.Element[]);
     }
@@ -86,8 +86,8 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
             xFrom += width;
             width = -width;
         }
-        let trans2Xpercent = width == 0 ? `1px` : `${(xFrom + width) / this.renderDimension * 100}%`;
-        let trans2Ypercent = height == 0 ? `1px` : `${(yFrom + height) / this.renderDimension * 100}%`;
+        let trans2Xpercent = width === 0 ? `1px` : `${(xFrom + width) / this.renderDimension * 100}%`;
+        let trans2Ypercent = height === 0 ? `1px` : `${(yFrom + height) / this.renderDimension * 100}%`;
         let line = (<div className="histogramboxprimitives-line" style={{ width: trans2Xpercent, height: trans2Ypercent, }} />);
         return this.drawEntity(xFrom, yFrom, line);
     }
@@ -102,10 +102,10 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
         }
         let widthPercent = r.width / this.renderDimension * 100;
         let heightPercent = r.height / this.renderDimension * 100;
-        let rect = (<div className={`histogramboxprimitives-${classExt}`} onPointerDown={(e: React.PointerEvent) => { if (e.button == 0) tapHandler() }}
+        let rect = (<div className={`histogramboxprimitives-${classExt}`} onPointerDown={(e: React.PointerEvent) => { if (e.button === 0) tapHandler() }}
             style={{
-                borderBottomStyle: barAxis == 1 ? "none" : "solid",
-                borderLeftStyle: barAxis == 0 ? "none" : "solid",
+                borderBottomStyle: barAxis === 1 ? "none" : "solid",
+                borderLeftStyle: barAxis === 0 ? "none" : "solid",
                 width: `${widthPercent}%`,
                 height: `${heightPercent}%`,
                 background: color ? `${LABColor.RGBtoHexString(color)}` : ""
diff --git a/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx
index 93b237deb..dd62e9146 100644
--- a/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx
+++ b/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx
@@ -34,7 +34,7 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive
         let vb = this.props.HistoBox.VisualBinRanges;
         if (!vb.length || !sc.Initialized)
             return (null);
-        let dim = (axis == 0 ? this.props.HistoBox.PanelWidth : this.props.HistoBox.PanelHeight) / ((axis == 0 && vb[axis] instanceof NominalVisualBinRange) ?
+        let dim = (axis === 0 ? this.props.HistoBox.PanelWidth : this.props.HistoBox.PanelHeight) / ((axis === 0 && vb[axis] instanceof NominalVisualBinRange) ?
             (12 + 5) : //  (<number>FontStyles.AxisLabel.fontSize + 5)));
             sc.MaxLabelSizes[axis].coords[axis] + 5);
 
@@ -47,17 +47,17 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive
                 let xStart = (axis === 0 ? r.xFrom + (r.xTo - r.xFrom) / 2.0 : r.xFrom - 10 - textWidth);
                 let yStart = (axis === 1 ? r.yFrom - textHeight / 2 : r.yFrom);
 
-                if (axis == 0 && vb[axis] instanceof NominalVisualBinRange) {
+                if (axis === 0 && vb[axis] instanceof NominalVisualBinRange) {
                     let space = (r.xTo - r.xFrom) / sc.RenderDimension * this.props.HistoBox.PanelWidth;
                     xStart += Math.max(textWidth / 2, (1 - textWidth / space) * textWidth / 2) - textHeight / 2;
                 }
 
-                let xPercent = axis == 1 ? `${xStart}px` : `${xStart / sc.RenderDimension * 100}%`
-                let yPercent = axis == 0 ? `${this.props.HistoBox.PanelHeight - sc.BottomOffset - textHeight}px` : `${yStart / sc.RenderDimension * 100}%`
+                let xPercent = axis === 1 ? `${xStart}px` : `${xStart / sc.RenderDimension * 100}%`
+                let yPercent = axis === 0 ? `${this.props.HistoBox.PanelHeight - sc.BottomOffset - textHeight}px` : `${yStart / sc.RenderDimension * 100}%`
 
                 prims.push(
                     <div className="histogramLabelPrimitives-placer" key={DashUtils.GenerateGuid()} style={{ transform: `translate(${xPercent}, ${yPercent})` }}>
-                        <div className="histogramLabelPrimitives-gridlabel" style={{ transform: `rotate(${axis == 0 ? sc.LabelAngle : 0}rad)` }}>
+                        <div className="histogramLabelPrimitives-gridlabel" style={{ transform: `rotate(${axis === 0 ? sc.LabelAngle : 0}rad)` }}>
                             {label}
                         </div>
                     </div>
diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts
index 3e72a50ae..ba6fe2ad5 100644
--- a/src/client/northstar/manager/Gateway.ts
+++ b/src/client/northstar/manager/Gateway.ts
@@ -49,7 +49,7 @@ export class Gateway {
 
     public async Compile(data: any): Promise<CompileResults | undefined> {
         const json = await this.MakePostJsonRequest("compile", data);
-        if (json != null) {
+        if (json !== null) {
             const cr = CompileResults.fromJS(json);
             return cr;
         }
@@ -108,7 +108,7 @@ export class Gateway {
 
     public async StartOperation(data: any): Promise<OperationReference | undefined> {
         const json = await this.MakePostJsonRequest("operation", data);
-        if (json != null) {
+        if (json !== null) {
             const or = OperationReference.fromJS(json);
             return or;
         }
@@ -116,7 +116,7 @@ export class Gateway {
 
     public async GetResult(data: any): Promise<Result | undefined> {
         const json = await this.MakePostJsonRequest("result", data);
-        if (json != null) {
+        if (json !== null) {
             const res = Result.fromJS(json);
             return res;
         }
@@ -163,7 +163,7 @@ export class Gateway {
 
     public static ConstructUrl(appendix: string): string {
         let base = Settings.Instance.ServerUrl;
-        if (base.slice(-1) == "/") {
+        if (base.slice(-1) === "/") {
             base = base.slice(0, -1);
         }
         let url = base + "/" + Settings.Instance.ServerApiPath + "/" + appendix;
diff --git a/src/client/northstar/model/ModelExtensions.ts b/src/client/northstar/model/ModelExtensions.ts
index 9fcba7f1c..e4bf77ed8 100644
--- a/src/client/northstar/model/ModelExtensions.ts
+++ b/src/client/northstar/model/ModelExtensions.ts
@@ -3,23 +3,23 @@ import { Utils } from '../utils/Utils'
 
 import { FilterModel } from '../core/filter/FilterModel'
 
-(SingleDimensionAggregateParameters as any).prototype["Equals"] = function (other: Object) {
+(SingleDimensionAggregateParameters as any).prototype.Equals = function (other: Object) {
     if (!Utils.EqualityHelper(this, other)) return false;
     if (!Utils.EqualityHelper((this as SingleDimensionAggregateParameters).attributeParameters!,
         (other as SingleDimensionAggregateParameters).attributeParameters!)) return false;
-    if (!((this as SingleDimensionAggregateParameters).attributeParameters! as any)["Equals"]((other as SingleDimensionAggregateParameters).attributeParameters)) return false;
+    if (!((this as SingleDimensionAggregateParameters).attributeParameters! as any).Equals((other as SingleDimensionAggregateParameters).attributeParameters)) return false;
     return true;
 }
 
 {
-    (AttributeParameters as any).prototype["Equals"] = function (other: AttributeParameters) {
+    (AttributeParameters as any).prototype.Equals = function (other: AttributeParameters) {
         return (<any>this).constructor.name === (<any>other).constructor.name &&
             this.rawName === other.rawName;
     }
 }
 
 {
-    (Solution as any).prototype["Equals"] = function (other: Object) {
+    (Solution as any).prototype.Equals = function (other: Object) {
         if (!Utils.EqualityHelper(this, other)) return false;
         if ((this as Solution).solutionId !== (other as Solution).solutionId) return false;
         return true;
@@ -27,11 +27,11 @@ import { FilterModel } from '../core/filter/FilterModel'
 }
 
 {
-    (MarginAggregateParameters as any).prototype["Equals"] = function (other: Object) {
+    (MarginAggregateParameters as any).prototype.Equals = function (other: Object) {
         if (!Utils.EqualityHelper(this, other)) return false;
         if (!Utils.EqualityHelper((this as SingleDimensionAggregateParameters).attributeParameters!,
             (other as SingleDimensionAggregateParameters).attributeParameters!)) return false;
-        if (!((this as SingleDimensionAggregateParameters).attributeParameters! as any)["Equals"]((other as SingleDimensionAggregateParameters).attributeParameters!)) return false;
+        if (!((this as SingleDimensionAggregateParameters).attributeParameters! as any).Equals((other as SingleDimensionAggregateParameters).attributeParameters!)) return false;
 
         if ((this as MarginAggregateParameters).aggregateFunction !== (other as MarginAggregateParameters).aggregateFunction) return false;
         return true;
@@ -39,7 +39,7 @@ import { FilterModel } from '../core/filter/FilterModel'
 }
 
 {
-    (Brush as any).prototype["Equals"] = function (other: Object) {
+    (Brush as any).prototype.Equals = function (other: Object) {
         if (!Utils.EqualityHelper(this, other)) return false;
         if ((this as Brush).brushEnum !== (other as Brush).brushEnum) return false;
         if ((this as Brush).brushIndex !== (other as Brush).brushIndex) return false;
diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts
index d0711fb69..1a58e6180 100644
--- a/src/client/northstar/model/ModelHelpers.ts
+++ b/src/client/northstar/model/ModelHelpers.ts
@@ -16,7 +16,7 @@ export class ModelHelpers {
     public static CreateAggregateKey(distinctAttributeParameters: AttributeParameters | undefined, atm: AttributeTransformationModel, histogramResult: HistogramResult,
         brushIndex: number, aggParameters?: SingleDimensionAggregateParameters): AggregateKey {
         {
-            if (aggParameters == undefined) {
+            if (aggParameters === undefined) {
                 aggParameters = ModelHelpers.GetAggregateParameter(distinctAttributeParameters, atm);
             }
             else {
@@ -146,7 +146,7 @@ export class ModelHelpers {
     }
 
     public static GetAggregateResult(bin: Bin, aggregateKey: AggregateKey) {
-        if (aggregateKey.aggregateParameterIndex == -1 || aggregateKey.brushIndex == -1) {
+        if (aggregateKey.aggregateParameterIndex === -1 || aggregateKey.brushIndex === -1) {
             return null;
         }
         return bin.aggregateResults![aggregateKey.aggregateParameterIndex! * bin.ySize! + aggregateKey.brushIndex!];
@@ -157,9 +157,9 @@ export class ModelHelpers {
         var ret = new Array<AggregateFunction>();
         ret.push(AggregateFunction.None);
         ret.push(AggregateFunction.Count);
-        if (atm.AttributeModel.DataType == DataType.Float ||
-            atm.AttributeModel.DataType == DataType.Double ||
-            atm.AttributeModel.DataType == DataType.Int) {
+        if (atm.AttributeModel.DataType === DataType.Float ||
+            atm.AttributeModel.DataType === DataType.Double ||
+            atm.AttributeModel.DataType === DataType.Int) {
             ret.push(AggregateFunction.Avg);
             ret.push(AggregateFunction.Sum);
         }
diff --git a/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts b/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts
index 9313fb1a7..f5872aa4c 100644
--- a/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts
+++ b/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts
@@ -39,24 +39,24 @@ export class DateTimeVisualBinRange extends VisualBinRange {
 
     public GetLabel(value: number): string {
         var dt = DateTimeVisualBinRange.TicksToDate(value);
-        if (this.DataBinRange.step!.dateTimeStepGranularity == DateTimeStepGranularity.Second ||
-            this.DataBinRange.step!.dateTimeStepGranularity == DateTimeStepGranularity.Minute) {
+        if (this.DataBinRange.step!.dateTimeStepGranularity === DateTimeStepGranularity.Second ||
+            this.DataBinRange.step!.dateTimeStepGranularity === DateTimeStepGranularity.Minute) {
             return ("" + this.pad(dt.getMinutes(), 2) + ":" + this.pad(dt.getSeconds(), 2));
             //return dt.ToString("mm:ss");
         }
-        else if (this.DataBinRange.step!.dateTimeStepGranularity == DateTimeStepGranularity.Hour) {
+        else if (this.DataBinRange.step!.dateTimeStepGranularity === DateTimeStepGranularity.Hour) {
             return (this.pad(dt.getHours(), 2) + ":" + this.pad(dt.getMinutes(), 2));
             //return dt.ToString("HH:mm");
         }
-        else if (this.DataBinRange.step!.dateTimeStepGranularity == DateTimeStepGranularity.Day) {
+        else if (this.DataBinRange.step!.dateTimeStepGranularity === DateTimeStepGranularity.Day) {
             return ((dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear());
             //return dt.ToString("MM/dd/yyyy");
         }
-        else if (this.DataBinRange.step!.dateTimeStepGranularity == DateTimeStepGranularity.Month) {
+        else if (this.DataBinRange.step!.dateTimeStepGranularity === DateTimeStepGranularity.Month) {
             //return dt.ToString("MM/yyyy");
             return ((dt.getMonth() + 1) + "/" + dt.getFullYear());
         }
-        else if (this.DataBinRange.step!.dateTimeStepGranularity == DateTimeStepGranularity.Year) {
+        else if (this.DataBinRange.step!.dateTimeStepGranularity === DateTimeStepGranularity.Year) {
             return "" + dt.getFullYear();
         }
         return "n/a";
@@ -82,22 +82,22 @@ export class DateTimeVisualBinRange extends VisualBinRange {
     public static AddToDateTimeTicks(ticks: number, dateTimeStep: DateTimeStep): number {
         var copiedDate = DateTimeVisualBinRange.TicksToDate(ticks);
         var returnDate: Date = new Date(Date.now());
-        if (dateTimeStep.dateTimeStepGranularity == DateTimeStepGranularity.Second) {
+        if (dateTimeStep.dateTimeStepGranularity === DateTimeStepGranularity.Second) {
             returnDate = new Date(copiedDate.setSeconds(copiedDate.getSeconds() + dateTimeStep.dateTimeStepValue!));
         }
-        else if (dateTimeStep.dateTimeStepGranularity == DateTimeStepGranularity.Minute) {
+        else if (dateTimeStep.dateTimeStepGranularity === DateTimeStepGranularity.Minute) {
             returnDate = new Date(copiedDate.setMinutes(copiedDate.getMinutes() + dateTimeStep.dateTimeStepValue!));
         }
-        else if (dateTimeStep.dateTimeStepGranularity == DateTimeStepGranularity.Hour) {
+        else if (dateTimeStep.dateTimeStepGranularity === DateTimeStepGranularity.Hour) {
             returnDate = new Date(copiedDate.setHours(copiedDate.getHours() + dateTimeStep.dateTimeStepValue!));
         }
-        else if (dateTimeStep.dateTimeStepGranularity == DateTimeStepGranularity.Day) {
+        else if (dateTimeStep.dateTimeStepGranularity === DateTimeStepGranularity.Day) {
             returnDate = new Date(copiedDate.setDate(copiedDate.getDate() + dateTimeStep.dateTimeStepValue!));
         }
-        else if (dateTimeStep.dateTimeStepGranularity == DateTimeStepGranularity.Month) {
+        else if (dateTimeStep.dateTimeStepGranularity === DateTimeStepGranularity.Month) {
             returnDate = new Date(copiedDate.setMonth(copiedDate.getMonth() + dateTimeStep.dateTimeStepValue!));
         }
-        else if (dateTimeStep.dateTimeStepGranularity == DateTimeStepGranularity.Year) {
+        else if (dateTimeStep.dateTimeStepGranularity === DateTimeStepGranularity.Year) {
             returnDate = new Date(copiedDate.setFullYear(copiedDate.getFullYear() + dateTimeStep.dateTimeStepValue!));
         }
         return DateTimeVisualBinRange.DateToTicks(returnDate);
diff --git a/src/client/northstar/model/binRanges/VisualBinRange.ts b/src/client/northstar/model/binRanges/VisualBinRange.ts
index f53008f9a..a0766e494 100644
--- a/src/client/northstar/model/binRanges/VisualBinRange.ts
+++ b/src/client/northstar/model/binRanges/VisualBinRange.ts
@@ -2,10 +2,6 @@ import { BinLabel } from '../../model/idea/idea'
 
 export abstract class VisualBinRange {
 
-    constructor() {
-
-    }
-
     public abstract AddStep(value: number): number;
 
     public abstract GetValueFromIndex(index: number): number;
diff --git a/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts b/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
index 53d585bb4..63ee61909 100644
--- a/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
+++ b/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
@@ -39,8 +39,7 @@ export class VisualBinRangeHelper {
             var aggregateKey = ModelHelpers.CreateAggregateKey(distinctAttributeParameters, attr, histoResult, ModelHelpers.AllBrushIndex(histoResult));
             var minValue = Number.MAX_VALUE;
             var maxValue = Number.MIN_VALUE;
-            for (var b = 0; b < histoResult.brushes!.length; b++) {
-                var brush = histoResult.brushes![b];
+            for (const brush of histoResult.brushes!) {
                 aggregateKey.brushIndex = brush.brushIndex;
                 for (var key in histoResult.bins) {
                     if (histoResult.bins.hasOwnProperty(key)) {
@@ -56,12 +55,12 @@ export class VisualBinRangeHelper {
 
             let visualBinRange = QuantitativeVisualBinRange.Initialize(minValue, maxValue, 10, false);
 
-            if (chartType == ChartType.HorizontalBar || chartType == ChartType.VerticalBar) {
+            if (chartType === ChartType.HorizontalBar || chartType === ChartType.VerticalBar) {
                 visualBinRange = QuantitativeVisualBinRange.Initialize(Math.min(0, minValue),
                     Math.max(0, (visualBinRange as QuantitativeVisualBinRange).DataBinRange.maxValue!),
                     SETTINGS_X_BINS, false);
             }
-            else if (chartType == ChartType.SinglePoint) {
+            else if (chartType === ChartType.SinglePoint) {
                 visualBinRange = QuantitativeVisualBinRange.Initialize(Math.min(0, minValue), Math.max(0, maxValue),
                     SETTINGS_X_BINS, false);
             }
diff --git a/src/client/northstar/model/idea/MetricTypeMapping.ts b/src/client/northstar/model/idea/MetricTypeMapping.ts
index 11e0c871a..e9759cf16 100644
--- a/src/client/northstar/model/idea/MetricTypeMapping.ts
+++ b/src/client/northstar/model/idea/MetricTypeMapping.ts
@@ -5,20 +5,20 @@ import { Dictionary } from 'typescript-collections';
 export class MetricTypeMapping {
 
     public static GetMetricInterpretation(metricType: MetricType): MetricInterpretation {
-        if (metricType == MetricType.Accuracy ||
-            metricType == MetricType.F1 ||
-            metricType == MetricType.F1Macro ||
-            metricType == MetricType.F1Micro ||
-            metricType == MetricType.JaccardSimilarityScore ||
-            metricType == MetricType.ObjectDetectionAveragePrecision ||
-            metricType == MetricType.Precision ||
-            metricType == MetricType.PrecisionAtTopK ||
-            metricType == MetricType.NormalizedMutualInformation ||
-            metricType == MetricType.Recall ||
-            metricType == MetricType.RocAucMacro ||
-            metricType == MetricType.RocAuc ||
-            metricType == MetricType.RocAucMicro ||
-            metricType == MetricType.RSquared) {
+        if (metricType === MetricType.Accuracy ||
+            metricType === MetricType.F1 ||
+            metricType === MetricType.F1Macro ||
+            metricType === MetricType.F1Micro ||
+            metricType === MetricType.JaccardSimilarityScore ||
+            metricType === MetricType.ObjectDetectionAveragePrecision ||
+            metricType === MetricType.Precision ||
+            metricType === MetricType.PrecisionAtTopK ||
+            metricType === MetricType.NormalizedMutualInformation ||
+            metricType === MetricType.Recall ||
+            metricType === MetricType.RocAucMacro ||
+            metricType === MetricType.RocAuc ||
+            metricType === MetricType.RocAucMicro ||
+            metricType === MetricType.RSquared) {
             return MetricInterpretation.HigherIsBetter;
         }
         return MetricInterpretation.LowerIsBetter;
diff --git a/src/client/northstar/operations/BaseOperation.ts b/src/client/northstar/operations/BaseOperation.ts
index f545b2c58..a14337763 100644
--- a/src/client/northstar/operations/BaseOperation.ts
+++ b/src/client/northstar/operations/BaseOperation.ts
@@ -29,11 +29,11 @@ export abstract class BaseOperation {
         // let filterModels: FilterModel[] = [];
         // return FilterModel.GetFilterModelsRecursive(this, new Set<GraphNode<BaseOperationViewModel, FilterLinkViewModel>>(), filterModels, true)
         // if (this.OverridingFilters.length > 0) {
-        //     return "(" + this.OverridingFilters.filter(fm => fm != null).map(fm => fm.ToPythonString()).join(" || ") + ")";
+        //     return "(" + this.OverridingFilters.filter(fm => fm !== null).map(fm => fm.ToPythonString()).join(" || ") + ")";
         // }
         // let rdg = MainManager.Instance.MainViewModel.FilterReverseDependencyGraph;
         // let sliceModel = this.TypedViewModel.IncomingSliceModel;
-        // if (sliceModel != null && sliceModel.Source != null && instanceOfIBaseFilterProvider(sliceModel.Source) && rdg.has(sliceModel.Source)) {
+        // if (sliceModel !== null && sliceModel.Source !== null && instanceOfIBaseFilterProvider(sliceModel.Source) && rdg.has(sliceModel.Source)) {
         //     let filterModels = sliceModel.Source.FilterModels.map(f => f);
         //     return FilterModel.GetFilterModelsRecursive(rdg.get(sliceModel.Source), new Set<GraphNode<BaseOperationViewModel, FilterLinkViewModel>>(), filterModels, false);
         // }
@@ -99,8 +99,8 @@ export abstract class BaseOperation {
                     if (result instanceof ErrorResult) {
                         throw new Error((result as ErrorResult).message);
                     }
-                    if (this.RequestSalt == pollPromise.RequestSalt) {
-                        if (result && (!this.Result || this.Result.progress != result.progress)) {
+                    if (this.RequestSalt === pollPromise.RequestSalt) {
+                        if (result && (!this.Result || this.Result.progress !== result.progress)) {
                             /*if (operationViewModel.Result !== null && operationViewModel.Result !== undefined) {
                                 let t1 = performance.now();
                                 console.log((t1 - start) + " milliseconds.");
diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts
index e63de1632..7f48d1629 100644
--- a/src/client/northstar/operations/HistogramOperation.ts
+++ b/src/client/northstar/operations/HistogramOperation.ts
@@ -67,7 +67,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons
         let brushes: string[] = [];
         this.BrushLinks.map(brushLink => {
             let brushHistogram = brushLink.b.GetT(KeyStore.Data, HistogramField);
-            if (brushHistogram && brushHistogram != FieldWaiting) {
+            if (brushHistogram && brushHistogram !== FieldWaiting) {
                 let filterModels: FilterModel[] = [];
                 brushes.push(FilterModel.GetFilterModelsRecursive(brushHistogram.Data, new Set<IBaseFilterProvider>(), filterModels, false));
             }
diff --git a/src/client/northstar/utils/ArrayUtil.ts b/src/client/northstar/utils/ArrayUtil.ts
index f35c98317..a52ca6d96 100644
--- a/src/client/northstar/utils/ArrayUtil.ts
+++ b/src/client/northstar/utils/ArrayUtil.ts
@@ -7,14 +7,14 @@ export class ArrayUtil {
             return false;
         }
         let isComplex = typeof arr1[0] === "object";
-        for (let i = 0; i < arr1.length; i++) {
-            if (isComplex && "Equals" in arr1[i]) {
-                if (arr1[i].Equals(arr2)) {
+        for (const ele of arr1) {
+            if (isComplex && "Equals" in ele) {
+                if (ele.Equals(arr2)) {
                     return true;
                 }
             }
             else {
-                if (arr1[i] === arr2) {
+                if (ele === arr2) {
                     return true;
                 }
             }
@@ -63,9 +63,9 @@ export class ArrayUtil {
 
     public static Distinct(arr: any[]): any[] {
         let ret = [];
-        for (let i = 0; i < arr.length; i++) {
-            if (!ArrayUtil.Contains(ret, arr[i])) {
-                ret.push(arr[i]);
+        for (const ele of arr) {
+            if (!ArrayUtil.Contains(ret, ele)) {
+                ret.push(ele);
             }
         }
         return ret;
diff --git a/src/client/northstar/utils/GeometryUtil.ts b/src/client/northstar/utils/GeometryUtil.ts
index d5f3ba631..6d8acea20 100644
--- a/src/client/northstar/utils/GeometryUtil.ts
+++ b/src/client/northstar/utils/GeometryUtil.ts
@@ -85,7 +85,7 @@ export class GeometryUtil {
     //         var xi = vs[i].x, yi = vs[i].y;
     //         var xj = vs[j].x, yj = vs[j].y;
 
-    //         var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
+    //         var intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
     //         if (intersect) 
     //            inside = !inside;
     //     }
diff --git a/src/client/northstar/utils/MathUtil.ts b/src/client/northstar/utils/MathUtil.ts
index bb7e73871..7aa255096 100644
--- a/src/client/northstar/utils/MathUtil.ts
+++ b/src/client/northstar/utils/MathUtil.ts
@@ -93,7 +93,7 @@ export class MathUtil {
     public static DistToLineSegment(v: PIXIPoint, w: PIXIPoint, p: PIXIPoint) {
         // Return minimum distance between line segment vw and point p
         var l2 = MathUtil.DistSquared(v, w);  // i.e. |w-v|^2 -  avoid a sqrt
-        if (l2 == 0.0) return MathUtil.Dist(p, v);   // v == w case
+        if (l2 === 0.0) return MathUtil.Dist(p, v);   // v === w case
         // Consider the line extending the segment, parameterized as v + t (w - v).
         // We find projection of point p onto the line. 
         // It falls where t = [(p-v) . (w-v)] / |w-v|^2
@@ -117,7 +117,7 @@ export class MathUtil {
         var b2 = ps2.x - pe2.x;
 
         var delta = a1 * b2 - a2 * b1;
-        if (delta == 0) {
+        if (delta === 0) {
             return undefined;
         }
         var c2 = a2 * ps2.x + b2 * ps2.y;
@@ -147,19 +147,19 @@ export class MathUtil {
         var ret = new Array<PIXIPoint>();
         var dist = this.Dist(lineFrom, lineTo)
         var inter = this.LineSegmentIntersection(lineFrom, lineTo, r1, r2);
-        if (inter != null && this.PointInPIXIRectangle(inter, rect) &&
+        if (inter && this.PointInPIXIRectangle(inter, rect) &&
             this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
             ret.push(inter);
         inter = this.LineSegmentIntersection(lineFrom, lineTo, r2, r3);
-        if (inter != null && this.PointInPIXIRectangle(inter, rect) &&
+        if (inter && this.PointInPIXIRectangle(inter, rect) &&
             this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
             ret.push(inter);
         inter = this.LineSegmentIntersection(lineFrom, lineTo, r3, r4);
-        if (inter != null && this.PointInPIXIRectangle(inter, rect) &&
+        if (inter && this.PointInPIXIRectangle(inter, rect) &&
             this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
             ret.push(inter);
         inter = this.LineSegmentIntersection(lineFrom, lineTo, r4, r1);
-        if (inter != null && this.PointInPIXIRectangle(inter, rect) &&
+        if (inter && this.PointInPIXIRectangle(inter, rect) &&
             this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
             ret.push(inter);
         return ret;
diff --git a/src/client/northstar/utils/SizeConverter.ts b/src/client/northstar/utils/SizeConverter.ts
index bb91ed4a7..b5c4a16ab 100644
--- a/src/client/northstar/utils/SizeConverter.ts
+++ b/src/client/northstar/utils/SizeConverter.ts
@@ -54,7 +54,7 @@ export class SizeConverter {
     }
 
     public DataToScreenNormalizedRange(dataValue: number, normalization: number, axis: number, binBrushMaxAxis: number) {
-        var value = normalization != 1 - axis || binBrushMaxAxis == 0 ? dataValue : (dataValue - 0) / (binBrushMaxAxis - 0) * this.DataRanges[axis];
+        var value = normalization !== 1 - axis || binBrushMaxAxis === 0 ? dataValue : (dataValue - 0) / (binBrushMaxAxis - 0) * this.DataRanges[axis];
         var from = this.DataToScreenCoord(Math.min(0, value), axis);
         var to = this.DataToScreenCoord(Math.max(0, value), axis);
         return [from, value, to];
@@ -85,7 +85,7 @@ export class SizeConverter {
         return flip ? (this.RenderDimension) - retY : retY;
     }
     public DataToScreenCoord(v: number, axis: number) {
-        if (axis == 0)
+        if (axis === 0)
             return this.DataToScreenX(v);
         return this.DataToScreenY(v);
     }
diff --git a/src/client/northstar/utils/Utils.ts b/src/client/northstar/utils/Utils.ts
index b35dce820..c96b4cbd9 100644
--- a/src/client/northstar/utils/Utils.ts
+++ b/src/client/northstar/utils/Utils.ts
@@ -27,17 +27,17 @@ export class Utils {
 
     public static isBaseBrushable<T>(obj: Object): obj is IBaseBrushable<T> {
         let typed = <IBaseBrushable<T>>obj;
-        return typed != null && typed.BrusherModels !== undefined;
+        return typed !== null && typed.BrusherModels !== undefined;
     }
 
     public static isBaseFilterProvider(obj: Object): obj is IBaseFilterProvider {
         let typed = <IBaseFilterProvider>obj;
-        return typed != null && typed.FilterModels !== undefined;
+        return typed !== null && typed.FilterModels !== undefined;
     }
 
     public static isBaseFilterConsumer(obj: Object): obj is IBaseFilterConsumer {
         let typed = <IBaseFilterConsumer>obj;
-        return typed != null && typed.FilterOperand !== undefined;
+        return typed !== null && typed.FilterOperand !== undefined;
     }
 
     public static EncodeQueryData(data: any): string {
@@ -63,9 +63,9 @@ export class Utils {
     public static GetQueryVariable(variable: string) {
         let query = window.location.search.substring(1);
         let vars = query.split("&");
-        for (let i = 0; i < vars.length; i++) {
-            let pair = vars[i].split("=");
-            if (decodeURIComponent(pair[0]) == variable) {
+        for (const variable of vars) {
+            let pair = variable.split("=");
+            if (decodeURIComponent(pair[0]) === variable) {
                 return decodeURIComponent(pair[1]);
             }
         }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 11bf24505..1bb00a3fc 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -60,10 +60,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             if (text[0] === '#') {
                 let command = text.slice(1, text.length);
                 this._fieldKey = new Key(command)
-                // if (command == "Title" || command == "title") {
+                // if (command === "Title" || command === "title") {
                 //     this._fieldKey = KeyStore.Title;
                 // }
-                // else if (command == "Width" || command == "width") {
+                // else if (command === "Width" || command === "width") {
                 //     this._fieldKey = KeyStore.Width;
                 // }
                 this._title = "changed"
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 33759d38a..74f868c11 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -62,7 +62,7 @@ export class Main extends React.Component {
 
     @computed private get mainContainer(): Document | undefined {
         let doc = this.userDocument.GetT(KeyStore.ActiveWorkspace, Document);
-        return doc == FieldWaiting ? undefined : doc;
+        return doc === FieldWaiting ? undefined : doc;
     }
 
     private set mainContainer(doc: Document | undefined) {
@@ -84,7 +84,7 @@ export class Main extends React.Component {
         configure({ enforceActions: "observed" });
         if (window.location.pathname !== RouteStore.home) {
             let pathname = window.location.pathname.split("/");
-            if (pathname.length > 1 && pathname[pathname.length - 2] == 'doc') {
+            if (pathname.length > 1 && pathname[pathname.length - 2] === 'doc') {
                 CurrentUserUtils.MainDocId = pathname[pathname.length - 1];
             }
         };
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index ee752a2ca..7a5ab6e3c 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -65,13 +65,13 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
         let data = documentToAdd.GetList<Document>(KeyStore.Data, []);
-        for (let i = 0; i < data.length; i++) {
-            if (this.createsCycle(data[i], containerDocument))
+        for (const doc of data) {
+            if (this.createsCycle(doc, containerDocument))
                 return true;
         }
         let annots = documentToAdd.GetList<Document>(KeyStore.Annotations, []);
-        for (let i = 0; i < annots.length; i++) {
-            if (this.createsCycle(annots[i], containerDocument))
+        for (const annot of annots) {
+            if (this.createsCycle(annot, containerDocument))
                 return true;
         }
         for (let containerProto: FieldValue<Document> = containerDocument; containerProto && containerProto !== FieldWaiting; containerProto = containerProto.GetPrototype()) {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 1b0ad0bee..2380709d2 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -101,12 +101,12 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             newRow.addChild(newContentItem, undefined, true);
             newRow.addChild(collayout, 0, true);
 
-            collayout.config["width"] = 50;
-            newContentItem.config["width"] = 50;
+            collayout.config.width = 50;
+            newContentItem.config.width = 50;
         }
         if (minimize) {
-            newContentItem.config["width"] = 10;
-            newContentItem.config["height"] = 10;
+            newContentItem.config.width = 10;
+            newContentItem.config.height = 10;
         }
         newContentItem.callDownwards('_$init');
         this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
@@ -124,7 +124,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             }
             else {
-                if (config == JSON.stringify(this._goldenLayout.toConfig()))
+                if (config === JSON.stringify(this._goldenLayout.toConfig()))
                     return;
                 try {
                     this._goldenLayout.unbind('itemDropped', this.itemDropped);
@@ -154,7 +154,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             reaction(
                 () => this.props.Document.GetText(KeyStore.Data, ""),
                 () => {
-                    if (!this._goldenLayout || this._ignoreStateChange != JSON.stringify(this._goldenLayout.toConfig())) {
+                    if (!this._goldenLayout || this._ignoreStateChange !== JSON.stringify(this._goldenLayout.toConfig())) {
                         setTimeout(() => this.setupGoldenLayout(), 1);
                     }
                     this._ignoreStateChange = "";
@@ -193,7 +193,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         var className = (e.target as any).className;
-        if ((className == "lm_title" || className == "lm_tab lm_active") && (e.ctrlKey || e.altKey)) {
+        if ((className === "lm_title" || className === "lm_tab lm_active") && (e.ctrlKey || e.altKey)) {
             e.stopPropagation();
             e.preventDefault();
             let docid = (e.target as any).DashDocId;
@@ -209,7 +209,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                         })
             }));
         }
-        if (className == "lm_drag_handle" || className == "lm_close" || className == "lm_maximise" || className == "lm_minimise" || className == "lm_close_tab") {
+        if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") {
             this._flush = true;
         }
         if (this.props.active()) {
@@ -227,12 +227,12 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         this.stateChanged();
     }
     tabCreated = (tab: any) => {
-        if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type != "stack") {
-            if (tab.titleElement[0].textContent.indexOf("-waiting") != -1) {
+        if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
+            if (tab.titleElement[0].textContent.indexOf("-waiting") !== -1) {
                 Server.GetField(tab.contentItem.config.props.documentId, action((f: Opt<Field>) => {
-                    if (f != undefined && f instanceof Document) {
+                    if (f !== undefined && f instanceof Document) {
                         f.GetTAsync(KeyStore.Title, TextField, (tfield) => {
-                            if (tfield != undefined) {
+                            if (tfield !== undefined) {
                                 tab.titleElement[0].textContent = f.Title;
                             }
                         })
@@ -296,9 +296,9 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         Server.GetField(this.props.documentId, action((f: Opt<Field>) => this._document = f as Document));
     }
 
-    private _nativeWidth = () => { return this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth); }
-    private _nativeHeight = () => { return this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight); }
-    private _contentScaling = () => { return this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth); }
+    private _nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth)
+    private _nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight)
+    private _contentScaling = () => this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth)
 
     ScreenToLocalTransform = () => {
         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 14ed70b8c..1f2e71f6e 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -33,7 +33,7 @@ export class CollectionPDFView extends React.Component<CollectionViewProps> {
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } });
         }
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9dade94f1..3817d5333 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -151,7 +151,7 @@ export class CollectionSchemaView extends CollectionViewBase {
             }),
             style: {
                 background: rowInfo.index === this._selectedIndex ? "lightGray" : "white",
-                //color: rowInfo.index == this._selectedIndex ? "white" : "black"
+                //color: rowInfo.index === this._selectedIndex ? "white" : "black"
             }
         };
     }
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 3ab6db5ef..afadfeefb 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -61,7 +61,7 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
     @action
     updateTimecode = () => {
         if (this._player) {
-            if ((this._player as any).AHackBecauseSomethingResetsTheVideoToZero != -1) {
+            if ((this._player as any).AHackBecauseSomethingResetsTheVideoToZero !== -1) {
                 this._player.currentTime = (this._player as any).AHackBecauseSomethingResetsTheVideoToZero;
                 (this._player as any).AHackBecauseSomethingResetsTheVideoToZero = -1;
             } else {
@@ -103,7 +103,7 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "VideoOptions", event: () => { } });
         }
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 5b4caf58d..1b0cfd57b 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -28,7 +28,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document.Id != CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        if (!e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) })
             ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) })
             ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) })
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index b4784ae9c..3af3c5d63 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -91,11 +91,11 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
             if (sourceDoc) runInAction(() => {
                 let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
-                if (srcTarg && srcTarg != FieldWaiting) {
+                if (srcTarg && srcTarg !== FieldWaiting) {
                     let linkDocs = srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]);
                     linkDocs.map(linkDoc => {
                         let targDoc = linkDoc.GetT(KeyStore.LinkedToDocs, Document);
-                        if (targDoc && targDoc != FieldWaiting) {
+                        if (targDoc && targDoc !== FieldWaiting) {
                             let dropdoc = targDoc.MakeDelegate();
                             de.data.droppedDocuments.push(dropdoc);
                             this.props.addDocument(dropdoc, false);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 19227f5e0..52e40d64a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -176,8 +176,8 @@ export class CollectionFreeFormView extends CollectionViewBase {
             e.stopPropagation();
             e.preventDefault();
         } else {
-            // if (modes[e.deltaMode] == 'pixels') coefficient = 50;
-            // else if (modes[e.deltaMode] == 'lines') coefficient = 1000; // This should correspond to line-height??
+            // if (modes[e.deltaMode] === 'pixels') coefficient = 50;
+            // else if (modes[e.deltaMode] === 'lines') coefficient = 1000; // This should correspond to line-height??
             let transform = this.getTransform();
 
             let deltaScale = (1 - (e.deltaY / coefficient));
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 7022fd972..704db1d4a 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -48,7 +48,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
 
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.buttons == 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) {
+        if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) {
             this._downX = this._lastX = e.pageX;
             this._downY = this._lastY = e.pageY;
             this._used = false;
@@ -63,7 +63,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         this._lastX = e.pageX;
         this._lastY = e.pageY;
         if (!e.cancelBubble) {
-            if (!this._used && e.buttons == 1 && !e.altKey && !e.metaKey &&
+            if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey &&
                 (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) {
                 this._visible = true;
             }
@@ -99,15 +99,15 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
 
     @action
     marqueeCommand = (e: KeyboardEvent) => {
-        if (e.key == "Backspace" || e.key == "Delete") {
+        if (e.key === "Backspace" || e.key === "Delete") {
             this.marqueeSelect().map(d => this.props.removeDocument(d));
             let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
-            if (ink && ink != FieldWaiting) {
+            if (ink && ink !== FieldWaiting) {
                 this.marqueeInkDelete(ink.Data);
             }
             this.cleanupInteractions();
         }
-        if (e.key == "c") {
+        if (e.key === "c") {
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
                 this.props.removeDocument(d);
@@ -118,7 +118,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 return d;
             });
             let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
-            let inkData = ink && ink != FieldWaiting ? ink.Data : undefined;
+            let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined;
             //setTimeout(() => {
             let newCollection = Documents.FreeformDocument(selected, {
                 x: bounds.left,
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
index 93c98f7b0..599461f85 100644
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
+++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
@@ -33,7 +33,7 @@ export class PreviewCursor extends React.Component<PreviewCursorProps>  {
 
     @action
     onPointerDown = (e: React.PointerEvent) => {
-        if (e.button == 0 && this.props.container.props.active()) {
+        if (e.button === 0 && this.props.container.props.active()) {
             document.removeEventListener("keypress", this.onKeyPress, false);
             this._showOnUp = true;
             this.DownX = e.pageX;
diff --git a/src/client/views/nodes/Annotation.tsx b/src/client/views/nodes/Annotation.tsx
index a2c7be1a8..e4f17940c 100644
--- a/src/client/views/nodes/Annotation.tsx
+++ b/src/client/views/nodes/Annotation.tsx
@@ -4,13 +4,13 @@ import { observer } from "mobx-react"
 import { observable, action } from 'mobx';
 import 'react-pdf/dist/Page/AnnotationLayer.css'
 
-interface IProps{
+interface IProps {
     Span: HTMLSpanElement;
-    X: number; 
-    Y: number; 
-    Highlights: any[]; 
-    Annotations: any[]; 
-    CurrAnno: any[]; 
+    X: number;
+    Y: number;
+    Highlights: any[];
+    Annotations: any[];
+    CurrAnno: any[];
 
 }
 
@@ -23,95 +23,95 @@ interface IProps{
  */
 @observer
 export class Annotation extends React.Component<IProps> {
-    
+
     /**
      * changes color of the span (highlighted section)
      */
-    onColorChange = (e:React.PointerEvent) => {
-        if (e.currentTarget.innerHTML == "r"){
+    onColorChange = (e: React.PointerEvent) => {
+        if (e.currentTarget.innerHTML === "r") {
             this.props.Span.style.backgroundColor = "rgba(255,0,0, 0.3)"
-        } else if (e.currentTarget.innerHTML == "b"){
+        } else if (e.currentTarget.innerHTML === "b") {
             this.props.Span.style.backgroundColor = "rgba(0,255, 255, 0.3)"
-        } else if (e.currentTarget.innerHTML == "y"){
+        } else if (e.currentTarget.innerHTML === "y") {
             this.props.Span.style.backgroundColor = "rgba(255,255,0, 0.3)"
-        } else if (e.currentTarget.innerHTML == "g"){
+        } else if (e.currentTarget.innerHTML === "g") {
             this.props.Span.style.backgroundColor = "rgba(76, 175, 80, 0.3)"
         }
-      
+
     }
 
     /**
      * removes the highlighted span. Supposed to remove Annotation too, but I don't know how to unmount this
      */
     @action
-    onRemove = (e:any) => {
-        let index:number = -1; 
+    onRemove = (e: any) => {
+        let index: number = -1;
         //finding the highlight in the highlight array 
         this.props.Highlights.forEach((e) => {
-            for (let i = 0; i < e.spans.length; i++){
-                if (e.spans[i] == this.props.Span){
-                    index = this.props.Highlights.indexOf(e); 
-                    this.props.Highlights.splice(index, 1); 
+            for (const span of e.spans) {
+                if (span === this.props.Span) {
+                    index = this.props.Highlights.indexOf(e);
+                    this.props.Highlights.splice(index, 1);
                 }
             }
         })
 
         //removing from CurrAnno and Annotation array 
-        this.props.Annotations.splice(index, 1); 
+        this.props.Annotations.splice(index, 1);
         this.props.CurrAnno.pop()
-        
+
         //removing span from div
-        if(this.props.Span.parentElement){
-            let nodesArray = this.props.Span.parentElement.childNodes; 
+        if (this.props.Span.parentElement) {
+            let nodesArray = this.props.Span.parentElement.childNodes;
             nodesArray.forEach((e) => {
-                if (e == this.props.Span){
-                    if (this.props.Span.parentElement){   
+                if (e === this.props.Span) {
+                    if (this.props.Span.parentElement) {
                         this.props.Highlights.forEach((item) => {
-                            if (item == e){
-                                item.remove(); 
+                            if (item === e) {
+                                item.remove();
                             }
                         })
-                        e.remove();                   
+                        e.remove();
                     }
                 }
-            }) 
+            })
         }
-    
-        
+
+
     }
 
     render() {
         return (
-            <div 
-            style = {{
-            position: "absolute",
-            top: "20px", 
-            left: "0px",  
-            zIndex: 1, 
-            transform: `translate(${this.props.X}px, ${this.props.Y}px)`,
-            
-            }}>
-                <div style = {{width:"200px", height:"50px", backgroundColor: "orange"}}>
+            <div
+                style={{
+                    position: "absolute",
+                    top: "20px",
+                    left: "0px",
+                    zIndex: 1,
+                    transform: `translate(${this.props.X}px, ${this.props.Y}px)`,
+
+                }}>
+                <div style={{ width: "200px", height: "50px", backgroundColor: "orange" }}>
                     <button
-                    style = {{borderRadius: "25px", width:"25%", height:"100%"}}
-                    onClick = {this.onRemove}
+                        style={{ borderRadius: "25px", width: "25%", height: "100%" }}
+                        onClick={this.onRemove}
                     >x</button>
-                    <div style = {{width:"75%", height: "100%" , display:"inline-block"}}>
-                        <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"red", borderRadius:"50%", color: "transparent"}}>r</button>
-                        <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"blue", borderRadius:"50%", color: "transparent"}}>b</button>
-                        <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"yellow", borderRadius:"50%", color:"transparent"}}>y</button>
-                        <button onPointerDown = {this.onColorChange} style = {{backgroundColor:"green", borderRadius:"50%", color:"transparent"}}>g</button>
+                    <div style={{ width: "75%", height: "100%", display: "inline-block" }}>
+                        <button onPointerDown={this.onColorChange} style={{ backgroundColor: "red", borderRadius: "50%", color: "transparent" }}>r</button>
+                        <button onPointerDown={this.onColorChange} style={{ backgroundColor: "blue", borderRadius: "50%", color: "transparent" }}>b</button>
+                        <button onPointerDown={this.onColorChange} style={{ backgroundColor: "yellow", borderRadius: "50%", color: "transparent" }}>y</button>
+                        <button onPointerDown={this.onColorChange} style={{ backgroundColor: "green", borderRadius: "50%", color: "transparent" }}>g</button>
                     </div>
-                    
+
                 </div>
-                <div  style = {{width:"200px", height:"200"}}>
-                    <textarea style = {{width: "100%", height: "100%"}}
-                    defaultValue = "Enter Text Here..."
-                   
+                <div style={{ width: "200px", height: "200" }}>
+                    <textarea style={{ width: "100%", height: "100%" }}
+                        defaultValue="Enter Text Here..."
+
                     ></textarea>
                 </div>
             </div>
-          
+
         );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 0ce991485..1bd934c25 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -29,7 +29,7 @@ export class AudioBox extends React.Component<FieldViewProps> {
 
     render() {
         let field = this.props.Document.Get(this.props.fieldKey)
-        let path = field == FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3" :
+        let path = field === FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3" :
             field instanceof AudioField ? field.Data.href : "http://techslides.com/demos/samples/sample.mp3";
 
         return (
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 1c9155dce..34cc326aa 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -77,7 +77,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         }
         for (const key of this.layoutFields) {
             let field = this.props.Document.Get(key);
-            bindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field;
+            bindings[key.Name] = field && field !== FieldWaiting ? field.GetValue() : field;
         }
         return bindings;
     }
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 9b067aeeb..9958a7c5a 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -32,10 +32,10 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
 
     @action
     onEnterKey = (e: React.KeyboardEvent): void => {
-        if (e.key == 'Enter') {
+        if (e.key === 'Enter') {
             if (this._keyInput && this._valueInput) {
                 let doc = this.props.Document.GetT(KeyStore.Data, Document);
-                if (!doc || doc == FieldWaiting) {
+                if (!doc || doc === FieldWaiting) {
                     return
                 }
                 let realDoc = doc;
@@ -70,7 +70,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
 
     createTable = () => {
         let doc = this.props.Document.GetT(KeyStore.Data, Document);
-        if (!doc || doc == FieldWaiting) {
+        if (!doc || doc === FieldWaiting) {
             return <tr><td>Loading...</td></tr>
         }
         let realDoc = doc;
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index e81f8fec7..4791d6029 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -49,7 +49,7 @@ export class LinkBox extends React.Component<Props> {
                 } else if (contextDoc instanceof Document) {
                     this.props.pairedDoc.GetTAsync(KeyStore.Page, NumberField).then((pfield: any) => {
                         contextDoc.GetTAsync(KeyStore.CurPage, NumberField).then((cfield: any) => {
-                            if (pfield != cfield)
+                            if (pfield !== cfield)
                                 contextDoc.SetNumber(KeyStore.CurPage, pfield.Data);
                             let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
                             if (contextView) {
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 5eeb40772..6c2d24630 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -24,7 +24,7 @@ export class LinkMenu extends React.Component<Props> {
     renderLinkItems(links: Document[], key: Key, type: string) {
         return links.map(link => {
             let doc = link.GetT(key, Document);
-            if (doc && doc != FieldWaiting) {
+            if (doc && doc !== FieldWaiting) {
                 return <LinkBox key={doc.Id} linkDoc={link} linkName={link.Title} pairedDoc={doc} showEditor={action(() => this._editingLink = link)} type={type} />
             }
         })
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index b4590df34..a08b320e8 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -34,7 +34,7 @@ export class VideoBox extends React.Component<FieldViewProps> {
             var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
             var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
             var newNativeHeight = nativeWidth * r.entry.height / r.entry.width;
-            if (!nativeHeight && newNativeHeight != nativeHeight && !isNaN(newNativeHeight)) {
+            if (!nativeHeight && newNativeHeight !== nativeHeight && !isNaN(newNativeHeight)) {
                 this.props.Document.SetNumber(KeyStore.Height, newNativeHeight / nativeWidth * this.props.Document.GetNumber(KeyStore.Width, 0));
                 this.props.Document.SetNumber(KeyStore.NativeHeight, newNativeHeight);
             }
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 92e2fabd4..c1d389001 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -20,7 +20,7 @@ export class WebBox extends React.Component<FieldViewProps> {
 
     render() {
         let field = this.props.Document.Get(this.props.fieldKey);
-        let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
+        let path = field === FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
             field instanceof WebField ? field.Data.href : "https://crossorigin.me/" + "https://cs.brown.edu";
 
         let content = this.html ?
diff --git a/src/fields/AudioField.ts b/src/fields/AudioField.ts
index 8864471ae..252a5b74e 100644
--- a/src/fields/AudioField.ts
+++ b/src/fields/AudioField.ts
@@ -4,7 +4,7 @@ import { Types } from "../server/Message";
 
 export class AudioField extends BasicField<URL> {
     constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
-        super(data == undefined ? new URL("http://techslides.com/demos/samples/sample.mp3") : data, save, id);
+        super(data === undefined ? new URL("http://techslides.com/demos/samples/sample.mp3") : data, save, id);
     }
 
     toString(): string {
diff --git a/src/fields/BasicField.ts b/src/fields/BasicField.ts
index a92c4a236..3083a1937 100644
--- a/src/fields/BasicField.ts
+++ b/src/fields/BasicField.ts
@@ -46,7 +46,7 @@ export abstract class BasicField<T> extends Field {
 
     @action
     TrySetValue(value: any): boolean {
-        if (typeof value == typeof this.data) {
+        if (typeof value === typeof this.data) {
             this.Data = value;
             return true;
         }
diff --git a/src/fields/ImageField.ts b/src/fields/ImageField.ts
index a9ece7d7b..ef616b2ad 100644
--- a/src/fields/ImageField.ts
+++ b/src/fields/ImageField.ts
@@ -4,7 +4,7 @@ import { Types } from "../server/Message";
 
 export class ImageField extends BasicField<URL> {
     constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
-        super(data == undefined ? new URL("http://cs.brown.edu/~bcz/bob_fettucine.jpg") : data, save, id);
+        super(data === undefined ? new URL("http://cs.brown.edu/~bcz/bob_fettucine.jpg") : data, save, id);
     }
 
     toString(): string {
diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts
index c4008bd12..815a3df73 100644
--- a/src/fields/ListField.ts
+++ b/src/fields/ListField.ts
@@ -26,7 +26,7 @@ export class ListField<T extends Field> extends BasicField<T[]> {
         }
         this.observeDisposer = observe(this.Data as IObservableArray<T>, (change: IArrayChange<T> | IArraySplice<T>) => {
             this.updateProxies()
-            if (change.type == "splice") {
+            if (change.type === "splice") {
                 UndoManager.AddEvent({
                     undo: () => this.Data.splice(change.index, change.addedCount, ...change.removed),
                     redo: () => this.Data.splice(change.index, change.removedCount, ...change.added)
@@ -57,8 +57,8 @@ export class ListField<T extends Field> extends BasicField<T[]> {
     }
     private arraysEqual(a: any[], b: any[]) {
         if (a === b) return true;
-        if (a == null || b == null) return false;
-        if (a.length != b.length) return false;
+        if (a === null || b === null) return false;
+        if (a.length !== b.length) return false;
 
         // If you don't care about the order of the elements inside
         // the array, you should sort both arrays here.
@@ -79,9 +79,9 @@ export class ListField<T extends Field> extends BasicField<T[]> {
                 var added = this.data.length < this._proxies.length;
                 var deleted = this.data.length > this._proxies.length;
                 for (let i = 0; i < dataids.length && added; i++)
-                    added = proxies.indexOf(dataids[i]) != -1;
+                    added = proxies.indexOf(dataids[i]) !== -1;
                 for (let i = 0; i < this._proxies.length && deleted; i++)
-                    deleted = dataids.indexOf(proxies[i]) != -1;
+                    deleted = dataids.indexOf(proxies[i]) !== -1;
 
                 this._processingServerUpdate = true;
                 for (let i = 0; i < proxies.length && added; i++) {
diff --git a/src/fields/PDFField.ts b/src/fields/PDFField.ts
index b6625387e..436c1cf2b 100644
--- a/src/fields/PDFField.ts
+++ b/src/fields/PDFField.ts
@@ -7,7 +7,7 @@ import { Types } from "../server/Message";
 
 export class PDFField extends BasicField<URL> {
     constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
-        super(data == undefined ? new URL("http://cs.brown.edu/~bcz/bob_fettucine.jpg") : data, save, id);
+        super(data === undefined ? new URL("http://cs.brown.edu/~bcz/bob_fettucine.jpg") : data, save, id);
     }
 
     toString(): string {
diff --git a/src/fields/VideoField.ts b/src/fields/VideoField.ts
index 626e4ec83..992cc1641 100644
--- a/src/fields/VideoField.ts
+++ b/src/fields/VideoField.ts
@@ -4,7 +4,7 @@ import { Types } from "../server/Message";
 
 export class VideoField extends BasicField<URL> {
     constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
-        super(data == undefined ? new URL("http://techslides.com/demos/sample-videos/small.mp4") : data, save, id);
+        super(data === undefined ? new URL("http://techslides.com/demos/sample-videos/small.mp4") : data, save, id);
     }
 
     toString(): string {
diff --git a/src/server/index.ts b/src/server/index.ts
index ce8bbefe8..f60e6e293 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -143,7 +143,7 @@ addSecureRoute(
     Method.GET,
     (user, res, req) => {
         let detector = new mobileDetect(req.headers['user-agent'] || "");
-        if (detector.mobile() != null) {
+        if (detector.mobile() !== null) {
             res.sendFile(path.join(__dirname, '../../deploy/mobile/image.html'));
         } else {
             res.sendFile(path.join(__dirname, '../../deploy/index.html'));
-- 
cgit v1.2.3-70-g09d2


From f873d620e9a3804d5a6783d7ea335b27d59b4612 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 5 Apr 2019 13:03:21 -0400
Subject: fixed dragging misalignment

---
 src/client/util/DragManager.ts                     | 53 ++++++++++++----------
 src/client/views/DocumentDecorations.tsx           | 18 ++++----
 .../views/collections/CollectionDockingView.tsx    |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 4 files changed, 43 insertions(+), 34 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index cc47c57e0..043932de5 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -21,7 +21,7 @@ export function setupDrag(
             document.removeEventListener("pointerup", onRowUp);
             var dragData = new DragManager.DocumentDragData([docFunc()]);
             dragData.removeDocument = removeFunc;
-            DragManager.StartDocumentDrag([_reference.current!], dragData);
+            DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y);
         }
     );
     let onRowUp = action(
@@ -132,11 +132,14 @@ export namespace DragManager {
     export function StartDocumentDrag(
         eles: HTMLElement[],
         dragData: DocumentDragData,
+        downX: number,
+        downY: number,
         options?: DragOptions
     ) {
         StartDrag(
             eles,
             dragData,
+            downX, downY,
             options,
             (dropData: { [id: string]: any }) =>
                 (dropData.droppedDocuments = dragData.aliasOnDrop
@@ -156,13 +159,15 @@ export namespace DragManager {
     export function StartLinkDrag(
         ele: HTMLElement,
         dragData: LinkDragData,
+        downX: number, downY: number,
         options?: DragOptions
     ) {
-        StartDrag([ele], dragData, options);
+        StartDrag([ele], dragData, downX, downY, options);
     }
     function StartDrag(
         eles: HTMLElement[],
         dragData: { [id: string]: any },
+        downX: number, downY: number,
         options?: DragOptions,
         finishDrag?: (dropData: { [id: string]: any }) => void
     ) {
@@ -204,23 +209,22 @@ export namespace DragManager {
             dragElement.style.width = `${rect.width / scaleX}px`;
             dragElement.style.height = `${rect.height / scaleY}px`;
 
-            // bcz: PDFs don't show up if you clone them because they contain a canvas.
+            // bcz: if PDFs are rendered with svg's, then this code isn't needed
+            // bcz: PDFs don't show up if you clone them when rendered using a canvas. 
             //      however, PDF's have a thumbnail field that contains an image of their canvas.
             //      So we replace the pdf's canvas with the image thumbnail
-            if (docs.length) {
-                var pdfBox = dragElement.getElementsByClassName(
-                    "pdfBox-cont"
-                )[0] as HTMLElement;
-                let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
-                if (pdfBox && pdfBox.childElementCount && thumbnail) {
-                    let img = new Image();
-                    img!.src = thumbnail.toString();
-                    img!.style.position = "absolute";
-                    img!.style.width = `${rect.width / scaleX}px`;
-                    img!.style.height = `${rect.height / scaleY}px`;
-                    pdfBox.replaceChild(img!, pdfBox.children[0]);
-                }
-            }
+            // if (docs.length) {
+            //     var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement;
+            //     let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
+            //     if (pdfBox && pdfBox.childElementCount && thumbnail) {
+            //         let img = new Image();
+            //         img!.src = thumbnail.toString();
+            //         img!.style.position = "absolute";
+            //         img!.style.width = `${rect.width / scaleX}px`;
+            //         img!.style.height = `${rect.height / scaleY}px`;
+            //         pdfBox.replaceChild(img!, pdfBox.children[0]);
+            //     }
+            // }
 
             dragDiv.appendChild(dragElement);
             return dragElement;
@@ -236,6 +240,8 @@ export namespace DragManager {
         }
         eles.map(ele => (ele.hidden = hideSource));
 
+        let lastX = downX;
+        let lastY = downY;
         const moveHandler = (e: PointerEvent) => {
             e.stopPropagation();
             e.preventDefault();
@@ -250,12 +256,13 @@ export namespace DragManager {
                     button: 0
                 });
             }
-            dragElements.map(
-                (dragElement, i) =>
-                    (dragElement.style.transform = `translate(${(xs[i] +=
-                        e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${
-                        scaleXs[i]
-                        }, ${scaleYs[i]})`)
+            let moveX = e.pageX - lastX;
+            let moveY = e.pageY - lastY;
+            lastX = e.pageX;
+            lastY = e.pageY;
+            dragElements.map((dragElement, i) => (dragElement.style.transform =
+                `translate(${(xs[i] += moveX)}px, ${(ys[i] += moveY)}px) 
+                scale(${scaleXs[i]}, ${scaleYs[i]})`)
             );
         };
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 8bf1a42d1..c7e4a269a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -126,12 +126,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         this._dragging = true;
         document.removeEventListener("pointermove", this.onBackgroundMove);
         document.removeEventListener("pointerup", this.onBackgroundUp);
-        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData, {
-            handlers: {
-                dragComplete: action(() => this._dragging = false),
-            },
-            hideSource: true
-        })
+        DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData,
+            e.x, e.y,
+            {
+                handlers: {
+                    dragComplete: action(() => this._dragging = false),
+                },
+                hideSource: true
+            })
         e.stopPropagation();
     }
 
@@ -219,7 +221,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             document.removeEventListener("pointermove", this.onLinkerButtonMoved)
             document.removeEventListener("pointerup", this.onLinkerButtonUp)
             let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
-            DragManager.StartLinkDrag(this._linkerButton.current, dragData, {
+            DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, {
                 handlers: {
                     dragComplete: action(() => { }),
                 },
@@ -265,7 +267,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                         moddrag.push(doc);
                 }
                 let dragData = new DragManager.DocumentDragData(moddrag);
-                DragManager.StartDocumentDrag([this._linkButton.current], dragData, {
+                DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, {
                     handlers: {
                         dragComplete: action(() => { }),
                     },
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 39e0dd989..921ee4591 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -200,7 +200,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             let tab = (e.target as any).parentElement as HTMLElement;
             Server.GetField(docid, action((f: Opt<Field>) => {
                 if (f instanceof Document)
-                    DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]),
+                    DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]), e.pageX, e.pageY,
                         {
                             handlers: {
                                 dragComplete: action(() => { }),
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b9329f269..7514e782d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -219,7 +219,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                     this.props.RemoveDocument(this.props.Document);
                 }
             };
-            DragManager.StartDocumentDrag([this._mainCont.current], dragData, {
+            DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, {
                 handlers: {
                     dragComplete: action(() => { })
                 },
@@ -239,7 +239,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             document.removeEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
             if (!this.topMost || e.buttons == 2 || e.altKey) {
-                this.startDragging(e.x, e.y, e.ctrlKey || e.altKey);
+                this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey);
             }
         }
         e.stopPropagation();
-- 
cgit v1.2.3-70-g09d2


From a63a3f912f8857963cd5cc14cf1e73f645eb3477 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 8 Apr 2019 20:35:29 -0400
Subject: fixed part of scroll issue.  fixed dragging text boxes.

---
 src/client/views/DocumentDecorations.tsx    | 3 +++
 src/client/views/nodes/FormattedTextBox.tsx | 2 --
 2 files changed, 3 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c7e4a269a..4a7502072 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -386,6 +386,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     // }
     render() {
         var bounds = this.Bounds;
+        if (bounds.x === Number.MAX_VALUE) {
+            return (null);
+        }
         // console.log(this._documents.length)
         // let test = this._documents[0].props.Document.Title;
         if (this.Hidden) {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index e59179874..6a38fbe0e 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -153,8 +153,6 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
             e.stopPropagation();
         }
-        if (e.buttons === 1 && this.props.fieldKey !== KeyStore.Archives)
-            e.preventDefault();
     };
     onPointerUp = (e: React.PointerEvent): void => {
         if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
-- 
cgit v1.2.3-70-g09d2


From 5e086920bf97297a02bcd38faea56454c2220279 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Mon, 8 Apr 2019 22:45:22 -0400
Subject: Enabled semi-colon and braces linter rule

---
 src/Utils.ts                                       | 12 +--
 src/client/Server.ts                               | 35 ++++----
 src/client/SocketStub.ts                           | 24 +++---
 src/client/documents/Documents.ts                  | 38 +++++----
 src/client/northstar/core/BaseObject.ts            |  4 +-
 .../northstar/core/attribute/AttributeModel.ts     |  6 +-
 .../core/attribute/AttributeTransformationModel.ts | 17 ++--
 .../core/attribute/CalculatedAttributeModel.ts     |  2 +-
 .../northstar/core/brusher/IBaseBrushable.ts       |  4 +-
 src/client/northstar/core/brusher/IBaseBrusher.ts  |  2 +-
 src/client/northstar/core/filter/FilterModel.ts    |  2 +-
 .../northstar/core/filter/IBaseFilterConsumer.ts   |  4 +-
 .../northstar/core/filter/IBaseFilterProvider.ts   |  2 +-
 .../northstar/core/filter/ValueComparision.ts      | 16 ++--
 src/client/northstar/dash-fields/HistogramField.ts |  2 +-
 .../dash-nodes/HistogramBinPrimitiveCollection.ts  | 12 +--
 src/client/northstar/dash-nodes/HistogramBox.tsx   | 24 +++---
 .../dash-nodes/HistogramBoxPrimitives.tsx          | 40 +++++----
 .../dash-nodes/HistogramLabelPrimitives.tsx        | 15 ++--
 src/client/northstar/manager/Gateway.ts            |  2 +-
 src/client/northstar/model/ModelExtensions.ts      | 18 ++--
 src/client/northstar/model/ModelHelpers.ts         |  8 +-
 .../model/binRanges/AlphabeticVisualBinRange.ts    |  4 +-
 .../model/binRanges/DateTimeVisualBinRange.ts      |  4 +-
 .../model/binRanges/NominalVisualBinRange.ts       |  4 +-
 .../model/binRanges/QuantitativeVisualBinRange.ts  |  2 +-
 .../northstar/model/binRanges/VisualBinRange.ts    |  2 +-
 .../model/binRanges/VisualBinRangeHelper.ts        | 14 +--
 src/client/northstar/operations/BaseOperation.ts   |  9 +-
 .../northstar/operations/HistogramOperation.ts     |  2 +-
 src/client/northstar/utils/ArrayUtil.ts            |  2 +-
 src/client/northstar/utils/Extensions.ts           |  6 +-
 src/client/northstar/utils/GeometryUtil.ts         | 34 ++++----
 src/client/northstar/utils/MathUtil.ts             | 38 +++++----
 src/client/northstar/utils/SizeConverter.ts        | 16 ++--
 src/client/northstar/utils/StyleContants.ts        |  2 +-
 src/client/northstar/utils/Utils.ts                |  8 +-
 src/client/util/DocumentManager.ts                 | 12 +--
 src/client/util/DragManager.ts                     |  5 +-
 src/client/util/RichTextSchema.tsx                 | 42 ++++-----
 src/client/util/Scripting.ts                       | 10 +--
 src/client/util/ScrollBox.tsx                      |  4 +-
 src/client/util/SelectionManager.ts                |  4 +-
 src/client/util/TooltipTextMenu.tsx                | 38 ++++-----
 src/client/util/Transform.ts                       | 20 ++---
 src/client/util/TypedEvent.ts                      |  2 +-
 src/client/util/UndoManager.ts                     | 24 +++---
 src/client/views/ContextMenu.tsx                   | 14 +--
 src/client/views/ContextMenuItem.tsx               |  4 +-
 src/client/views/DocumentDecorations.tsx           | 99 +++++++++++-----------
 src/client/views/EditableView.tsx                  | 10 +--
 src/client/views/InkingCanvas.tsx                  | 15 ++--
 src/client/views/InkingControl.tsx                 | 12 +--
 src/client/views/InkingStroke.tsx                  |  6 +-
 src/client/views/Main.tsx                          | 55 ++++++------
 .../views/collections/CollectionBaseView.tsx       | 34 +++++---
 .../views/collections/CollectionDockingView.tsx    | 37 ++++----
 src/client/views/collections/CollectionPDFView.tsx |  6 +-
 .../views/collections/CollectionSchemaView.tsx     | 39 ++++-----
 src/client/views/collections/CollectionSubView.tsx | 41 ++++-----
 .../views/collections/CollectionTreeView.tsx       | 14 +--
 .../views/collections/CollectionVideoView.tsx      |  6 +-
 src/client/views/collections/CollectionView.tsx    | 20 ++---
 .../CollectionFreeFormLinkView.tsx                 |  2 +-
 .../CollectionFreeFormLinksView.tsx                | 18 ++--
 .../CollectionFreeFormRemoteCursors.tsx            |  6 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 33 ++++----
 .../collections/collectionFreeForm/MarqueeView.tsx | 15 ++--
 .../collectionFreeForm/PreviewCursor.tsx           |  5 +-
 src/client/views/nodes/Annotation.tsx              | 22 ++---
 src/client/views/nodes/AudioBox.tsx                | 12 +--
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 12 +--
 src/client/views/nodes/DocumentContentsView.tsx    |  6 +-
 src/client/views/nodes/DocumentView.tsx            | 35 ++++----
 src/client/views/nodes/FieldView.tsx               | 29 ++++---
 src/client/views/nodes/FormattedTextBox.tsx        | 17 ++--
 src/client/views/nodes/ImageBox.tsx                | 12 +--
 src/client/views/nodes/KeyValueBox.tsx             | 18 ++--
 src/client/views/nodes/KeyValuePair.tsx            | 14 +--
 src/client/views/nodes/LinkBox.tsx                 | 17 ++--
 src/client/views/nodes/LinkEditor.tsx              |  6 +-
 src/client/views/nodes/LinkMenu.tsx                | 10 +--
 src/client/views/nodes/PDFBox.tsx                  | 56 ++++++------
 src/client/views/nodes/Sticky.tsx                  |  6 +-
 src/client/views/nodes/VideoBox.tsx                | 10 +--
 src/client/views/nodes/WebBox.tsx                  |  6 +-
 src/debug/Test.tsx                                 |  8 +-
 src/debug/Viewer.tsx                               | 48 +++++------
 src/fields/AudioField.ts                           |  2 +-
 src/fields/BasicField.ts                           |  6 +-
 src/fields/Document.ts                             | 25 +++---
 src/fields/DocumentReference.ts                    |  2 +-
 src/fields/Field.ts                                |  2 +-
 src/fields/HtmlField.ts                            |  2 +-
 src/fields/ImageField.ts                           |  2 +-
 src/fields/InkField.ts                             |  2 +-
 src/fields/Key.ts                                  |  6 +-
 src/fields/KeyStore.ts                             |  3 +-
 src/fields/ListField.ts                            | 31 ++++---
 src/fields/NumberField.ts                          |  4 +-
 src/fields/PDFField.ts                             |  4 +-
 src/fields/RichTextField.ts                        |  2 +-
 src/fields/TextField.ts                            |  4 +-
 src/fields/TupleField.ts                           |  6 +-
 src/fields/VideoField.ts                           |  2 +-
 src/fields/WebField.ts                             |  2 +-
 src/mobile/ImageUpload.tsx                         | 14 +--
 src/server/Client.ts                               |  4 +-
 src/server/authentication/config/passport.ts       |  6 +-
 .../authentication/controllers/WorkspacesMenu.tsx  |  2 +-
 .../authentication/controllers/user_controller.ts  | 20 ++---
 .../authentication/models/current_user_utils.ts    |  8 +-
 src/server/authentication/models/user_model.ts     |  2 +-
 src/server/database.ts                             | 34 ++++----
 src/server/index.ts                                | 76 ++++++++---------
 test/test.ts                                       |  6 +-
 tslint.json                                        | 16 ++--
 117 files changed, 901 insertions(+), 826 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index 8bd7f2f5c..b0e66787e 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -6,16 +6,16 @@ import { Message, Types } from './server/Message';
 export class Utils {
 
     public static GenerateGuid(): string {
-        return v4()
+        return v4();
     }
 
     public static GenerateDeterministicGuid(seed: string): string {
-        return v5(seed, v5.URL)
+        return v5(seed, v5.URL);
     }
 
     public static GetScreenTransform(ele: HTMLElement): { scale: number, translateX: number, translateY: number } {
         if (!ele) {
-            return { scale: 1, translateX: 1, translateY: 1 }
+            return { scale: 1, translateX: 1, translateY: 1 };
         }
         const rect = ele.getBoundingClientRect();
         const scale = ele.offsetWidth === 0 && rect.width === 0 ? 1 : rect.width / ele.offsetWidth;
@@ -55,8 +55,8 @@ export class Utils {
         return (args: any) => {
             this.log(prefix, messageName, args, true);
             func(args);
-        }
-    };
+        };
+    }
 
     public static Emit<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T) {
         this.log("Emit", message.Name, args, false);
@@ -81,7 +81,7 @@ export class Utils {
     public static AddServerHandlerCallback<T>(socket: Socket, message: Message<T>, handler: (args: [T, (res: any) => any]) => any) {
         socket.on(message.Message, (arg: T, fn: (res: any) => any) => {
             this.log('S receiving', message.Name, arg, true);
-            handler([arg, this.loggingCallback('S sending', fn, message.Name)])
+            handler([arg, this.loggingCallback('S sending', fn, message.Name)]);
         });
     }
 }
diff --git a/src/client/Server.ts b/src/client/Server.ts
index 45c7144ca..857101a33 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -1,7 +1,7 @@
-import { Key } from "../fields/Key"
+import { Key } from "../fields/Key";
 import { ObservableMap, action, reaction } from "mobx";
-import { Field, FieldWaiting, FIELD_WAITING, Opt, FieldId } from "../fields/Field"
-import { Document } from "../fields/Document"
+import { Field, FieldWaiting, FIELD_WAITING, Opt, FieldId } from "../fields/Field";
+import { Document } from "../fields/Document";
 import { SocketStub, FieldMap } from "./SocketStub";
 import * as OpenSocket from 'socket.io-client';
 import { Utils } from "./../Utils";
@@ -10,7 +10,7 @@ import { MessageStore, Types } from "./../server/Message";
 export class Server {
     public static ClientFieldsCached: ObservableMap<FieldId, Field | FIELD_WAITING> = new ObservableMap();
     static Socket: SocketIOClient.Socket = OpenSocket(`${window.location.protocol}//${window.location.hostname}:4321`);
-    static GUID: string = Utils.GenerateGuid()
+    static GUID: string = Utils.GenerateGuid();
 
 
     // Retrieves the cached value of the field and sends a request to the server for the real value (if it's not cached).
@@ -25,15 +25,16 @@ export class Server {
                 this.ClientFieldsCached.set(fieldid, FieldWaiting);
                 SocketStub.SEND_FIELD_REQUEST(fieldid, action((field: Field | undefined) => {
                     let cached = this.ClientFieldsCached.get(fieldid);
-                    if (cached !== FieldWaiting)
+                    if (cached !== FieldWaiting) {
                         cb(cached);
+                    }
                     else {
                         if (field) {
                             this.ClientFieldsCached.set(fieldid, field);
                         } else {
-                            this.ClientFieldsCached.delete(fieldid)
+                            this.ClientFieldsCached.delete(fieldid);
                         }
-                        cb(field)
+                        cb(field);
                     }
                 }));
             } else if (cached !== FieldWaiting) {
@@ -42,12 +43,12 @@ export class Server {
                 reaction(() => this.ClientFieldsCached.get(fieldid),
                     (field, reaction) => {
                         if (field !== FieldWaiting) {
-                            reaction.dispose()
-                            cb(field)
+                            reaction.dispose();
+                            cb(field);
                         }
-                    })
+                    });
             }
-        }
+        };
         if (callback) {
             fn(callback);
         } else {
@@ -79,15 +80,15 @@ export class Server {
                     let field = fields[id];
                     if (field) {
                         if (!(this.ClientFieldsCached.get(field.Id) instanceof Field)) {
-                            this.ClientFieldsCached.set(field.Id, field)
+                            this.ClientFieldsCached.set(field.Id, field);
                         } else {
-                            throw new Error("we shouldn't be trying to replace things that are already in the cache")
+                            throw new Error("we shouldn't be trying to replace things that are already in the cache");
                         }
                     } else {
                         if (this.ClientFieldsCached.get(id) === FieldWaiting) {
                             this.ClientFieldsCached.delete(id);
                         } else {
-                            throw new Error("we shouldn't be trying to replace things that are already in the cache")
+                            throw new Error("we shouldn't be trying to replace things that are already in the cache");
                         }
                     }
                 }
@@ -99,9 +100,9 @@ export class Server {
                                 let realField = field as Field;
                                 existingFields[realField.Id] = realField;
                             }
-                            cb({ ...fields, ...existingFields })
+                            cb({ ...fields, ...existingFields });
                         }
-                    }, { fireImmediately: true })
+                    }, { fireImmediately: true });
             }));
         };
         if (callback) {
@@ -139,7 +140,7 @@ export class Server {
 
     public static UpdateField(field: Field) {
         if (!this.ClientFieldsCached.has(field.Id)) {
-            this.ClientFieldsCached.set(field.Id, field)
+            this.ClientFieldsCached.set(field.Id, field);
         }
         SocketStub.SEND_SET_FIELD(field);
     }
diff --git a/src/client/SocketStub.ts b/src/client/SocketStub.ts
index c3cd8bee6..257973e3d 100644
--- a/src/client/SocketStub.ts
+++ b/src/client/SocketStub.ts
@@ -1,7 +1,7 @@
-import { Key } from "../fields/Key"
-import { Field, FieldId, Opt } from "../fields/Field"
+import { Key } from "../fields/Key";
+import { Field, FieldId, Opt } from "../fields/Field";
 import { ObservableMap } from "mobx";
-import { Document } from "../fields/Document"
+import { Document } from "../fields/Document";
 import { MessageStore, DocumentTransfer } from "../server/Message";
 import { Utils } from "../Utils";
 import { Server } from "./Server";
@@ -37,7 +37,7 @@ export class SocketStub {
         // document.fields.forEach((f, key) => (this.FieldStore.get(document.Id) as Document)._proxies.set(key.Id, (f as Field).Id));
 
         console.log("sending " + document.Title);
-        Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(document.ToJson()))
+        Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(document.ToJson()));
     }
 
     public static SEND_FIELD_REQUEST(fieldid: FieldId): Promise<Opt<Field>>;
@@ -50,12 +50,12 @@ export class SocketStub {
                 } else {
                     cb(undefined);
                 }
-            })
-        }
+            });
+        };
         if (callback) {
             fn(callback);
         } else {
-            return new Promise(fn)
+            return new Promise(fn);
         }
     }
 
@@ -65,7 +65,7 @@ export class SocketStub {
             for (let field of fields) {
                 fieldMap[field._id] = ServerUtils.FromJson(field);
             }
-            callback(fieldMap)
+            callback(fieldMap);
         });
     }
 
@@ -78,8 +78,9 @@ export class SocketStub {
 
         // server updates its document to hold a proxy mapping from key => fieldId
         var document = this.FieldStore.get(doc.Id) as Document;
-        if (document)
+        if (document) {
             document._proxies.set(key.Id, value.Id);
+        }
 
         // server adds the field to its repository of fields
         this.FieldStore.set(value.Id, value);
@@ -93,8 +94,9 @@ export class SocketStub {
 
         // Server removes the field id from the document's list of field proxies
         var document = this.FieldStore.get(doc.Id) as Document;
-        if (document)
+        if (document) {
             document._proxies.delete(key.Id);
+        }
     }
 
     public static SEND_SET_FIELD(field: Field) {
@@ -103,6 +105,6 @@ export class SocketStub {
         // ...SOCKET(SET_FIELD, field id, serialized field value)
 
         // Server updates the value of the field in its fieldstore
-        Utils.Emit(Server.Socket, MessageStore.SetField, field.ToJson())
+        Utils.Emit(Server.Socket, MessageStore.SetField, field.ToJson());
     }
 }
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 613b94abd..72e6e57ab 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -64,7 +64,7 @@ export namespace Documents {
     const webProtoId = "webProto";
     const collProtoId = "collectionProto";
     const kvpProtoId = "kvpProto";
-    const videoProtoId = "videoProto"
+    const videoProtoId = "videoProto";
     const audioProtoId = "audioProto";
 
     export function initProtos(): Promise<void> {
@@ -102,7 +102,7 @@ export namespace Documents {
         if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); }
         if (options.panx !== undefined) { doc.SetNumber(KeyStore.PanX, options.panx); }
         if (options.pany !== undefined) { doc.SetNumber(KeyStore.PanY, options.pany); }
-        return doc
+        return doc;
     }
 
     function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document {
@@ -110,10 +110,12 @@ export namespace Documents {
     }
     function SetInstanceOptions<T, U extends Field & { Data: T }>(doc: Document, options: DocumentOptions, value: [T, { new(): U }] | Document, id?: string) {
         var deleg = doc.MakeDelegate(id);
-        if (value instanceof Document)
-            deleg.Set(KeyStore.Data, value)
-        else
+        if (value instanceof Document) {
+            deleg.Set(KeyStore.Data, value);
+        }
+        else {
             deleg.SetData(KeyStore.Data, value[0], value[1]);
+        }
         return assignOptions(deleg, options);
     }
 
@@ -134,7 +136,7 @@ export namespace Documents {
     function CreateTextPrototype(): Document {
         let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(),
             { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] });
-        return textProto
+        return textProto;
     }
     function CreatePdfPrototype(): Document {
         let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"),
@@ -168,7 +170,7 @@ export namespace Documents {
     }
     function CreateAudioPrototype(): Document {
         let audioProto = setupPrototypeOptions(audioProtoId, "AUDIO_PROTO", AudioBox.LayoutString(),
-            { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+            { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] });
         return audioProto;
     }
 
@@ -205,22 +207,22 @@ export namespace Documents {
         return assignToDelegate(SetInstanceOptions(webProto, options, [html, HtmlField]).MakeDelegate(), options);
     }
     export function KVPDocument(document: Document, options: DocumentOptions = {}, id?: string) {
-        return assignToDelegate(SetInstanceOptions(kvpProto, options, document, id), options)
+        return assignToDelegate(SetInstanceOptions(kvpProto, options, document, id), options);
     }
     export function FreeformDocument(documents: Array<Document>, options: DocumentOptions, id?: string, makePrototype: boolean = true) {
         if (!makePrototype) {
-            return SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id)
+            return SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id);
         }
-        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options)
+        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate(), options);
     }
     export function SchemaDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
-        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options)
+        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options);
     }
     export function TreeDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
-        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options)
+        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options);
     }
     export function DockDocument(config: string, options: DocumentOptions, id?: string) {
-        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options)
+        return assignToDelegate(SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options);
     }
 
     export function CaptionDocument(doc: Document) {
@@ -240,13 +242,13 @@ export namespace Documents {
             <div style="position:relative; height:15%; text-align:center; ">`
             + FormattedTextBox.LayoutString("CaptionKey") +
             `</div> 
-        </div>` };
+        </div>`; }
     export function FixedCaption(fieldName: string = "Caption") {
         return `<div style="position:absolute; height:30px; bottom:0; width:100%">
             <div style="position:absolute; width:100%; height:100%; text-align:center;bottom:0;">`
             + FormattedTextBox.LayoutString(fieldName + "Key") +
             `</div> 
-        </div>` };
+        </div>`; }
 
     function OuterCaption() {
         return (`
@@ -258,7 +260,7 @@ export namespace Documents {
         <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
     </div>
 </div>       
-        `)
+        `);
     }
     function InnerCaption() {
         return (`
@@ -270,7 +272,7 @@ export namespace Documents {
             <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
         </div>
     </div>       
-            `)
+            `);
     }
 
     /*
@@ -293,6 +295,6 @@ export namespace Documents {
             <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
         </div>
     </div>       
-            `)
+            `);
     }
 }
\ No newline at end of file
diff --git a/src/client/northstar/core/BaseObject.ts b/src/client/northstar/core/BaseObject.ts
index f1761e643..ed3818071 100644
--- a/src/client/northstar/core/BaseObject.ts
+++ b/src/client/northstar/core/BaseObject.ts
@@ -1,5 +1,5 @@
-import { IEquatable } from '../utils/IEquatable'
-import { IDisposable } from '../utils/IDisposable'
+import { IEquatable } from '../utils/IEquatable';
+import { IDisposable } from '../utils/IDisposable';
 
 export class BaseObject implements IEquatable, IDisposable {
 
diff --git a/src/client/northstar/core/attribute/AttributeModel.ts b/src/client/northstar/core/attribute/AttributeModel.ts
index 230bfecc8..c89b1617c 100644
--- a/src/client/northstar/core/attribute/AttributeModel.ts
+++ b/src/client/northstar/core/attribute/AttributeModel.ts
@@ -1,5 +1,5 @@
-import { Attribute, DataType, VisualizationHint } from '../../model/idea/idea'
-import { BaseObject } from '../BaseObject'
+import { Attribute, DataType, VisualizationHint } from '../../model/idea/idea';
+import { BaseObject } from '../BaseObject';
 import { observable } from "mobx";
 
 export abstract class AttributeModel extends BaseObject {
@@ -93,7 +93,7 @@ export class BackendAttributeModel extends AttributeModel {
     }
 
     public get DisplayName(): string {
-        return this._displayName.ReplaceAll("_", " ");;
+        return this._displayName.ReplaceAll("_", " ");
     }
 
     public get CodeName(): string {
diff --git a/src/client/northstar/core/attribute/AttributeTransformationModel.ts b/src/client/northstar/core/attribute/AttributeTransformationModel.ts
index f50b78d51..66485183b 100644
--- a/src/client/northstar/core/attribute/AttributeTransformationModel.ts
+++ b/src/client/northstar/core/attribute/AttributeTransformationModel.ts
@@ -1,4 +1,4 @@
-;
+
 import { computed, observable } from "mobx";
 import { AggregateFunction } from "../../model/idea/idea";
 import { AttributeModel } from "./AttributeModel";
@@ -20,16 +20,21 @@ export class AttributeTransformationModel implements IEquatable {
         if (this.AggregateFunction === AggregateFunction.Count) {
             return "count";
         }
-        if (this.AggregateFunction === AggregateFunction.Avg)
+        if (this.AggregateFunction === AggregateFunction.Avg) {
             displayName = "avg(" + displayName + ")";
-        else if (this.AggregateFunction === AggregateFunction.Max)
+        }
+        else if (this.AggregateFunction === AggregateFunction.Max) {
             displayName = "max(" + displayName + ")";
-        else if (this.AggregateFunction === AggregateFunction.Min)
+ }
+        else if (this.AggregateFunction === AggregateFunction.Min) {
             displayName = "min(" + displayName + ")";
-        else if (this.AggregateFunction === AggregateFunction.Sum)
+ }
+        else if (this.AggregateFunction === AggregateFunction.Sum) {
             displayName = "sum(" + displayName + ")";
-        else if (this.AggregateFunction === AggregateFunction.SumE)
+ }
+        else if (this.AggregateFunction === AggregateFunction.SumE) {
             displayName = "sumE(" + displayName + ")";
+ }
 
         return displayName;
     }
diff --git a/src/client/northstar/core/attribute/CalculatedAttributeModel.ts b/src/client/northstar/core/attribute/CalculatedAttributeModel.ts
index 0b8e0d12c..a197c1305 100644
--- a/src/client/northstar/core/attribute/CalculatedAttributeModel.ts
+++ b/src/client/northstar/core/attribute/CalculatedAttributeModel.ts
@@ -1,5 +1,5 @@
 import { BackendAttributeModel, AttributeModel, CodeAttributeModel } from "./AttributeModel";
-import { DataType, VisualizationHint } from '../../model/idea/idea'
+import { DataType, VisualizationHint } from '../../model/idea/idea';
 
 export class CalculatedAttributeManager {
     public static AllCalculatedAttributes: Array<AttributeModel> = new Array<AttributeModel>();
diff --git a/src/client/northstar/core/brusher/IBaseBrushable.ts b/src/client/northstar/core/brusher/IBaseBrushable.ts
index 99a36636f..c46db4d22 100644
--- a/src/client/northstar/core/brusher/IBaseBrushable.ts
+++ b/src/client/northstar/core/brusher/IBaseBrushable.ts
@@ -1,6 +1,6 @@
-import { PIXIPoint } from '../../utils/MathUtil'
+import { PIXIPoint } from '../../utils/MathUtil';
 import { IEquatable } from '../../utils/IEquatable';
-import { Document } from '../../../../fields/Document'
+import { Document } from '../../../../fields/Document';
 
 export interface IBaseBrushable<T> extends IEquatable {
     BrusherModels: Array<Document>;
diff --git a/src/client/northstar/core/brusher/IBaseBrusher.ts b/src/client/northstar/core/brusher/IBaseBrusher.ts
index d7ae65464..d2de6ed62 100644
--- a/src/client/northstar/core/brusher/IBaseBrusher.ts
+++ b/src/client/northstar/core/brusher/IBaseBrusher.ts
@@ -1,4 +1,4 @@
-import { PIXIPoint } from '../../utils/MathUtil'
+import { PIXIPoint } from '../../utils/MathUtil';
 import { IEquatable } from '../../utils/IEquatable';
 
 
diff --git a/src/client/northstar/core/filter/FilterModel.ts b/src/client/northstar/core/filter/FilterModel.ts
index 20fca77f5..e2ba3f652 100644
--- a/src/client/northstar/core/filter/FilterModel.ts
+++ b/src/client/northstar/core/filter/FilterModel.ts
@@ -15,7 +15,7 @@ export class FilterModel {
 
     public Equals(other: FilterModel): boolean {
         if (!Utils.EqualityHelper(this, other)) return false;
-        if (!this.isSame(this.ValueComparisons, (other as FilterModel).ValueComparisons)) return false;
+        if (!this.isSame(this.ValueComparisons, (other).ValueComparisons)) return false;
         return true;
     }
 
diff --git a/src/client/northstar/core/filter/IBaseFilterConsumer.ts b/src/client/northstar/core/filter/IBaseFilterConsumer.ts
index 93f66a154..59d7adf4c 100644
--- a/src/client/northstar/core/filter/IBaseFilterConsumer.ts
+++ b/src/client/northstar/core/filter/IBaseFilterConsumer.ts
@@ -1,5 +1,5 @@
-import { FilterOperand } from '../filter/FilterOperand'
-import { IEquatable } from '../../utils/IEquatable'
+import { FilterOperand } from '../filter/FilterOperand';
+import { IEquatable } from '../../utils/IEquatable';
 import { Document } from "../../../../fields/Document";
 
 export interface IBaseFilterConsumer extends IEquatable {
diff --git a/src/client/northstar/core/filter/IBaseFilterProvider.ts b/src/client/northstar/core/filter/IBaseFilterProvider.ts
index d082bfe12..fc3301b11 100644
--- a/src/client/northstar/core/filter/IBaseFilterProvider.ts
+++ b/src/client/northstar/core/filter/IBaseFilterProvider.ts
@@ -1,4 +1,4 @@
-import { FilterModel } from '../filter/FilterModel'
+import { FilterModel } from '../filter/FilterModel';
 
 export interface IBaseFilterProvider {
     FilterModels: Array<FilterModel>;
diff --git a/src/client/northstar/core/filter/ValueComparision.ts b/src/client/northstar/core/filter/ValueComparision.ts
index 1a3e461f5..80b1242a9 100644
--- a/src/client/northstar/core/filter/ValueComparision.ts
+++ b/src/client/northstar/core/filter/ValueComparision.ts
@@ -1,5 +1,5 @@
-import { Predicate } from '../../model/idea/idea'
-import { Utils } from '../../utils/Utils'
+import { Predicate } from '../../model/idea/idea';
+import { Utils } from '../../utils/Utils';
 import { AttributeModel } from '../attribute/AttributeModel';
 
 export class ValueComparison {
@@ -15,15 +15,19 @@ export class ValueComparison {
     }
 
     public Equals(other: Object): boolean {
-        if (!Utils.EqualityHelper(this, other))
+        if (!Utils.EqualityHelper(this, other)) {
             return false;
-        if (this.Predicate !== (other as ValueComparison).Predicate)
+        }
+        if (this.Predicate !== (other as ValueComparison).Predicate) {
             return false;
+        }
         let isComplex = (typeof this.Value === "object");
-        if (!isComplex && this.Value !== (other as ValueComparison).Value)
+        if (!isComplex && this.Value !== (other as ValueComparison).Value) {
             return false;
-        if (isComplex && !this.Value.Equals((other as ValueComparison).Value))
+        }
+        if (isComplex && !this.Value.Equals((other as ValueComparison).Value)) {
             return false;
+        }
         return true;
     }
 
diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts
index fa2a9c008..6abde4677 100644
--- a/src/client/northstar/dash-fields/HistogramField.ts
+++ b/src/client/northstar/dash-fields/HistogramField.ts
@@ -41,7 +41,7 @@ export class HistogramField extends BasicField<HistogramOperation> {
 
             data: this.toString(),
             _id: this.Id
-        }
+        };
     }
 
     @action
diff --git a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
index cdae90c8b..6291ec1fc 100644
--- a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
+++ b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel";
 import { ChartType } from '../../northstar/model/binRanges/VisualBinRange';
 import { AggregateFunction, Bin, Brush, DoubleValueAggregateResult, HistogramResult, MarginAggregateParameters, MarginAggregateResult } from "../../northstar/model/idea/idea";
@@ -29,7 +29,7 @@ export class HistogramBinPrimitiveCollection {
     private _histoBox: HistogramBox;
     private get histoOp() { return this._histoBox.HistoOp; }
     private get histoResult() { return this.histoOp.Result as HistogramResult; }
-    private get sizeConverter() { return this._histoBox.SizeConverter!; }
+    private get sizeConverter() { return this._histoBox.SizeConverter; }
     public BinPrimitives: Array<HistogramBinPrimitive> = new Array<HistogramBinPrimitive>();
     public HitGeom: PIXIRectangle = PIXIRectangle.EMPTY;
 
@@ -99,13 +99,14 @@ export class HistogramBinPrimitiveCollection {
     private createHeatmapBinPrimitives(bin: Bin, brush: Brush, brushFactorSum: number): number {
 
         let unNormalizedValue = this.getBinValue(2, bin, brush.brushIndex!);
-        if (unNormalizedValue === undefined)
+        if (unNormalizedValue === undefined) {
             return brushFactorSum;
+        }
 
         var normalizedValue = (unNormalizedValue - this._histoBox.ValueRange[0]) / (Math.abs((this._histoBox.ValueRange[1] - this._histoBox.ValueRange[0])) < HistogramBinPrimitiveCollection.TOLERANCE ?
             unNormalizedValue : this._histoBox.ValueRange[1] - this._histoBox.ValueRange[0]);
 
-        let allUnNormalizedValue = this.getBinValue(2, bin, ModelHelpers.AllBrushIndex(this.histoResult))
+        let allUnNormalizedValue = this.getBinValue(2, bin, ModelHelpers.AllBrushIndex(this.histoResult));
 
         // bcz: are these calls needed?  
         let [xFrom, xTo] = this.sizeConverter.DataToScreenXAxisRange(this._histoBox.VisualBinRanges, 0, bin);
@@ -145,8 +146,9 @@ export class HistogramBinPrimitiveCollection {
             let [xFrom, xTo] = this.sizeConverter.DataToScreenPointRange(0, bin, ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, this.histoOp.X, this.histoResult, brush.brushIndex!));
             let [yFrom, yTo] = this.sizeConverter.DataToScreenPointRange(1, bin, ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, this.histoOp.Y, this.histoResult, brush.brushIndex!));
 
-            if (xFrom !== undefined && yFrom !== undefined && xTo !== undefined && yTo !== undefined)
+            if (xFrom !== undefined && yFrom !== undefined && xTo !== undefined && yTo !== undefined) {
                 this.createBinPrimitive(-1, brush, PIXIRectangle.EMPTY, 0, xFrom, xTo, yFrom, yTo, this.baseColorFromBrush(brush), 1, unNormalizedValue);
+            }
         }
         return 0;
     }
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index ec9413649..7df59ef07 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 import { action, computed, observable, reaction, runInAction, trace } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
@@ -25,7 +25,7 @@ import { StyleConstants } from "../utils/StyleContants";
 
 @observer
 export class HistogramBox extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(HistogramBox, fieldStr) }
+    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(HistogramBox, fieldStr); }
     private _dropXRef = React.createRef<HTMLDivElement>();
     private _dropYRef = React.createRef<HTMLDivElement>();
     private _dropXDisposer?: DragManager.DragDropDisposer;
@@ -92,15 +92,15 @@ export class HistogramBox extends React.Component<FieldViewProps> {
         }
         reaction(() => CurrentUserUtils.NorthstarDBCatalog, (catalog?: Catalog) => this.activateHistogramOperation(catalog), { fireImmediately: true });
         reaction(() => [this.VisualBinRanges && this.VisualBinRanges.slice()], () => this.SizeConverter.SetVisualBinRanges(this.VisualBinRanges));
-        reaction(() => [this.PanelHeight, this.PanelWidth], () => this.SizeConverter.SetIsSmall(this.PanelWidth < 40 && this.PanelHeight < 40))
+        reaction(() => [this.PanelHeight, this.PanelWidth], () => this.SizeConverter.SetIsSmall(this.PanelWidth < 40 && this.PanelHeight < 40));
         reaction(() => this.HistogramResult ? this.HistogramResult.binRanges : undefined,
             (binRanges: BinRange[] | undefined) => {
                 if (binRanges) {
                     this.VisualBinRanges.splice(0, this.VisualBinRanges.length, ...binRanges.map((br, ind) =>
-                        VisualBinRangeHelper.GetVisualBinRange(this.HistoOp.Schema!.distinctAttributeParameters, br, this.HistogramResult!, ind ? this.HistoOp.Y : this.HistoOp.X, this.ChartType)));
+                        VisualBinRangeHelper.GetVisualBinRange(this.HistoOp.Schema!.distinctAttributeParameters, br, this.HistogramResult, ind ? this.HistoOp.Y : this.HistoOp.X, this.ChartType)));
 
-                    let valueAggregateKey = ModelHelpers.CreateAggregateKey(this.HistoOp.Schema!.distinctAttributeParameters, this.HistoOp.V, this.HistogramResult!, ModelHelpers.AllBrushIndex(this.HistogramResult!));
-                    this.ValueRange = Object.values(this.HistogramResult!.bins!).reduce((prev, cur) => {
+                    let valueAggregateKey = ModelHelpers.CreateAggregateKey(this.HistoOp.Schema!.distinctAttributeParameters, this.HistoOp.V, this.HistogramResult, ModelHelpers.AllBrushIndex(this.HistogramResult));
+                    this.ValueRange = Object.values(this.HistogramResult.bins!).reduce((prev, cur) => {
                         let value = ModelHelpers.GetAggregateResult(cur, valueAggregateKey) as DoubleValueAggregateResult;
                         return value && value.hasResult ? [Math.min(prev[0], value.result!), Math.max(prev[1], value.result!)] : prev;
                     }, [Number.MAX_VALUE, Number.MIN_VALUE]);
@@ -109,10 +109,12 @@ export class HistogramBox extends React.Component<FieldViewProps> {
     }
 
     componentWillUnmount() {
-        if (this._dropXDisposer)
+        if (this._dropXDisposer) {
             this._dropXDisposer();
-        if (this._dropYDisposer)
+        }
+        if (this._dropYDisposer) {
             this._dropYDisposer();
+        }
     }
 
     activateHistogramOperation(catalog?: Catalog) {
@@ -128,7 +130,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
                             this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => {
                                 brush.SetNumber(KeyStore.BackgroundColor, StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]);
                                 let brushed = brush.GetList(KeyStore.BrushingDocs, [] as Document[]);
-                                return { l: brush, b: brushed[0].Id === proto.Id ? brushed[1] : brushed[0] }
+                                return { l: brush, b: brushed[0].Id === proto.Id ? brushed[1] : brushed[0] };
                             }));
                         }, { fireImmediately: true });
                     reaction(() => this.createOperationParamsCache, () => this.HistoOp.Update(), { fireImmediately: true });
@@ -146,7 +148,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
         let roff = this.SizeConverter.RightOffset;
         let boff = this.SizeConverter.BottomOffset;
         return (
-            <Measure onResize={(r: any) => runInAction(() => { this.PanelWidth = r.entry.width; this.PanelHeight = r.entry.height })}>
+            <Measure onResize={(r: any) => runInAction(() => { this.PanelWidth = r.entry.width; this.PanelHeight = r.entry.height; })}>
                 {({ measureRef }) =>
                     <div className="histogrambox-container" ref={measureRef} style={{ transform: `translate(-50%, -50%)` }}>
                         <div className="histogrambox-yaxislabel" onPointerDown={this.yLabelPointerDown} ref={this._dropYRef} >
@@ -168,7 +170,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
                     </div>
                 }
             </Measure>
-        )
+        );
     }
 }
 
diff --git a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
index a78703247..4c5bdb14b 100644
--- a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 import { computed, observable, reaction, runInAction, trace, action } from "mobx";
 import { observer } from "mobx-react";
 import { Utils as DashUtils } from '../../../Utils';
@@ -28,17 +28,18 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
     @computed get selectedPrimitives() { return this._selectedPrims.map(bp => this.drawRect(bp.Rect, bp.BarAxis, undefined, "border")); }
     @computed get barPrimitives() {
         let histoResult = this.props.HistoBox.HistogramResult;
-        if (!histoResult || !histoResult.bins || !this.props.HistoBox.VisualBinRanges.length)
+        if (!histoResult || !histoResult.bins || !this.props.HistoBox.VisualBinRanges.length) {
             return (null);
+        }
         let allBrushIndex = ModelHelpers.AllBrushIndex(histoResult);
         return Object.keys(histoResult.bins).reduce((prims: JSX.Element[], key: string) => {
-            let drawPrims = new HistogramBinPrimitiveCollection(histoResult!.bins![key], this.props.HistoBox);
+            let drawPrims = new HistogramBinPrimitiveCollection(histoResult.bins![key], this.props.HistoBox);
             let toggle = this.getSelectionToggle(drawPrims.BinPrimitives, allBrushIndex,
-                ModelHelpers.GetBinFilterModel(histoResult!.bins![key], allBrushIndex, histoResult!, this.histoOp.X, this.histoOp.Y));
+                ModelHelpers.GetBinFilterModel(histoResult.bins![key], allBrushIndex, histoResult, this.histoOp.X, this.histoOp.Y));
             drawPrims.BinPrimitives.filter(bp => bp.DataValue && bp.BrushIndex !== allBrushIndex).map(bp =>
                 prims.push(...[{ r: bp.Rect, c: bp.Color }, { r: bp.MarginRect, c: StyleConstants.MARGIN_BARS_COLOR }].map(pair => this.drawRect(pair.r, bp.BarAxis, pair.c, "bar", toggle))));
             return prims;
-        }, [] as JSX.Element[])
+        }, [] as JSX.Element[]);
     }
 
     componentDidMount() {
@@ -47,8 +48,9 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
 
     private getSelectionToggle(binPrimitives: HistogramBinPrimitive[], allBrushIndex: number, filterModel: FilterModel) {
         let rawAllBrushPrim = ArrayUtil.FirstOrDefault(binPrimitives, bp => bp.BrushIndex === allBrushIndex);
-        if (!rawAllBrushPrim)
-            return () => { }
+        if (!rawAllBrushPrim) {
+            return () => { };
+        }
         let allBrushPrim = rawAllBrushPrim;
         return () => runInAction(() => {
             if (ArrayUtil.Contains(this.histoOp.FilterModels, filterModel)) {
@@ -59,23 +61,25 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
                 this._selectedPrims.push(allBrushPrim);
                 this.histoOp.AddFilterModels([filterModel]);
             }
-        })
+        });
     }
 
     private renderGridLinesAndLabels(axis: number) {
         trace();
-        if (!this.props.HistoBox.SizeConverter.Initialized)
+        if (!this.props.HistoBox.SizeConverter.Initialized) {
             return (null);
+        }
         let labels = this.props.HistoBox.VisualBinRanges[axis].GetLabels();
         return <svg className="histogramboxprimitives-svgContainer">
             {labels.reduce((prims, binLabel, i) => {
                 let r = this.props.HistoBox.SizeConverter.DataToScreenRange(binLabel.minValue!, binLabel.maxValue!, axis);
                 prims.push(this.drawLine(r.xFrom, r.yFrom, axis === 0 ? 0 : r.xTo - r.xFrom, axis === 0 ? r.yTo - r.yFrom : 0));
-                if (i === labels.length - 1)
+                if (i === labels.length - 1) {
                     prims.push(this.drawLine(axis === 0 ? r.xTo : r.xFrom, axis === 0 ? r.yFrom : r.yTo, axis === 0 ? 0 : r.xTo - r.xFrom, axis === 0 ? r.yTo - r.yFrom : 0));
+                }
                 return prims;
             }, [] as JSX.Element[])}
-        </svg>
+        </svg>;
     }
 
     drawLine(xFrom: number, yFrom: number, width: number, height: number) {
@@ -89,9 +93,9 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
         }
         let trans2Xpercent = `${(xFrom + width) / this.renderDimension * 100}%`;
         let trans2Ypercent = `${(yFrom + height) / this.renderDimension * 100}%`;
-        let trans1Xpercent = `${xFrom / this.renderDimension * 100}%`
-        let trans1Ypercent = `${yFrom / this.renderDimension * 100}%`
-        return <line className="histogramboxprimitives-line" key={DashUtils.GenerateGuid()} x1={trans1Xpercent} x2={`${trans2Xpercent}`} y1={trans1Ypercent} y2={`${trans2Ypercent}`} />
+        let trans1Xpercent = `${xFrom / this.renderDimension * 100}%`;
+        let trans1Ypercent = `${yFrom / this.renderDimension * 100}%`;
+        return <line className="histogramboxprimitives-line" key={DashUtils.GenerateGuid()} x1={trans1Xpercent} x2={`${trans2Xpercent}`} y1={trans1Ypercent} y2={`${trans2Ypercent}`} />;
     }
     drawRect(r: PIXIRectangle, barAxis: number, color: number | undefined, classExt: string, tapHandler: () => void = () => { }) {
         if (r.height < 0) {
@@ -102,11 +106,11 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
             r.x += r.width;
             r.width = -r.width;
         }
-        let transXpercent = `${r.x / this.renderDimension * 100}%`
-        let transYpercent = `${r.y / this.renderDimension * 100}%`
+        let transXpercent = `${r.x / this.renderDimension * 100}%`;
+        let transYpercent = `${r.y / this.renderDimension * 100}%`;
         let widthXpercent = `${r.width / this.renderDimension * 100}%`;
         let heightYpercent = `${r.height / this.renderDimension * 100}%`;
-        return (<rect className={`histogramboxprimitives-${classExt}`} key={DashUtils.GenerateGuid()} onPointerDown={(e: React.PointerEvent) => { if (e.button === 0) tapHandler() }}
+        return (<rect className={`histogramboxprimitives-${classExt}`} key={DashUtils.GenerateGuid()} onPointerDown={(e: React.PointerEvent) => { if (e.button === 0) tapHandler(); }}
             x={transXpercent} width={`${widthXpercent}`} y={transYpercent} height={`${heightYpercent}`} fill={color ? `${LABColor.RGBtoHexString(color)}` : "transparent"} />);
     }
     render() {
@@ -118,6 +122,6 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
                 {this.barPrimitives}
                 {this.selectedPrimitives}
             </svg>
-        </div>
+        </div>;
     }
 }
\ No newline at end of file
diff --git a/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx
index dd62e9146..5785fe838 100644
--- a/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx
+++ b/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 import { action, computed, reaction } from "mobx";
 import { observer } from "mobx-react";
 import { Utils as DashUtils } from '../../../Utils';
@@ -13,7 +13,7 @@ import { HistogramPrimitivesProps } from "./HistogramBoxPrimitives";
 export class HistogramLabelPrimitives extends React.Component<HistogramPrimitivesProps> {
     componentDidMount() {
         reaction(() => [this.props.HistoBox.PanelWidth, this.props.HistoBox.SizeConverter.LeftOffset, this.props.HistoBox.VisualBinRanges.length],
-            (fields) => HistogramLabelPrimitives.computeLabelAngle(fields[0] as number, fields[1] as number, this.props.HistoBox), { fireImmediately: true });
+            (fields) => HistogramLabelPrimitives.computeLabelAngle(fields[0], fields[1], this.props.HistoBox), { fireImmediately: true });
     }
 
     @action
@@ -32,8 +32,9 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive
     private renderGridLinesAndLabels(axis: number) {
         let sc = this.props.HistoBox.SizeConverter;
         let vb = this.props.HistoBox.VisualBinRanges;
-        if (!vb.length || !sc.Initialized)
+        if (!vb.length || !sc.Initialized) {
             return (null);
+        }
         let dim = (axis === 0 ? this.props.HistoBox.PanelWidth : this.props.HistoBox.PanelHeight) / ((axis === 0 && vb[axis] instanceof NominalVisualBinRange) ?
             (12 + 5) : //  (<number>FontStyles.AxisLabel.fontSize + 5)));
             sc.MaxLabelSizes[axis].coords[axis] + 5);
@@ -52,8 +53,8 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive
                     xStart += Math.max(textWidth / 2, (1 - textWidth / space) * textWidth / 2) - textHeight / 2;
                 }
 
-                let xPercent = axis === 1 ? `${xStart}px` : `${xStart / sc.RenderDimension * 100}%`
-                let yPercent = axis === 0 ? `${this.props.HistoBox.PanelHeight - sc.BottomOffset - textHeight}px` : `${yStart / sc.RenderDimension * 100}%`
+                let xPercent = axis === 1 ? `${xStart}px` : `${xStart / sc.RenderDimension * 100}%`;
+                let yPercent = axis === 0 ? `${this.props.HistoBox.PanelHeight - sc.BottomOffset - textHeight}px` : `${yStart / sc.RenderDimension * 100}%`;
 
                 prims.push(
                     <div className="histogramLabelPrimitives-placer" key={DashUtils.GenerateGuid()} style={{ transform: `translate(${xPercent}, ${yPercent})` }}>
@@ -61,7 +62,7 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive
                             {label}
                         </div>
                     </div>
-                )
+                );
             }
             return prims;
         }, [] as JSX.Element[]);
@@ -73,7 +74,7 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive
         return <div className="histogramLabelPrimitives-container">
             {xaxislines}
             {yaxislines}
-        </div>
+        </div>;
     }
 
 }
\ No newline at end of file
diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts
index ba6fe2ad5..1c8d3fd73 100644
--- a/src/client/northstar/manager/Gateway.ts
+++ b/src/client/northstar/manager/Gateway.ts
@@ -1,4 +1,4 @@
-import { Catalog, OperationReference, Result, CompileResults } from "../model/idea/idea"
+import { Catalog, OperationReference, Result, CompileResults } from "../model/idea/idea";
 import { computed, observable, action } from "mobx";
 
 export class Gateway {
diff --git a/src/client/northstar/model/ModelExtensions.ts b/src/client/northstar/model/ModelExtensions.ts
index e4bf77ed8..29f80d2d1 100644
--- a/src/client/northstar/model/ModelExtensions.ts
+++ b/src/client/northstar/model/ModelExtensions.ts
@@ -1,7 +1,7 @@
-import { AttributeParameters, Brush, MarginAggregateParameters, SingleDimensionAggregateParameters, Solution } from '../model/idea/idea'
-import { Utils } from '../utils/Utils'
+import { AttributeParameters, Brush, MarginAggregateParameters, SingleDimensionAggregateParameters, Solution } from '../model/idea/idea';
+import { Utils } from '../utils/Utils';
 
-import { FilterModel } from '../core/filter/FilterModel'
+import { FilterModel } from '../core/filter/FilterModel';
 
 (SingleDimensionAggregateParameters as any).prototype.Equals = function (other: Object) {
     if (!Utils.EqualityHelper(this, other)) return false;
@@ -9,13 +9,13 @@ import { FilterModel } from '../core/filter/FilterModel'
         (other as SingleDimensionAggregateParameters).attributeParameters!)) return false;
     if (!((this as SingleDimensionAggregateParameters).attributeParameters! as any).Equals((other as SingleDimensionAggregateParameters).attributeParameters)) return false;
     return true;
-}
+};
 
 {
     (AttributeParameters as any).prototype.Equals = function (other: AttributeParameters) {
-        return (<any>this).constructor.name === (<any>other).constructor.name &&
+        return (this).constructor.name === (<any>other).constructor.name &&
             this.rawName === other.rawName;
-    }
+    };
 }
 
 {
@@ -23,7 +23,7 @@ import { FilterModel } from '../core/filter/FilterModel'
         if (!Utils.EqualityHelper(this, other)) return false;
         if ((this as Solution).solutionId !== (other as Solution).solutionId) return false;
         return true;
-    }
+    };
 }
 
 {
@@ -35,7 +35,7 @@ import { FilterModel } from '../core/filter/FilterModel'
 
         if ((this as MarginAggregateParameters).aggregateFunction !== (other as MarginAggregateParameters).aggregateFunction) return false;
         return true;
-    }
+    };
 }
 
 {
@@ -44,5 +44,5 @@ import { FilterModel } from '../core/filter/FilterModel'
         if ((this as Brush).brushEnum !== (other as Brush).brushEnum) return false;
         if ((this as Brush).brushIndex !== (other as Brush).brushIndex) return false;
         return true;
-    }
+    };
 }
\ No newline at end of file
diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts
index 1a58e6180..ac807b41f 100644
--- a/src/client/northstar/model/ModelHelpers.ts
+++ b/src/client/northstar/model/ModelHelpers.ts
@@ -64,7 +64,7 @@ export class ModelHelpers {
             if (aggParams) {
                 aggregateParameters.push(aggParams);
 
-                var margin = new MarginAggregateParameters()
+                var margin = new MarginAggregateParameters();
                 margin.aggregateFunction = agg.AggregateFunction;
                 margin.attributeParameters = ModelHelpers.GetAttributeParameters(agg.AttributeModel);
                 margin.distinctAttributeParameters = distinctAttributeParameters;
@@ -106,7 +106,7 @@ export class ModelHelpers {
                 {
                     rawName: am.CodeName,
                     visualizationHints: am.VisualizationHints,
-                    id: (am as BackendAttributeModel).Id
+                    id: (am).Id
                 });
         }
         else if (am instanceof CodeAttributeModel) {
@@ -114,11 +114,11 @@ export class ModelHelpers {
                 {
                     rawName: am.CodeName,
                     visualizationHints: am.VisualizationHints,
-                    code: (am as CodeAttributeModel).Code
+                    code: (am).Code
                 });
         }
         else {
-            throw new Exception()
+            throw new Exception();
         }
     }
 
diff --git a/src/client/northstar/model/binRanges/AlphabeticVisualBinRange.ts b/src/client/northstar/model/binRanges/AlphabeticVisualBinRange.ts
index 995bf4e0b..120b034f2 100644
--- a/src/client/northstar/model/binRanges/AlphabeticVisualBinRange.ts
+++ b/src/client/northstar/model/binRanges/AlphabeticVisualBinRange.ts
@@ -1,5 +1,5 @@
-import { AlphabeticBinRange, BinLabel } from '../../model/idea/idea'
-import { VisualBinRange } from './VisualBinRange'
+import { AlphabeticBinRange, BinLabel } from '../../model/idea/idea';
+import { VisualBinRange } from './VisualBinRange';
 
 export class AlphabeticVisualBinRange extends VisualBinRange {
     public DataBinRange: AlphabeticBinRange;
diff --git a/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts b/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts
index f5872aa4c..776e643cd 100644
--- a/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts
+++ b/src/client/northstar/model/binRanges/DateTimeVisualBinRange.ts
@@ -1,5 +1,5 @@
-import { DateTimeBinRange, DateTimeStep, DateTimeStepGranularity } from '../idea/idea'
-import { VisualBinRange } from './VisualBinRange'
+import { DateTimeBinRange, DateTimeStep, DateTimeStepGranularity } from '../idea/idea';
+import { VisualBinRange } from './VisualBinRange';
 
 export class DateTimeVisualBinRange extends VisualBinRange {
     public DataBinRange: DateTimeBinRange;
diff --git a/src/client/northstar/model/binRanges/NominalVisualBinRange.ts b/src/client/northstar/model/binRanges/NominalVisualBinRange.ts
index 407ff3ea6..42509d797 100644
--- a/src/client/northstar/model/binRanges/NominalVisualBinRange.ts
+++ b/src/client/northstar/model/binRanges/NominalVisualBinRange.ts
@@ -1,5 +1,5 @@
-import { NominalBinRange, BinLabel } from '../../model/idea/idea'
-import { VisualBinRange } from './VisualBinRange'
+import { NominalBinRange, BinLabel } from '../../model/idea/idea';
+import { VisualBinRange } from './VisualBinRange';
 
 export class NominalVisualBinRange extends VisualBinRange {
     public DataBinRange: NominalBinRange;
diff --git a/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts b/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts
index 80886416b..c579c8e5f 100644
--- a/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts
+++ b/src/client/northstar/model/binRanges/QuantitativeVisualBinRange.ts
@@ -1,4 +1,4 @@
-import { QuantitativeBinRange } from '../idea/idea'
+import { QuantitativeBinRange } from '../idea/idea';
 import { VisualBinRange } from './VisualBinRange';
 import { format } from "d3-format";
 
diff --git a/src/client/northstar/model/binRanges/VisualBinRange.ts b/src/client/northstar/model/binRanges/VisualBinRange.ts
index a0766e494..449a22e91 100644
--- a/src/client/northstar/model/binRanges/VisualBinRange.ts
+++ b/src/client/northstar/model/binRanges/VisualBinRange.ts
@@ -1,4 +1,4 @@
-import { BinLabel } from '../../model/idea/idea'
+import { BinLabel } from '../../model/idea/idea';
 
 export abstract class VisualBinRange {
 
diff --git a/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts b/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
index 63ee61909..9671e55f8 100644
--- a/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
+++ b/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
@@ -16,18 +16,18 @@ export class VisualBinRangeHelper {
 
     public static GetNonAggregateVisualBinRange(dataBinRange: BinRange): VisualBinRange {
         if (dataBinRange instanceof NominalBinRange) {
-            return new NominalVisualBinRange(dataBinRange as NominalBinRange);
+            return new NominalVisualBinRange(dataBinRange);
         }
         else if (dataBinRange instanceof QuantitativeBinRange) {
-            return new QuantitativeVisualBinRange(dataBinRange as QuantitativeBinRange);
+            return new QuantitativeVisualBinRange(dataBinRange);
         }
         else if (dataBinRange instanceof AlphabeticBinRange) {
-            return new AlphabeticVisualBinRange(dataBinRange as AlphabeticBinRange);
+            return new AlphabeticVisualBinRange(dataBinRange);
         }
         else if (dataBinRange instanceof DateTimeBinRange) {
-            return new DateTimeVisualBinRange(dataBinRange as DateTimeBinRange);
+            return new DateTimeVisualBinRange(dataBinRange);
         }
-        throw new Exception()
+        throw new Exception();
     }
 
     public static GetVisualBinRange(distinctAttributeParameters: AttributeParameters | undefined, dataBinRange: BinRange, histoResult: HistogramResult, attr: AttributeTransformationModel, chartType: ChartType): VisualBinRange {
@@ -51,13 +51,13 @@ export class VisualBinRangeHelper {
                         }
                     }
                 }
-            };
+            }
 
             let visualBinRange = QuantitativeVisualBinRange.Initialize(minValue, maxValue, 10, false);
 
             if (chartType === ChartType.HorizontalBar || chartType === ChartType.VerticalBar) {
                 visualBinRange = QuantitativeVisualBinRange.Initialize(Math.min(0, minValue),
-                    Math.max(0, (visualBinRange as QuantitativeVisualBinRange).DataBinRange.maxValue!),
+                    Math.max(0, (visualBinRange).DataBinRange.maxValue!),
                     SETTINGS_X_BINS, false);
             }
             else if (chartType === ChartType.SinglePoint) {
diff --git a/src/client/northstar/operations/BaseOperation.ts b/src/client/northstar/operations/BaseOperation.ts
index a14337763..c6d5f0a15 100644
--- a/src/client/northstar/operations/BaseOperation.ts
+++ b/src/client/northstar/operations/BaseOperation.ts
@@ -1,4 +1,4 @@
-import { FilterModel } from '../core/filter/FilterModel'
+import { FilterModel } from '../core/filter/FilterModel';
 import { ErrorResult, Exception, OperationParameters, OperationReference, Result, ResultParameters } from '../model/idea/idea';
 import { action, computed, observable } from "mobx";
 import { Gateway } from '../manager/Gateway';
@@ -62,8 +62,9 @@ export abstract class BaseOperation {
             }
 
             let operationParameters = this.CreateOperationParameters();
-            if (this.Result)
-                this.Result.progress = 0; // bcz: used to set Result to undefined, but that causes the display to blink
+            if (this.Result) {
+                this.Result.progress = 0;
+            } // bcz: used to set Result to undefined, but that causes the display to blink
             this.Error = "";
             let salt = Math.random().toString();
             this.RequestSalt = salt;
@@ -97,7 +98,7 @@ export abstract class BaseOperation {
                 pollPromise.Start(async () => {
                     let result = await Gateway.Instance.GetResult(resultParameters.toJSON());
                     if (result instanceof ErrorResult) {
-                        throw new Error((result as ErrorResult).message);
+                        throw new Error((result).message);
                     }
                     if (this.RequestSalt === pollPromise.RequestSalt) {
                         if (result && (!this.Result || this.Result.progress !== result.progress)) {
diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts
index a3ddc1c98..760106023 100644
--- a/src/client/northstar/operations/HistogramOperation.ts
+++ b/src/client/northstar/operations/HistogramOperation.ts
@@ -62,7 +62,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons
     @computed
     public get FilterString(): string {
         let filterModels: FilterModel[] = [];
-        return FilterModel.GetFilterModelsRecursive(this, new Set<IBaseFilterProvider>(), filterModels, true)
+        return FilterModel.GetFilterModelsRecursive(this, new Set<IBaseFilterProvider>(), filterModels, true);
     }
 
     @computed
diff --git a/src/client/northstar/utils/ArrayUtil.ts b/src/client/northstar/utils/ArrayUtil.ts
index a52ca6d96..12b8d8e77 100644
--- a/src/client/northstar/utils/ArrayUtil.ts
+++ b/src/client/northstar/utils/ArrayUtil.ts
@@ -50,7 +50,7 @@ export class ArrayUtil {
         if (filtered.length > 0) {
             return filtered[0];
         }
-        throw new Exception()
+        throw new Exception();
     }
 
     public static FirstOrDefault<T>(arr: T[], predicate: (x: any) => boolean): T | undefined {
diff --git a/src/client/northstar/utils/Extensions.ts b/src/client/northstar/utils/Extensions.ts
index 7c2b7fc9d..df14d4da0 100644
--- a/src/client/northstar/utils/Extensions.ts
+++ b/src/client/northstar/utils/Extensions.ts
@@ -6,7 +6,7 @@ interface String {
 String.prototype.ReplaceAll = function (toReplace: string, replacement: string): string {
     var target = this;
     return target.split(toReplace).join(replacement);
-}
+};
 
 String.prototype.Truncate = function (length: number, replacement: string): String {
     var target = this;
@@ -14,7 +14,7 @@ String.prototype.Truncate = function (length: number, replacement: string): Stri
         target = target.slice(0, Math.max(0, length - replacement.length)) + replacement;
     }
     return target;
-}
+};
 
 interface Math {
     log10(val: number): number;
@@ -22,7 +22,7 @@ interface Math {
 
 Math.log10 = function (val: number): number {
     return Math.log(val) / Math.LN10;
-}
+};
 
 declare interface ObjectConstructor {
     assign(...objects: Object[]): Object;
diff --git a/src/client/northstar/utils/GeometryUtil.ts b/src/client/northstar/utils/GeometryUtil.ts
index 6d8acea20..d5220c479 100644
--- a/src/client/northstar/utils/GeometryUtil.ts
+++ b/src/client/northstar/utils/GeometryUtil.ts
@@ -8,15 +8,19 @@ export class GeometryUtil {
         let minY: number = Number.MAX_VALUE;
         let maxX: number = Number.MIN_VALUE;
         let maxY: number = Number.MIN_VALUE;
-        for (var i = 0; i < points.length; i++) {
-            if (points[i].x < minX)
-                minX = points[i].x;
-            if (points[i].y < minY)
-                minY = points[i].y;
-            if (points[i].x > maxX)
-                maxX = points[i].x;
-            if (points[i].y > maxY)
-                maxY = points[i].y;
+        for (const point of points) {
+            if (point.x < minX) {
+                minX = point.x;
+            }
+            if (point.y < minY) {
+                minY = point.y;
+            }
+            if (point.x > maxX) {
+                maxX = point.x;
+            }
+            if (point.y > maxY) {
+                maxY = point.y;
+            }
         }
         return new PIXIRectangle(minX * scale - padding, minY * scale - padding, (maxX - minX) * scale + padding * 2, (maxY - minY) * scale + padding * 2);
     }
@@ -35,7 +39,7 @@ export class GeometryUtil {
                 nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,
                 ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
             return new PIXIPoint(nx, ny);
-        }
+        };
         return points.map(p => rotate(center.x, center.y, p.x, p.y, angle));
     }
 
@@ -54,9 +58,9 @@ export class GeometryUtil {
             return [];
         }
 
-        for (let v = 0; v < points.length; v++) {
-            x = points[v].x;
-            y = points[v].y;
+        for (const point of points) {
+            x = point.x;
+            y = point.y;
             sum_x += x;
             sum_y += y;
             sum_xx += x * x;
@@ -68,8 +72,8 @@ export class GeometryUtil {
         let b = (sum_y / count) - (m * sum_x) / count;
         let result: PIXIPoint[] = new Array<PIXIPoint>();
 
-        for (let v = 0; v < points.length; v++) {
-            x = points[v].x;
+        for (const point of points) {
+            x = point.x;
             y = x * m + b;
             result.push(new PIXIPoint(x, y));
         }
diff --git a/src/client/northstar/utils/MathUtil.ts b/src/client/northstar/utils/MathUtil.ts
index 7aa255096..4b44f40c3 100644
--- a/src/client/northstar/utils/MathUtil.ts
+++ b/src/client/northstar/utils/MathUtil.ts
@@ -16,11 +16,11 @@ export class PIXIRectangle {
     public x: number;
     public y: number;
     public width: number;
-    public height: number
-    public get left() { return this.x }
+    public height: number;
+    public get left() { return this.x; }
     public get right() { return this.x + this.width; }
-    public get top() { return this.y }
-    public get bottom() { return this.top + this.height }
+    public get top() { return this.y; }
+    public get bottom() { return this.top + this.height; }
     public static get EMPTY() { return new PIXIRectangle(0, 0, -1, -1); }
     constructor(x: number, y: number, width: number, height: number) {
         this.x = x;
@@ -127,14 +127,18 @@ export class MathUtil {
     }
 
     public static PointInPIXIRectangle(p: PIXIPoint, rect: PIXIRectangle): boolean {
-        if (p.x < rect.left - this.EPSILON)
+        if (p.x < rect.left - this.EPSILON) {
             return false;
-        if (p.x > rect.right + this.EPSILON)
+        }
+        if (p.x > rect.right + this.EPSILON) {
             return false;
-        if (p.y < rect.top - this.EPSILON)
+        }
+        if (p.y < rect.top - this.EPSILON) {
             return false;
-        if (p.y > rect.bottom + this.EPSILON)
+        }
+        if (p.y > rect.bottom + this.EPSILON) {
             return false;
+        }
 
         return true;
     }
@@ -145,23 +149,27 @@ export class MathUtil {
         var r3 = new PIXIPoint(rect.right, rect.bottom);
         var r4 = new PIXIPoint(rect.left, rect.bottom);
         var ret = new Array<PIXIPoint>();
-        var dist = this.Dist(lineFrom, lineTo)
+        var dist = this.Dist(lineFrom, lineTo);
         var inter = this.LineSegmentIntersection(lineFrom, lineTo, r1, r2);
         if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
+            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
             ret.push(inter);
+        }
         inter = this.LineSegmentIntersection(lineFrom, lineTo, r2, r3);
         if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
+            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
             ret.push(inter);
+        }
         inter = this.LineSegmentIntersection(lineFrom, lineTo, r3, r4);
         if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
+            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
             ret.push(inter);
+        }
         inter = this.LineSegmentIntersection(lineFrom, lineTo, r4, r1);
         if (inter && this.PointInPIXIRectangle(inter, rect) &&
-            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist)
+            this.Dist(inter, lineFrom) < dist && this.Dist(inter, lineTo) < dist) {
             ret.push(inter);
+        }
         return ret;
     }
 
@@ -178,7 +186,7 @@ export class MathUtil {
     }
 
     public static Dot(p1: PIXIPoint, p2: PIXIPoint): number {
-        return p1.x * p2.x + p1.y * p2.y
+        return p1.x * p2.x + p1.y * p2.y;
     }
 
     public static Normalize(p1: PIXIPoint) {
@@ -193,7 +201,7 @@ export class MathUtil {
     public static DistSquared(p1: PIXIPoint, p2: PIXIPoint): number {
         const a = p1.x - p2.x;
         const b = p1.y - p2.y;
-        return (a * a + b * b)
+        return (a * a + b * b);
     }
 
     public static RectIntersectsRect(r1: PIXIRectangle, r2: PIXIRectangle): boolean {
diff --git a/src/client/northstar/utils/SizeConverter.ts b/src/client/northstar/utils/SizeConverter.ts
index b5c4a16ab..a52890ed9 100644
--- a/src/client/northstar/utils/SizeConverter.ts
+++ b/src/client/northstar/utils/SizeConverter.ts
@@ -32,8 +32,8 @@ export class SizeConverter {
         this.Initialized++;
         var xLabels = visualBinRanges[0].GetLabels();
         var yLabels = visualBinRanges[1].GetLabels();
-        var xLabelStrings = xLabels.map(l => l.label!).sort(function (a, b) { return b.length - a.length });
-        var yLabelStrings = yLabels.map(l => l.label!).sort(function (a, b) { return b.length - a.length });
+        var xLabelStrings = xLabels.map(l => l.label!).sort(function (a, b) { return b.length - a.length; });
+        var yLabelStrings = yLabels.map(l => l.label!).sort(function (a, b) { return b.length - a.length; });
 
         var metricsX = { width: 75 }; // RenderUtils.MeasureText(FontStyles.Default.fontFamily.toString(), 12, // FontStyles.AxisLabel.fontSize as number,
         //xLabelStrings[0]!.slice(0, 20)) // StyleConstants.MAX_CHAR_FOR_HISTOGRAM_LABELS));
@@ -62,19 +62,20 @@ export class SizeConverter {
 
     public DataToScreenPointRange(axis: number, bin: Bin, aggregateKey: AggregateKey) {
         var value = ModelHelpers.GetAggregateResult(bin, aggregateKey) as DoubleValueAggregateResult;
-        if (value && value.hasResult)
+        if (value && value.hasResult) {
             return [this.DataToScreenCoord(value.result!, axis) - 5,
             this.DataToScreenCoord(value.result!, axis) + 5];
+        }
         return [undefined, undefined];
     }
 
     public DataToScreenXAxisRange(visualBinRanges: VisualBinRange[], index: number, bin: Bin) {
         var value = visualBinRanges[0].GetValueFromIndex(bin.binIndex!.indices![index]);
-        return [this.DataToScreenX(value), this.DataToScreenX(visualBinRanges[index].AddStep(value))]
+        return [this.DataToScreenX(value), this.DataToScreenX(visualBinRanges[index].AddStep(value))];
     }
     public DataToScreenYAxisRange(visualBinRanges: VisualBinRange[], index: number, bin: Bin) {
         var value = visualBinRanges[1].GetValueFromIndex(bin.binIndex!.indices![index]);
-        return [this.DataToScreenY(value), this.DataToScreenY(visualBinRanges[index].AddStep(value))]
+        return [this.DataToScreenY(value), this.DataToScreenY(visualBinRanges[index].AddStep(value))];
     }
 
     public DataToScreenX(x: number): number {
@@ -85,8 +86,9 @@ export class SizeConverter {
         return flip ? (this.RenderDimension) - retY : retY;
     }
     public DataToScreenCoord(v: number, axis: number) {
-        if (axis === 0)
+        if (axis === 0) {
             return this.DataToScreenX(v);
+        }
         return this.DataToScreenY(v);
     }
     public DataToScreenRange(minVal: number, maxVal: number, axis: number) {
@@ -94,6 +96,6 @@ export class SizeConverter {
         let xTo = this.DataToScreenX(axis === 0 ? maxVal : this.DataMaxs[0]);
         let yFrom = this.DataToScreenY(axis === 1 ? minVal : this.DataMins[1]);
         let yTo = this.DataToScreenY(axis === 1 ? maxVal : this.DataMaxs[1]);
-        return { xFrom, yFrom, xTo, yTo }
+        return { xFrom, yFrom, xTo, yTo };
     }
 }
\ No newline at end of file
diff --git a/src/client/northstar/utils/StyleContants.ts b/src/client/northstar/utils/StyleContants.ts
index ac8617e3b..e9b6e0297 100644
--- a/src/client/northstar/utils/StyleContants.ts
+++ b/src/client/northstar/utils/StyleContants.ts
@@ -11,7 +11,7 @@ export class StyleConstants {
 
     static OPERATOR_MENU_LARGE: number = 35;
     static OPERATOR_MENU_SMALL: number = 25;
-    static BRUSH_PALETTE: number[] = [0x42b43c, 0xfa217f, 0x6a9c75, 0xfb5de7, 0x25b8ea, 0x9b5bc4, 0xda9f63, 0xe23209, 0xfb899b, 0x94a6fd]
+    static BRUSH_PALETTE: number[] = [0x42b43c, 0xfa217f, 0x6a9c75, 0xfb5de7, 0x25b8ea, 0x9b5bc4, 0xda9f63, 0xe23209, 0xfb899b, 0x94a6fd];
     static GAP: number = 3;
 
     static BACKGROUND_COLOR: number = 0xF3F3F3;
diff --git a/src/client/northstar/utils/Utils.ts b/src/client/northstar/utils/Utils.ts
index c96b4cbd9..d071dec62 100644
--- a/src/client/northstar/utils/Utils.ts
+++ b/src/client/northstar/utils/Utils.ts
@@ -1,7 +1,7 @@
-import { IBaseBrushable } from '../core/brusher/IBaseBrushable'
-import { IBaseFilterConsumer } from '../core/filter/IBaseFilterConsumer'
-import { IBaseFilterProvider } from '../core/filter/IBaseFilterProvider'
-import { AggregateFunction } from '../model/idea/idea'
+import { IBaseBrushable } from '../core/brusher/IBaseBrushable';
+import { IBaseFilterConsumer } from '../core/filter/IBaseFilterConsumer';
+import { IBaseFilterProvider } from '../core/filter/IBaseFilterProvider';
+import { AggregateFunction } from '../model/idea/idea';
 
 export class Utils {
 
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index fb489edb6..f38b8ca75 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,7 +1,7 @@
-import React = require('react')
+import React = require('react');
 import { observer } from 'mobx-react';
 import { observable, action, computed } from 'mobx';
-import { Document } from "../../fields/Document"
+import { Document } from "../../fields/Document";
 import { DocumentView } from '../views/nodes/DocumentView';
 import { KeyStore } from '../../fields/KeyStore';
 import { FieldWaiting } from '../../fields/Field';
@@ -50,7 +50,7 @@ export class DocumentManager {
             if (docSrc && docSrc !== FieldWaiting && Object.is(docSrc, toFind)) {
                 toReturn = view;
             }
-        })
+        });
 
         return (toReturn);
     }
@@ -71,7 +71,7 @@ export class DocumentManager {
                     toReturn.push(view);
                 }
             }
-        })
+        });
 
         return (toReturn);
     }
@@ -86,8 +86,8 @@ export class DocumentManager {
                         let linkToDoc = link.GetT(KeyStore.LinkedToDocs, Document);
                         if (linkToDoc && linkToDoc !== FieldWaiting) {
                             DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => {
-                                pairs.push({ a: dv, b: docView1, l: link })
-                            })
+                                pairs.push({ a: dv, b: docView1, l: link });
+                            });
                         }
                     }
                     return pairs;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index f95b2c29d..4849ae9f7 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -103,7 +103,7 @@ export namespace DragManager {
         element.addEventListener("dashOnDrop", handler);
         return () => {
             element.removeEventListener("dashOnDrop", handler);
-            delete element.dataset.canDrop
+            delete element.dataset.canDrop;
         };
     }
 
@@ -216,8 +216,9 @@ export namespace DragManager {
         const moveHandler = (e: PointerEvent) => {
             e.stopPropagation();
             e.preventDefault();
-            if (dragData instanceof DocumentDragData)
+            if (dragData instanceof DocumentDragData) {
                 dragData.aliasOnDrop = e.ctrlKey || e.altKey;
+            }
             if (e.shiftKey) {
                 abortDrag();
                 CollectionDockingView.Instance.StartOtherDrag(docs, {
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 2a3c1da6e..92944bec0 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -1,13 +1,13 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Schema, NodeSpec, MarkSpec, DOMOutputSpecArray, NodeType } from "prosemirror-model"
-import { joinUp, lift, setBlockType, toggleMark, wrapIn } from 'prosemirror-commands'
-import { redo, undo } from 'prosemirror-history'
-import { orderedList, bulletList, listItem, } from 'prosemirror-schema-list'
+import { Schema, NodeSpec, MarkSpec, DOMOutputSpecArray, NodeType } from "prosemirror-model";
+import { joinUp, lift, setBlockType, toggleMark, wrapIn } from 'prosemirror-commands';
+import { redo, undo } from 'prosemirror-history';
+import { orderedList, bulletList, listItem, } from 'prosemirror-schema-list';
 import { EditorState, Transaction, NodeSelection, } from "prosemirror-state";
 import { EditorView, } from "prosemirror-view";
 
 const pDOM: DOMOutputSpecArray = ["p", 0], blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"],
-  preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]
+  preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0];
 
 
 // :: Object
@@ -24,7 +24,7 @@ export const nodes: { [index: string]: NodeSpec } = {
     content: "inline*",
     group: "block",
     parseDOM: [{ tag: "p" }],
-    toDOM() { return pDOM }
+    toDOM() { return pDOM; }
   },
 
   // :: NodeSpec A blockquote (`<blockquote>`) wrapping one or more blocks.
@@ -33,14 +33,14 @@ export const nodes: { [index: string]: NodeSpec } = {
     group: "block",
     defining: true,
     parseDOM: [{ tag: "blockquote" }],
-    toDOM() { return blockquoteDOM }
+    toDOM() { return blockquoteDOM; }
   },
 
   // :: NodeSpec A horizontal rule (`<hr>`).
   horizontal_rule: {
     group: "block",
     parseDOM: [{ tag: "hr" }],
-    toDOM() { return hrDOM }
+    toDOM() { return hrDOM; }
   },
 
   // :: NodeSpec A heading textblock, with a `level` attribute that
@@ -57,7 +57,7 @@ export const nodes: { [index: string]: NodeSpec } = {
     { tag: "h4", attrs: { level: 4 } },
     { tag: "h5", attrs: { level: 5 } },
     { tag: "h6", attrs: { level: 6 } }],
-    toDOM(node: any) { return ["h" + node.attrs.level, 0] }
+    toDOM(node: any) { return ["h" + node.attrs.level, 0]; }
   },
 
   // :: NodeSpec A code listing. Disallows marks or non-text inline
@@ -70,7 +70,7 @@ export const nodes: { [index: string]: NodeSpec } = {
     code: true,
     defining: true,
     parseDOM: [{ tag: "pre", preserveWhitespace: "full" }],
-    toDOM() { return preDOM }
+    toDOM() { return preDOM; }
   },
 
   // :: NodeSpec The text node.
@@ -96,10 +96,10 @@ export const nodes: { [index: string]: NodeSpec } = {
           src: dom.getAttribute("src"),
           title: dom.getAttribute("title"),
           alt: dom.getAttribute("alt")
-        }
+        };
       }
     }],
-    toDOM(node: any) { return ["img", node.attrs] }
+    toDOM(node: any) { return ["img", node.attrs]; }
   },
 
   // :: NodeSpec A hard line break, represented in the DOM as `<br>`.
@@ -108,7 +108,7 @@ export const nodes: { [index: string]: NodeSpec } = {
     group: "inline",
     selectable: false,
     parseDOM: [{ tag: "br" }],
-    toDOM() { return brDOM }
+    toDOM() { return brDOM; }
   },
 
   ordered_list: {
@@ -136,7 +136,7 @@ export const nodes: { [index: string]: NodeSpec } = {
     ...listItem,
     content: 'paragraph block*'
   }
-}
+};
 
 const emDOM: DOMOutputSpecArray = ["em", 0];
 const strongDOM: DOMOutputSpecArray = ["strong", 0];
@@ -156,17 +156,17 @@ export const marks: { [index: string]: MarkSpec } = {
     inclusive: false,
     parseDOM: [{
       tag: "a[href]", getAttrs(dom: any) {
-        return { href: dom.getAttribute("href"), title: dom.getAttribute("title") }
+        return { href: dom.getAttribute("href"), title: dom.getAttribute("title") };
       }
     }],
-    toDOM(node: any) { return ["a", node.attrs, 0] }
+    toDOM(node: any) { return ["a", node.attrs, 0]; }
   },
 
   // :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
   // Has parse rules that also match `<i>` and `font-style: italic`.
   em: {
     parseDOM: [{ tag: "i" }, { tag: "em" }, { style: "font-style=italic" }],
-    toDOM() { return emDOM }
+    toDOM() { return emDOM; }
   },
 
   // :: MarkSpec A strong mark. Rendered as `<strong>`, parse rules
@@ -175,7 +175,7 @@ export const marks: { [index: string]: MarkSpec } = {
     parseDOM: [{ tag: "strong" },
     { tag: "b" },
     { style: "font-weight" }],
-    toDOM() { return strongDOM }
+    toDOM() { return strongDOM; }
   },
 
   underline: {
@@ -221,9 +221,9 @@ export const marks: { [index: string]: MarkSpec } = {
   // :: MarkSpec Code font mark. Represented as a `<code>` element.
   code: {
     parseDOM: [{ tag: "code" }],
-    toDOM() { return codeDOM }
+    toDOM() { return codeDOM; }
   }
-}
+};
 
 // :: Schema
 // This schema rougly corresponds to the document schema used by
@@ -233,4 +233,4 @@ export const marks: { [index: string]: MarkSpec } = {
 //
 // To reuse elements from this schema, extend or read from its
 // `spec.nodes` and `spec.marks` [properties](#model.Schema.spec).
-export const schema = new Schema({ nodes, marks })
\ No newline at end of file
+export const schema = new Schema({ nodes, marks });
\ No newline at end of file
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index bf9b8266f..468484928 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -14,7 +14,7 @@ import { ListField } from "../../fields/ListField";
 // import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
 
 // @ts-ignore
-import * as typescriptlib from '!!raw-loader!./type_decls.d'
+import * as typescriptlib from '!!raw-loader!./type_decls.d';
 import { Documents } from "../documents/Documents";
 import { Key } from "../../fields/Key";
 
@@ -50,7 +50,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
 
     let fieldTypes = [Document, NumberField, TextField, ImageField, RichTextField, ListField, Key];
     let paramNames = ["KeyStore", "Documents", ...fieldTypes.map(fn => fn.name)];
-    let params: any[] = [KeyStore, Documents, ...fieldTypes]
+    let params: any[] = [KeyStore, Documents, ...fieldTypes];
     let compiledFunction = new Function(...paramNames, `return ${script}`);
     let run = (args: { [name: string]: any } = {}): ScriptResult => {
         let argsArray: any[] = [];
@@ -67,7 +67,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
         } catch (error) {
             return { success: false, error };
         }
-    }
+    };
     return { compiled: true, run };
 }
 
@@ -90,14 +90,14 @@ class ScriptingCompilerHost {
     }
     // getDefaultLibFileName(options: ts.CompilerOptions): string {
     getDefaultLibFileName(options: any): string {
-        return 'node_modules/typescript/lib/lib.d.ts' // No idea what this means...
+        return 'node_modules/typescript/lib/lib.d.ts'; // No idea what this means...
     }
     writeFile(fileName: string, content: string) {
         const file = this.files.find(file => file.fileName === fileName);
         if (file) {
             file.content = content;
         } else {
-            this.files.push({ fileName, content })
+            this.files.push({ fileName, content });
         }
     }
     getCurrentDirectory(): string {
diff --git a/src/client/util/ScrollBox.tsx b/src/client/util/ScrollBox.tsx
index b6b088170..a209874a3 100644
--- a/src/client/util/ScrollBox.tsx
+++ b/src/client/util/ScrollBox.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 
 export class ScrollBox extends React.Component {
     onWheel = (e: React.WheelEvent) => {
@@ -16,6 +16,6 @@ export class ScrollBox extends React.Component {
             }} onWheel={this.onWheel}>
                 {this.props.children}
             </div>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 1bb15c86a..5ddaafc72 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -23,7 +23,7 @@ export namespace SelectionManager {
 
         @action
         DeselectAll(): void {
-            manager.SelectedDocuments.map(dv => dv.props.onActiveChanged(false))
+            manager.SelectedDocuments.map(dv => dv.props.onActiveChanged(false));
             manager.SelectedDocuments = [];
         }
     }
@@ -46,7 +46,7 @@ export namespace SelectionManager {
             }
         }
 
-        manager.DeselectAll()
+        manager.DeselectAll();
         if (found) manager.SelectDoc(found, false);
         Main.Instance.SetTextDoc(undefined, undefined);
     }
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 913472aa0..bd5753093 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -5,12 +5,12 @@ import { keymap } from "prosemirror-keymap";
 import { EditorState, Transaction, NodeSelection } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { schema } from "./RichTextSchema";
-import { Schema, NodeType } from "prosemirror-model"
-import React = require("react")
+import { Schema, NodeType } from "prosemirror-model";
+import React = require("react");
 import "./TooltipTextMenu.scss";
 const { toggleMark, setBlockType, wrapIn } = require("prosemirror-commands");
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { wrapInList, bulletList } from 'prosemirror-schema-list'
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { wrapInList, bulletList } from 'prosemirror-schema-list';
 import { faListUl } from '@fortawesome/free-solid-svg-icons';
 
 
@@ -39,7 +39,7 @@ export class TooltipTextMenu {
             { command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") },
             //this doesn't work currently - look into notion of active block
             { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
-        ]
+        ];
         items.forEach(({ dom }) => this.tooltip.appendChild(dom));
 
         //pointer down handler to activate button effects
@@ -52,8 +52,8 @@ export class TooltipTextMenu {
                     //uncomment this if we want the bullet button to disappear if current selection is bulleted
                     // dom.style.display = active ? "" : "none"
                 }
-            })
-        })
+            });
+        });
 
         this.update(view, undefined);
     }
@@ -99,32 +99,32 @@ export class TooltipTextMenu {
         return {
             command: setBlockType(schema.nodes.heading, { level }),
             dom: this.icon("H" + level, "heading")
-        }
+        };
     }
 
     //updates the tooltip menu when the selection changes
     update(view: EditorView, lastState: EditorState | undefined) {
-        let state = view.state
+        let state = view.state;
         // Don't do anything if the document/selection didn't change
         if (lastState && lastState.doc.eq(state.doc) &&
-            lastState.selection.eq(state.selection)) return
+            lastState.selection.eq(state.selection)) return;
 
         // Hide the tooltip if the selection is empty
         if (state.selection.empty) {
-            this.tooltip.style.display = "none"
-            return
+            this.tooltip.style.display = "none";
+            return;
         }
 
         // Otherwise, reposition it and update its content
-        this.tooltip.style.display = ""
-        let { from, to } = state.selection
-        let start = view.coordsAtPos(from), end = view.coordsAtPos(to)
+        this.tooltip.style.display = "";
+        let { from, to } = state.selection;
+        let start = view.coordsAtPos(from), end = view.coordsAtPos(to);
         // The box in which the tooltip is positioned, to use as base
-        let box = this.tooltip.offsetParent!.getBoundingClientRect()
+        let box = this.tooltip.offsetParent!.getBoundingClientRect();
         // Find a center-ish x position from the selection endpoints (when
         // crossing lines, end may be more to the left)
-        let left = Math.max((start.left + end.left) / 2, start.left + 3)
-        this.tooltip.style.left = (left - box.left) + "px"
+        let left = Math.max((start.left + end.left) / 2, start.left + 3);
+        this.tooltip.style.left = (left - box.left) + "px";
         let width = Math.abs(start.left - end.left) / 2;
         let mid = Math.min(start.left, end.left) + width;
 
@@ -133,5 +133,5 @@ export class TooltipTextMenu {
         this.tooltip.style.bottom = (box.bottom - start.top) + "px";
     }
 
-    destroy() { this.tooltip.remove() }
+    destroy() { this.tooltip.remove(); }
 }
\ No newline at end of file
diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts
index ed4282874..e9170ec36 100644
--- a/src/client/util/Transform.ts
+++ b/src/client/util/Transform.ts
@@ -62,19 +62,19 @@ export class Transform {
         return this;
     }
 
-    translated = (x: number, y: number): Transform => this.copy().translate(x, y)
+    translated = (x: number, y: number): Transform => this.copy().translate(x, y);
 
-    preTranslated = (x: number, y: number): Transform => this.copy().preTranslate(x, y)
+    preTranslated = (x: number, y: number): Transform => this.copy().preTranslate(x, y);
 
-    scaled = (scale: number): Transform => this.copy().scale(scale)
+    scaled = (scale: number): Transform => this.copy().scale(scale);
 
-    scaledAbout = (scale: number, x: number, y: number): Transform => this.copy().scaleAbout(scale, x, y)
+    scaledAbout = (scale: number, x: number, y: number): Transform => this.copy().scaleAbout(scale, x, y);
 
-    preScaled = (scale: number): Transform => this.copy().preScale(scale)
+    preScaled = (scale: number): Transform => this.copy().preScale(scale);
 
-    transformed = (transform: Transform): Transform => this.copy().transform(transform)
+    transformed = (transform: Transform): Transform => this.copy().transform(transform);
 
-    preTransformed = (transform: Transform): Transform => this.copy().preTransform(transform)
+    preTransformed = (transform: Transform): Transform => this.copy().preTransform(transform);
 
     transformPoint = (x: number, y: number): [number, number] => {
         x *= this._scale;
@@ -84,7 +84,7 @@ export class Transform {
         return [x, y];
     }
 
-    transformDirection = (x: number, y: number): [number, number] => [x * this._scale, y * this._scale]
+    transformDirection = (x: number, y: number): [number, number] => [x * this._scale, y * this._scale];
 
     transformBounds(x: number, y: number, width: number, height: number): { x: number, y: number, width: number, height: number } {
         [x, y] = this.transformPoint(x, y);
@@ -92,8 +92,8 @@ export class Transform {
         return { x, y, width, height };
     }
 
-    inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
+    inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale);
 
-    copy = () => new Transform(this._translateX, this._translateY, this._scale)
+    copy = () => new Transform(this._translateX, this._translateY, this._scale);
 
 }
\ No newline at end of file
diff --git a/src/client/util/TypedEvent.ts b/src/client/util/TypedEvent.ts
index 1b251da25..532ba78eb 100644
--- a/src/client/util/TypedEvent.ts
+++ b/src/client/util/TypedEvent.ts
@@ -36,5 +36,5 @@ export class TypedEvent<T> {
     this.listenersOncer = [];
   }
 
-  pipe = (te: TypedEvent<T>): Disposable => this.on((e) => te.emit(e))
+  pipe = (te: TypedEvent<T>): Disposable => this.on((e) => te.emit(e));
 }
\ No newline at end of file
diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts
index b4ea4acae..27aed4bac 100644
--- a/src/client/util/UndoManager.ts
+++ b/src/client/util/UndoManager.ts
@@ -1,5 +1,5 @@
 import { observable, action } from "mobx";
-import 'source-map-support/register'
+import 'source-map-support/register';
 import { Without } from "../../Utils";
 import { string } from "prop-types";
 
@@ -31,9 +31,9 @@ function propertyDecorator(target: any, key: string | symbol) {
                         batch.end();
                     }
                 }
-            })
+            });
         }
-    })
+    });
 }
 
 export function undoBatch(target: any, key: string | symbol, descriptor?: TypedPropertyDescriptor<any>): any;
@@ -43,11 +43,11 @@ export function undoBatch(target: any, key?: string | symbol, descriptor?: Typed
         return function () {
             let batch = UndoManager.StartBatch("");
             try {
-                return target.apply(undefined, arguments)
+                return target.apply(undefined, arguments);
             } finally {
                 batch.end();
             }
-        }
+        };
     }
     if (!descriptor) {
         propertyDecorator(target, key);
@@ -58,11 +58,11 @@ export function undoBatch(target: any, key?: string | symbol, descriptor?: Typed
     descriptor.value = function (...args: any[]) {
         let batch = UndoManager.StartBatch(getBatchName(target, key));
         try {
-            return oldFunction.apply(this, args)
+            return oldFunction.apply(this, args);
         } finally {
             batch.end();
         }
-    }
+    };
 
     return descriptor;
 }
@@ -117,8 +117,8 @@ export namespace UndoManager {
             EndBatch(cancel);
         }
 
-        end = () => { this.dispose(false); }
-        cancel = () => { this.dispose(true); }
+        end = () => { this.dispose(false); };
+        cancel = () => { this.dispose(true); };
     }
 
     export function StartBatch(batchName: string): Batch {
@@ -138,7 +138,7 @@ export namespace UndoManager {
             redoStack.length = 0;
             currentBatch = undefined;
         }
-    })
+    });
 
     export function RunInBatch(fn: () => void, batchName: string) {
         let batch = StartBatch(batchName);
@@ -166,7 +166,7 @@ export namespace UndoManager {
         undoing = false;
 
         redoStack.push(commands);
-    })
+    });
 
     export const Redo = action(() => {
         if (redoStack.length === 0) {
@@ -185,6 +185,6 @@ export namespace UndoManager {
         undoing = false;
 
         undoStack.push(commands);
-    })
+    });
 
 }
\ No newline at end of file
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index cfa8ea7b7..615a928ad 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -2,11 +2,11 @@ import React = require("react");
 import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem";
 import { observable, action } from "mobx";
 import { observer } from "mobx-react";
-import "./ContextMenu.scss"
+import "./ContextMenu.scss";
 
 @observer
 export class ContextMenu extends React.Component {
-    static Instance: ContextMenu
+    static Instance: ContextMenu;
 
     @observable private _items: Array<ContextMenuProps> = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }];
     @observable private _pageX: number = 0;
@@ -22,15 +22,15 @@ export class ContextMenu extends React.Component {
     constructor(props: Readonly<{}>) {
         super(props);
 
-        this.ref = React.createRef()
+        this.ref = React.createRef();
 
         ContextMenu.Instance = this;
     }
 
     @action
     clearItems() {
-        this._items = []
-        this._display = "none"
+        this._items = [];
+        this._display = "none";
     }
 
     @action
@@ -56,7 +56,7 @@ export class ContextMenu extends React.Component {
 
         this._searchString = "";
 
-        this._display = "flex"
+        this._display = "flex";
     }
 
     intersects = (x: number, y: number): boolean => {
@@ -86,7 +86,7 @@ export class ContextMenu extends React.Component {
                 {this._items.filter(prop => prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1).
                     map(prop => <ContextMenuItem {...prop} key={prop.description} />)}
             </div>
-        )
+        );
     }
 
     @action
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 4801c1555..70813f0dd 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -11,7 +11,7 @@ export interface SubmenuProps {
 }
 
 export interface ContextMenuItemProps {
-    type: ContextMenuProps | SubmenuProps
+    type: ContextMenuProps | SubmenuProps;
 }
 
 export class ContextMenuItem extends React.Component<ContextMenuProps> {
@@ -20,6 +20,6 @@ export class ContextMenuItem extends React.Component<ContextMenuProps> {
             <div className="contextMenu-item" onClick={this.props.event}>
                 <div className="contextMenu-description">{this.props.description}</div>
             </div>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 285d145a2..b29fb6a2b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -21,8 +21,8 @@ export const Flyout = higflyout.default;
 
 @observer
 export class DocumentDecorations extends React.Component<{}, { value: string }> {
-    static Instance: DocumentDecorations
-    private _resizer = ""
+    static Instance: DocumentDecorations;
+    private _resizer = "";
     private _isPointerDown = false;
     private keyinput: React.RefObject<HTMLInputElement>;
     private _documents: DocumentView[] = SelectionManager.SelectedDocuments();
@@ -40,8 +40,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
 
     constructor(props: Readonly<{}>) {
-        super(props)
-        DocumentDecorations.Instance = this
+        super(props);
+        DocumentDecorations.Instance = this;
         this.handleChange = this.handleChange.bind(this);
         this.keyinput = React.createRef();
     }
@@ -49,7 +49,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     @action
     handleChange = (event: any) => {
         this._title = event.target.value;
-    };
+    }
 
     @action
     enterPressed = (e: any) => {
@@ -59,14 +59,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             var text = e.target.value;
             if (text[0] === '#') {
                 let command = text.slice(1, text.length);
-                this._fieldKey = new Key(command)
+                this._fieldKey = new Key(command);
                 // if (command === "Title" || command === "title") {
                 //     this._fieldKey = KeyStore.Title;
                 // }
                 // else if (command === "Width" || command === "width") {
                 //     this._fieldKey = KeyStore.Width;
                 // }
-                this._title = "changed"
+                this._title = "changed";
                 // TODO: Change field with switch statement
             }
             else {
@@ -89,7 +89,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             return {
                 x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
                 r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
-            }
+            };
         }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE });
     }
 
@@ -104,7 +104,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         document.addEventListener("pointermove", this.onBackgroundMove);
         document.removeEventListener("pointerup", this.onBackgroundUp);
         document.addEventListener("pointerup", this.onBackgroundUp);
-        this._lastDrag = [e.clientX, e.clientY]
+        this._lastDrag = [e.clientX, e.clientY];
         e.stopPropagation();
         e.preventDefault();
     }
@@ -127,7 +127,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 dragComplete: action(() => this._dragging = false),
             },
             hideSource: true
-        })
+        });
         e.stopPropagation();
     }
 
@@ -199,53 +199,53 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
     onLinkerButtonDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
-        document.removeEventListener("pointermove", this.onLinkerButtonMoved)
+        document.removeEventListener("pointermove", this.onLinkerButtonMoved);
         document.addEventListener("pointermove", this.onLinkerButtonMoved);
-        document.removeEventListener("pointerup", this.onLinkerButtonUp)
+        document.removeEventListener("pointerup", this.onLinkerButtonUp);
         document.addEventListener("pointerup", this.onLinkerButtonUp);
     }
     onLinkerButtonUp = (e: PointerEvent): void => {
-        document.removeEventListener("pointermove", this.onLinkerButtonMoved)
-        document.removeEventListener("pointerup", this.onLinkerButtonUp)
+        document.removeEventListener("pointermove", this.onLinkerButtonMoved);
+        document.removeEventListener("pointerup", this.onLinkerButtonUp);
         e.stopPropagation();
     }
 
     onLinkerButtonMoved = (e: PointerEvent): void => {
         if (this._linkerButton.current !== null) {
-            document.removeEventListener("pointermove", this.onLinkerButtonMoved)
-            document.removeEventListener("pointerup", this.onLinkerButtonUp)
+            document.removeEventListener("pointermove", this.onLinkerButtonMoved);
+            document.removeEventListener("pointerup", this.onLinkerButtonUp);
             let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
             DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, {
                 handlers: {
                     dragComplete: action(() => { }),
                 },
                 hideSource: false
-            })
+            });
         }
         e.stopPropagation();
     }
 
     onLinkButtonDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
-        document.removeEventListener("pointermove", this.onLinkButtonMoved)
+        document.removeEventListener("pointermove", this.onLinkButtonMoved);
         document.addEventListener("pointermove", this.onLinkButtonMoved);
-        document.removeEventListener("pointerup", this.onLinkButtonUp)
+        document.removeEventListener("pointerup", this.onLinkButtonUp);
         document.addEventListener("pointerup", this.onLinkButtonUp);
     }
 
     onLinkButtonUp = (e: PointerEvent): void => {
-        document.removeEventListener("pointermove", this.onLinkButtonMoved)
-        document.removeEventListener("pointerup", this.onLinkButtonUp)
+        document.removeEventListener("pointermove", this.onLinkButtonMoved);
+        document.removeEventListener("pointerup", this.onLinkButtonUp);
         e.stopPropagation();
     }
 
     onLinkButtonMoved = async (e: PointerEvent) => {
         if (this._linkButton.current !== null) {
-            document.removeEventListener("pointermove", this.onLinkButtonMoved)
+            document.removeEventListener("pointermove", this.onLinkButtonMoved);
             document.removeEventListener("pointerup", this.onLinkButtonUp);
 
             let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document;
-            let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
+            let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
             let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
                 srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
                     (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
@@ -265,7 +265,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                         dragComplete: action(() => { }),
                     },
                     hideSource: false
-                })
+                });
             }
         }
         e.stopPropagation();
@@ -285,38 +285,38 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             case "":
                 break;
             case "documentDecorations-topLeftResizer":
-                dX = -1
-                dY = -1
-                dW = -(e.movementX)
-                dH = -(e.movementY)
+                dX = -1;
+                dY = -1;
+                dW = -(e.movementX);
+                dH = -(e.movementY);
                 break;
             case "documentDecorations-topRightResizer":
-                dW = e.movementX
-                dY = -1
-                dH = -(e.movementY)
+                dW = e.movementX;
+                dY = -1;
+                dH = -(e.movementY);
                 break;
             case "documentDecorations-topResizer":
-                dY = -1
-                dH = -(e.movementY)
+                dY = -1;
+                dH = -(e.movementY);
                 break;
             case "documentDecorations-bottomLeftResizer":
-                dX = -1
-                dW = -(e.movementX)
-                dH = e.movementY
+                dX = -1;
+                dW = -(e.movementX);
+                dH = e.movementY;
                 break;
             case "documentDecorations-bottomRightResizer":
-                dW = e.movementX
-                dH = e.movementY
+                dW = e.movementX;
+                dH = e.movementY;
                 break;
             case "documentDecorations-bottomResizer":
-                dH = e.movementY
+                dH = e.movementY;
                 break;
             case "documentDecorations-leftResizer":
-                dX = -1
-                dW = -(e.movementX)
+                dX = -1;
+                dW = -(e.movementX);
                 break;
             case "documentDecorations-rightResizer":
-                dW = e.movementX
+                dW = e.movementX;
                 break;
         }
 
@@ -338,14 +338,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 var nativeWidth = doc.GetNumber(KeyStore.NativeWidth, 0);
                 var nativeHeight = doc.GetNumber(KeyStore.NativeHeight, 0);
                 if (nativeWidth > 0 && nativeHeight > 0) {
-                    if (Math.abs(dW) > Math.abs(dH))
+                    if (Math.abs(dW) > Math.abs(dH)) {
                         actualdH = nativeHeight / nativeWidth * actualdW;
+                    }
                     else actualdW = nativeWidth / nativeHeight * actualdH;
                 }
                 doc.SetNumber(KeyStore.Width, actualdW);
                 doc.SetNumber(KeyStore.Height, actualdH);
             }
-        })
+        });
     }
 
     onPointerUp = (e: PointerEvent): void => {
@@ -362,10 +363,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (this._title === "changed" && this._documents.length > 0) {
             let field = this._documents[0].props.Document.Get(this._fieldKey);
             if (field instanceof TextField) {
-                return (field as TextField).GetValue();
+                return (field).GetValue();
             }
             else if (field instanceof NumberField) {
-                return (field as NumberField).GetValue().toString();
+                return (field).GetValue().toString();
             }
         }
         return this._title;
@@ -388,7 +389,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             return (null);
         }
         if (isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
-            console.log("DocumentDecorations: Bounds Error")
+            console.log("DocumentDecorations: Bounds Error");
             return (null);
         }
 
@@ -414,7 +415,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 top: bounds.y - this._resizeBorderWidth / 2,
                 pointerEvents: this._dragging ? "none" : "all",
                 zIndex: SelectionManager.SelectedDocuments().length > 1 ? 1000 : 0,
-            }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation() }} >
+            }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); }} >
             </div>
             <div id="documentDecorations-container" style={{
                 width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
@@ -440,6 +441,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 <div className="linkButton-linker" ref={this._linkerButton} onPointerDown={this.onLinkerButtonDown}>∞</div>
             </div >
         </div>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 982aacdea..2f17c6c51 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -1,7 +1,7 @@
-import React = require('react')
+import React = require('react');
 import { observer } from 'mobx-react';
 import { observable, action, trace } from 'mobx';
-import "./EditableView.scss"
+import "./EditableView.scss";
 
 export interface EditableProps {
     /**
@@ -22,7 +22,7 @@ export interface EditableProps {
      * The contents to render when not editing
      */
     contents: any;
-    height: number
+    height: number;
     display?: string;
 }
 
@@ -55,14 +55,14 @@ export class EditableView extends React.Component<EditableProps> {
     render() {
         if (this.editing) {
             return <input defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus onBlur={action(() => this.editing = false)}
-                style={{ display: this.props.display }}></input>
+                style={{ display: this.props.display }}></input>;
         } else {
             return (
                 <div className="editableView-container-editing" style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }}
                     onClick={action(() => this.editing = true)} >
                     {this.props.contents}
                 </div>
-            )
+            );
         }
     }
 }
\ No newline at end of file
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 4ecc44119..47ee8eb85 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -82,7 +82,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
             });
             this.inkData = data;
         }
-    };
+    }
 
     @action
     onPointerUp = (e: PointerEvent): void => {
@@ -109,7 +109,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
 
     @action
     onPointerMove = (e: PointerEvent): void => {
-        e.stopPropagation()
+        e.stopPropagation();
         e.preventDefault();
         if (InkingControl.Instance.selectedTool !== InkTool.Eraser) {
             let data = this.inkData;  // add points to new line as it is being drawn
@@ -120,7 +120,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
             }
             this.inkData = data;
         }
-    };
+    }
 
     relativeCoordinatesForEvent = (ex: number, ey: number): { x: number, y: number } => {
         let [x, y] = this.props.getScreenTransform().transformPoint(ex, ey);
@@ -137,14 +137,15 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
 
     @computed
     get drawnPaths() {
-        let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1)
+        let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
         let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => {
-            if (strokeData.page === -1 || strokeData.page === curPage)
+            if (strokeData.page === -1 || strokeData.page === curPage) {
                 paths.push(<InkingStroke key={id} id={id} line={strokeData.pathData}
                     offsetX={this.maxCanvasDim - this.inkMidX}
                     offsetY={this.maxCanvasDim - this.inkMidY}
                     color={strokeData.color} width={strokeData.width}
-                    tool={strokeData.tool} deleteCallback={this.removeLine} />)
+                    tool={strokeData.tool} deleteCallback={this.removeLine} />);
+            }
             return paths;
         }, [] as JSX.Element[]);
         return [<svg className={`inkingCanvas-paths-markers`} key="Markers"
@@ -165,6 +166,6 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
                 {this.props.children()}
                 {this.drawnPaths}
             </div >
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 64ee66ec7..9a68f0671 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -1,10 +1,10 @@
 import { observable, action, computed } from "mobx";
 
-import { CirclePicker, ColorResult } from 'react-color'
+import { CirclePicker, ColorResult } from 'react-color';
 import React = require("react");
 import { InkTool } from "../../fields/InkField";
 import { observer } from "mobx-react";
-import "./InkingControl.scss"
+import "./InkingControl.scss";
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons';
@@ -25,7 +25,7 @@ export class InkingControl extends React.Component {
 
     constructor(props: Readonly<{}>) {
         super(props);
-        InkingControl.Instance = this
+        InkingControl.Instance = this;
     }
 
     @action
@@ -66,9 +66,9 @@ export class InkingControl extends React.Component {
 
     selected = (tool: InkTool) => {
         if (this._selectedTool === tool) {
-            return { color: "#61aaa3" }
+            return { color: "#61aaa3" };
         }
-        return {}
+        return {};
     }
 
     @action
@@ -111,6 +111,6 @@ export class InkingControl extends React.Component {
                         onChange={(e: React.ChangeEvent<HTMLInputElement>) => this.switchWidth(e.target.value)} />
                 </li>
             </ul >
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 12b15a3f0..0f05da22c 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -30,7 +30,7 @@ export class InkingStroke extends React.Component<StrokeProps> {
     }
 
     parseData = (line: Array<{ x: number, y: number }>): string => {
-        return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ")
+        return !line.length ? "" : "M " + line.map(p => (p.x + this.props.offsetX) + " " + (p.y + this.props.offsetY)).join(" L ");
     }
 
     createStyle() {
@@ -41,7 +41,7 @@ export class InkingStroke extends React.Component<StrokeProps> {
                     fill: "none",
                     stroke: this._strokeColor,
                     strokeWidth: this._strokeWidth + "px",
-                }
+                };
         }
     }
 
@@ -53,6 +53,6 @@ export class InkingStroke extends React.Component<StrokeProps> {
         return (
             <path d={pathData} style={{ ...pathStyle, pointerEvents: pointerEvents }} strokeLinejoin="round" strokeLinecap="round"
                 onPointerOver={this.deleteStroke} onPointerDown={this.deleteStroke} />
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 6376fd694..fd2e23c91 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -16,7 +16,7 @@ import { WorkspacesMenu } from '../../server/authentication/controllers/Workspac
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { MessageStore } from '../../server/Message';
 import { Utils, returnTrue, emptyFunction } from '../../Utils';
-import * as rp from 'request-promise'
+import * as rp from 'request-promise';
 import { RouteStore } from '../../server/RouteStore';
 import { ServerUtils } from '../../server/ServerUtil';
 import { Documents } from '../documents/Documents';
@@ -74,7 +74,7 @@ export class Main extends React.Component {
             if (pathname.length > 1 && pathname[pathname.length - 2] === 'doc') {
                 CurrentUserUtils.MainDocId = pathname[pathname.length - 1];
             }
-        };
+        }
 
         CurrentUserUtils.loadCurrentUser();
 
@@ -119,8 +119,8 @@ export class Main extends React.Component {
 
     initEventListeners = () => {
         // window.addEventListener("pointermove", (e) => this.reportLocation(e))
-        window.addEventListener("drop", (e) => e.preventDefault(), false) // drop event handler
-        window.addEventListener("dragover", (e) => e.preventDefault(), false) // drag event handler
+        window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler
+        window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler
         // click interactions for the context menu
         document.addEventListener("pointerdown", action(function (e: PointerEvent) {
             if (!ContextMenu.Instance.intersects(e.pageX, e.pageY)) {
@@ -139,15 +139,15 @@ export class Main extends React.Component {
                 } else {
                     this.createNewWorkspace();
                 }
-            })
+            });
         } else {
             Server.GetField(CurrentUserUtils.MainDocId).then(field => {
                 if (field instanceof Document) {
-                    this.openWorkspace(field)
+                    this.openWorkspace(field);
                 } else {
                     this.createNewWorkspace(CurrentUserUtils.MainDocId);
                 }
-            })
+            });
         }
     }
 
@@ -163,7 +163,7 @@ export class Main extends React.Component {
                 // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
                 setTimeout(() => {
                     this.openWorkspace(mainDoc);
-                    let pendingDocument = Documents.SchemaDocument([], { title: "New Mobile Uploads" })
+                    let pendingDocument = Documents.SchemaDocument([], { title: "New Mobile Uploads" });
                     mainDoc.Set(KeyStore.OptionalRightCollection, pendingDocument);
                 }, 0);
             }
@@ -182,7 +182,7 @@ export class Main extends React.Component {
                         if (f && f.Data.length > 0) {
                             CollectionDockingView.Instance.AddRightSplit(col);
                         }
-                    })
+                    });
                 }
             }, 100);
         });
@@ -191,7 +191,7 @@ export class Main extends React.Component {
     @observable
     workspacesShown: boolean = false;
 
-    areWorkspacesShown = () => this.workspacesShown
+    areWorkspacesShown = () => this.workspacesShown;
     @action
     toggleWorkspaces = () => {
         this.workspacesShown = !this.workspacesShown;
@@ -199,7 +199,7 @@ export class Main extends React.Component {
 
     pwidthFunc = () => this.pwidth;
     pheightFunc = () => this.pheight;
-    focusDocument = (doc: Document) => { }
+    focusDocument = (doc: Document) => { };
     noScaling = () => 1;
 
     @observable _textDoc?: Document = undefined;
@@ -208,8 +208,9 @@ export class Main extends React.Component {
     SetTextDoc(textDoc?: Document, div?: HTMLDivElement) {
         this._textDoc = undefined;
         this._textDoc = textDoc;
-        if (div)
+        if (div) {
             this._textRect = div.getBoundingClientRect();
+        }
     }
 
     @computed
@@ -221,7 +222,7 @@ export class Main extends React.Component {
             let h: number = this._textRect.height;
             return <div className="mainDiv-textInput" style={{ transform: `translate(${x}px, ${y}px)`, width: `${w}px`, height: `${h}px` }} >
                 <FormattedTextBox fieldKey={KeyStore.Archives} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={Transform.Identity} focus={(doc) => { }} />
-            </ div>
+            </ div>;
         }
         else return (null);
     }
@@ -241,19 +242,19 @@ export class Main extends React.Component {
                 focus={this.focusDocument}
                 parentActive={returnTrue}
                 onActiveChanged={emptyFunction}
-                ContainingCollectionView={undefined} />
+                ContainingCollectionView={undefined} />;
     }
 
     /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */
     @computed
     get nodesMenu() {
         let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
-        let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf"
+        let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf";
         let weburl = "https://cs.brown.edu/courses/cs166/";
         let audiourl = "http://techslides.com/demos/samples/sample.mp3";
         let videourl = "http://techslides.com/demos/sample-videos/small.mp4";
 
-        let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }))
+        let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }));
         let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
         let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" }));
         let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", copyDraggedItems: true }));
@@ -261,7 +262,7 @@ export class Main extends React.Component {
         let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" }));
         let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" }));
         let addWebNode = action(() => Documents.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
-        let addAudioNode = action(() => Documents.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" }))
+        let addAudioNode = action(() => Documents.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" }));
 
         let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Document][] = [
             [React.createRef<HTMLDivElement>(), "font", "Add Textbox", addTextNode],
@@ -273,7 +274,7 @@ export class Main extends React.Component {
             [React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode],
             [React.createRef<HTMLDivElement>(), "tree", "Add Tree", addTreeNode],
             [React.createRef<HTMLDivElement>(), "table", "Add Schema", addSchemaNode],
-        ]
+        ];
 
         return < div id="add-nodes-menu" >
             <input type="checkbox" id="add-menu-toggle" />
@@ -289,7 +290,7 @@ export class Main extends React.Component {
                         </div></li>)}
                 </ul>
             </div>
-        </div >
+        </div >;
     }
 
     /* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */
@@ -298,7 +299,7 @@ export class Main extends React.Component {
         let workspacesRef = React.createRef<HTMLDivElement>();
         let logoutRef = React.createRef<HTMLDivElement>();
 
-        let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}))
+        let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}));
         return [
             <button className="clear-db-button" key="clear-db" onClick={clearDatabase}>Clear Database</button>,
             <div id="toolbar" key="toolbar">
@@ -310,7 +311,7 @@ export class Main extends React.Component {
                 <button onClick={this.toggleWorkspaces}>Workspaces</button></div>,
             <div className="main-buttonDiv" key="logout" style={{ top: '34px', right: '1px', position: 'absolute' }} ref={logoutRef}>
                 <button onClick={() => request.get(ServerUtils.prepend(RouteStore.logout), () => { })}>Log Out</button></div>
-        ]
+        ];
     }
 
     render() {
@@ -318,7 +319,7 @@ export class Main extends React.Component {
         let workspaces = this.userDocument.GetT<ListField<Document>>(KeyStore.Workspaces, ListField);
         if (workspaces && workspaces !== FieldWaiting) {
             workspaceMenu = <WorkspacesMenu active={this.mainContainer} open={this.openWorkspace} new={this.createNewWorkspace} allWorkspaces={workspaces.Data}
-                isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />
+                isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />;
         }
         return (
             <>
@@ -359,7 +360,7 @@ export class Main extends React.Component {
                             schemaDocuments.push(field);
                         } else {
                             var atmod = new ColumnAttributeModel(attr);
-                            let histoOp = new HistogramOperation(schema!.displayName!,
+                            let histoOp = new HistogramOperation(schema.displayName!,
                                 new AttributeTransformationModel(atmod, AggregateFunction.None),
                                 new AttributeTransformationModel(atmod, AggregateFunction.Count),
                                 new AttributeTransformationModel(atmod, AggregateFunction.Count));
@@ -368,7 +369,7 @@ export class Main extends React.Component {
                     }));
                 });
                 return schemaDoc;
-            })
+            });
         }
     }
     async initializeNorthstar(): Promise<void> {
@@ -386,7 +387,7 @@ export class Main extends React.Component {
 }
 
 (async () => {
-    await Documents.initProtos()
-    await CurrentUserUtils.loadCurrentUser()
+    await Documents.initProtos();
+    await CurrentUserUtils.loadCurrentUser();
     ReactDOM.render(<Main />, document.getElementById('root'));
-})()
+})();
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 7a5ab6e3c..32462a4c1 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -66,17 +66,20 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
     createsCycle(documentToAdd: Document, containerDocument: Document): boolean {
         let data = documentToAdd.GetList<Document>(KeyStore.Data, []);
         for (const doc of data) {
-            if (this.createsCycle(doc, containerDocument))
+            if (this.createsCycle(doc, containerDocument)) {
                 return true;
+            }
         }
         let annots = documentToAdd.GetList<Document>(KeyStore.Annotations, []);
         for (const annot of annots) {
-            if (this.createsCycle(annot, containerDocument))
+            if (this.createsCycle(annot, containerDocument)) {
                 return true;
+            }
         }
         for (let containerProto: FieldValue<Document> = containerDocument; containerProto && containerProto !== FieldWaiting; containerProto = containerProto.GetPrototype()) {
-            if (containerProto.Id === documentToAdd.Id)
+            if (containerProto.Id === documentToAdd.Id) {
                 return true;
+            }
         }
         return false;
     }
@@ -91,20 +94,23 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         }
         if (props.Document.Get(props.fieldKey) instanceof Field) {
             //TODO This won't create the field if it doesn't already exist
-            const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
+            const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>());
             if (!this.createsCycle(doc, props.Document)) {
-                if (!value.some(v => v.Id === doc.Id) || allowDuplicates)
+                if (!value.some(v => v.Id === doc.Id) || allowDuplicates) {
                     value.push(doc);
+                }
             }
-            else
+            else {
                 return false;
+            }
         } else {
             let proto = props.Document.GetPrototype();
             if (!proto || proto === FieldWaiting || !this.createsCycle(proto, doc)) {
                 props.Document.SetOnPrototype(props.fieldKey, new ListField([doc]));
             }
-            else
+            else {
                 return false;
+            }
         }
         return true;
     }
@@ -113,7 +119,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
     removeDocument(doc: Document): boolean {
         const props = this.props;
         //TODO This won't create the field if it doesn't already exist
-        const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
+        const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>());
         let index = -1;
         for (let i = 0; i < value.length; i++) {
             if (value[i].Id === doc.Id) {
@@ -125,16 +131,16 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             if (annotationOn === props.Document) {
                 doc.Set(KeyStore.AnnotationOn, undefined, true);
             }
-        })
+        });
 
         if (index !== -1) {
-            value.splice(index, 1)
+            value.splice(index, 1);
 
             // SelectionManager.DeselectAll()
-            ContextMenu.Instance.clearItems()
+            ContextMenu.Instance.clearItems();
             return true;
         }
-        return false
+        return false;
     }
 
     @action.bound
@@ -155,12 +161,12 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             moveDocument: this.moveDocument,
             active: this.active,
             onActiveChanged: this.onActiveChanged,
-        }
+        };
         return (
             <div className={this.props.className || "collectionView-cont"} onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
                 {this.props.children(this.collectionViewType, props)}
             </div>
-        )
+        );
     }
 
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index c3757a377..ea6d3a247 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -32,7 +32,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 documentId: document.Id,
                 //collectionDockingView: CollectionDockingView.Instance
             }
-        }
+        };
     }
 
     private _goldenLayout: any = null;
@@ -58,7 +58,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         let newItemStackConfig = {
             type: 'stack',
             content: [CollectionDockingView.makeDocumentConfig(document)]
-        }
+        };
         var docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
         this._goldenLayout.root.contentItems[0].addChild(docconfig);
         docconfig.callDownwards('_$init');
@@ -86,7 +86,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         let newItemStackConfig = {
             type: 'stack',
             content: [CollectionDockingView.makeDocumentConfig(document)]
-        }
+        };
 
         var newContentItem = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
 
@@ -124,8 +124,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 this._goldenLayout = new GoldenLayout(JSON.parse(config));
             }
             else {
-                if (config === JSON.stringify(this._goldenLayout.toConfig()))
+                if (config === JSON.stringify(this._goldenLayout.toConfig())) {
                     return;
+                }
                 try {
                     this._goldenLayout.unbind('itemDropped', this.itemDropped);
                     this._goldenLayout.unbind('tabCreated', this.tabCreated);
@@ -199,14 +200,15 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             let docid = (e.target as any).DashDocId;
             let tab = (e.target as any).parentElement as HTMLElement;
             Server.GetField(docid, action((f: Opt<Field>) => {
-                if (f instanceof Document)
-                    DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]), e.pageX, e.pageY,
+                if (f instanceof Document) {
+                    DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), e.pageX, e.pageY,
                         {
                             handlers: {
                                 dragComplete: action(() => { }),
                             },
                             hideSource: false
-                        })
+                        });
+                }
             }));
         }
         if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") {
@@ -220,7 +222,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     @undoBatch
     stateChanged = () => {
         var json = JSON.stringify(this._goldenLayout.toConfig());
-        this.props.Document.SetText(KeyStore.Data, json)
+        this.props.Document.SetText(KeyStore.Data, json);
     }
 
     itemDropped = () => {
@@ -236,7 +238,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                             if (tfield !== undefined) {
                                 tab.titleElement[0].textContent = f.Title;
                             }
-                        })
+                        });
                     }
                 }));
                 tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
@@ -281,7 +283,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
 }
 
 interface DockedFrameProps {
-    documentId: FieldId,
+    documentId: FieldId;
     //collectionDockingView: CollectionDockingView
 }
 @observer
@@ -297,18 +299,19 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         Server.GetField(this.props.documentId, action((f: Opt<Field>) => this._document = f as Document));
     }
 
-    private _nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth)
-    private _nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight)
-    private _contentScaling = () => this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth)
+    private _nativeWidth = () => this._document!.GetNumber(KeyStore.NativeWidth, this._panelWidth);
+    private _nativeHeight = () => this._document!.GetNumber(KeyStore.NativeHeight, this._panelHeight);
+    private _contentScaling = () => this._panelWidth / (this._nativeWidth() ? this._nativeWidth() : this._panelWidth);
 
     ScreenToLocalTransform = () => {
         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!);
-        return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._contentScaling())
+        return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this._contentScaling());
     }
 
     render() {
-        if (!this._document)
+        if (!this._document) {
             return (null);
+        }
         var content =
             <div className="collectionDockingView-content" ref={this._mainCont}>
                 <DocumentView key={this._document.Id} Document={this._document}
@@ -324,10 +327,10 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     onActiveChanged={emptyFunction}
                     focus={(doc: Document) => { }}
                     ContainingCollectionView={undefined} />
-            </div>
+            </div>;
 
         return <Measure onResize={action((r: any) => { this._panelWidth = r.entry.width; this._panelHeight = r.entry.height; })}>
             {({ measureRef }) => <div ref={measureRef}>  {content} </div>}
-        </Measure>
+        </Measure>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 32f50afc0..97bac745c 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -2,7 +2,7 @@ import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ContextMenu } from "../ContextMenu";
-import "./CollectionPDFView.scss"
+import "./CollectionPDFView.scss";
 import React = require("react");
 import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
@@ -44,7 +44,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
                 <CollectionFreeFormView {...props} />
                 {this.props.isSelected() ? this.uIButtons : (null)}
             </>
-        )
+        );
     }
 
     render() {
@@ -52,6 +52,6 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
             <CollectionBaseView {...this.props} className="collectionPdfView-cont" onContextMenu={this.onContextMenu}>
                 {this.subView}
             </CollectionBaseView>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9b780f29b..52933818f 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -41,7 +41,7 @@ class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggl
             if (field instanceof Key) {
                 this.key = field;
             }
-        }))
+        }));
     }
 
     render() {
@@ -49,7 +49,7 @@ class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggl
             return (<div key={this.key.Id}>
                 <input type="checkbox" checked={this.props.checked} onChange={() => this.key && this.props.toggle(this.key)} />
                 {this.key.Name}
-            </div>)
+            </div>);
         }
         return (null);
     }
@@ -85,10 +85,10 @@ export class CollectionSchemaView extends CollectionSubView {
             focus: emptyFunction,
             active: returnFalse,
             onActiveChanged: emptyFunction,
-        }
+        };
         let contents = (
             <FieldView {...props} />
-        )
+        );
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = setupDrag(reference, () => props.Document, this.props.moveDocument);
         let applyToDoc = (doc: Document, run: (args?: { [name: string]: any }) => any) => {
@@ -106,7 +106,7 @@ export class CollectionSchemaView extends CollectionSubView {
                 }
             }
             return false;
-        }
+        };
         return (
             <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "56px" }} key={props.Document.Id} ref={reference}>
                 <EditableView
@@ -138,11 +138,11 @@ export class CollectionSchemaView extends CollectionSubView {
                             if (val) {
                                 val.Data.forEach(doc => applyToDoc(doc, run));
                             }
-                        })
+                        });
                     }}>
                 </EditableView>
             </div>
-        )
+        );
     }
 
     private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
@@ -156,7 +156,7 @@ export class CollectionSchemaView extends CollectionSubView {
                 that._selectedIndex = rowInfo.index;
 
                 if (handleOriginal) {
-                    handleOriginal()
+                    handleOriginal();
                 }
             }),
             style: {
@@ -182,7 +182,7 @@ export class CollectionSchemaView extends CollectionSubView {
                     this.columns.splice(index, 1);
                 }
 
-            })
+            });
     }
 
     //toggles preview side-panel of schema
@@ -197,7 +197,7 @@ export class CollectionSchemaView extends CollectionSubView {
     @computed
     get findAllDocumentKeys(): { [id: string]: boolean } {
         const docs = this.props.Document.GetList<Document>(this.props.fieldKey, []);
-        let keys: { [id: string]: boolean } = {}
+        let keys: { [id: string]: boolean } = {};
         if (this._optionsActivated > -1) {
             // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
             //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
@@ -206,7 +206,7 @@ export class CollectionSchemaView extends CollectionSubView {
             //  is displayed (unlikely) it won't show up until something else changes.
             untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
         }
-        this.columns.forEach(key => keys[key.Id] = true)
+        this.columns.forEach(key => keys[key.Id] = true);
         return keys;
     }
 
@@ -248,10 +248,10 @@ export class CollectionSchemaView extends CollectionSubView {
     getContentScaling = (): number => this._contentScaling;
     getPanelWidth = (): number => this._panelWidth;
     getPanelHeight = (): number => this._panelHeight;
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling)
-    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling)
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
+    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
 
-    focusDocument = (doc: Document) => { }
+    focusDocument = (doc: Document) => { };
 
     onPointerDown = (e: React.PointerEvent): void => {
         if (this.props.isSelected()) {
@@ -273,8 +273,9 @@ export class CollectionSchemaView extends CollectionSubView {
         this.newKeyName = e.currentTarget.value;
     }
     onWheel = (e: React.WheelEvent): void => {
-        if (this.props.active())
+        if (this.props.active()) {
             e.stopPropagation();
+        }
     }
 
     @observable _optionsActivated: number = 0;
@@ -322,9 +323,9 @@ export class CollectionSchemaView extends CollectionSubView {
                     </div>
                 }
             </Measure>
-        )
+        );
         let dividerDragger = this.splitPercentage === 0 ? (null) :
-            <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />
+            <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
 
         //options button and menu
         let optionsMenu = !this.props.active() ? (null) : (<Flyout
@@ -379,6 +380,6 @@ export class CollectionSchemaView extends CollectionSubView {
                     {optionsMenu}
                 </div>
             </div >
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 59b89e119..bd385c27e 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -14,7 +14,7 @@ import { NumberField } from "../../../fields/NumberField";
 import { ServerUtils } from "../../../server/ServerUtil";
 import { Server } from "../../Server";
 import { FieldViewProps } from "../nodes/FieldView";
-import * as rp from 'request-promise'
+import * as rp from 'request-promise';
 
 export interface CollectionViewProps extends FieldViewProps {
     addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
@@ -58,8 +58,8 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                         let entry = new TupleField<[string, string], [number, number]>([textInfo, position]);
                         cursors.push(entry);
                     }
-                }))
-            })
+                }));
+            });
         }
     }
 
@@ -77,17 +77,17 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                 added = de.data.droppedDocuments.reduce((added: boolean, d) => added || this.props.addDocument(d), false);
             } else if (de.data.moveDocument) {
                 const move = de.data.moveDocument;
-                added = de.data.droppedDocuments.reduce((added: boolean, d) => added || move(d, this.props.Document, this.props.addDocument), false)
+                added = de.data.droppedDocuments.reduce((added: boolean, d) => added || move(d, this.props.Document, this.props.addDocument), false);
             } else {
-                added = de.data.droppedDocuments.reduce((added: boolean, d) => added || this.props.addDocument(d), false)
+                added = de.data.droppedDocuments.reduce((added: boolean, d) => added || this.props.addDocument(d), false);
             }
             e.stopPropagation();
             return added;
         }
         if (de.data instanceof DragManager.LinkDragData) {
             let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
-            if (sourceDoc) runInAction(() => {
-                let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
+            if (sourceDoc) { runInAction(() => {
+                let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
                 if (srcTarg && srcTarg !== FieldWaiting) {
                     let linkDocs = srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]);
                     linkDocs.map(linkDoc => {
@@ -97,9 +97,10 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                             de.data.droppedDocuments.push(dropdoc);
                             this.props.addDocument(dropdoc, false);
                         }
-                    })
+                    });
                 }
-            })
+            });
+            }
             return true;
         }
         return false;
@@ -133,7 +134,7 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                         alias.SetNumber(KeyStore.Height, options.height || options.width || 300);
                         this.props.addDocument(alias, false);
                     }
-                })
+                });
                 return undefined;
             }
             ctor = Documents.WebDocument;
@@ -151,8 +152,8 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
         if (text && text.startsWith("<div")) {
             return;
         }
-        e.stopPropagation()
-        e.preventDefault()
+        e.stopPropagation();
+        e.preventDefault();
 
         if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
             console.log("not good");
@@ -173,11 +174,11 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                 let prom = new Promise<string>(res =>
                     e.dataTransfer.items[i].getAsString(res)).then(action((s: string) => {
                         str = s;
-                        return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s))
+                        return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s));
                     })).then(res => {
                         let type = res.headers["content-type"];
                         if (type) {
-                            let doc = this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 })
+                            let doc = this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 });
                             if (doc) {
                                 this.props.addDocument(doc, false);
                             }
@@ -186,13 +187,13 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                 promises.push(prom);
                 // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
             }
-            let type = item.type
+            let type = item.type;
             if (item.kind === "file") {
                 let file = item.getAsFile();
-                let formData = new FormData()
+                let formData = new FormData();
 
                 if (file) {
-                    formData.append('file', file)
+                    formData.append('file', file);
                 }
 
                 let prom = fetch(upload, {
@@ -201,15 +202,15 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
                 }).then(async (res: Response) => {
                     const json = await res.json();
                     json.map((file: any) => {
-                        let path = window.location.origin + file
+                        let path = window.location.origin + file;
                         runInAction(() => {
-                            let doc = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300 })
+                            let doc = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300 });
 
                             let docs = this.props.Document.GetT(KeyStore.Data, ListField);
                             if (docs !== FieldWaiting) {
                                 if (!docs) {
                                     docs = new ListField<Document>();
-                                    this.props.Document.Set(KeyStore.Data, docs)
+                                    this.props.Document.Set(KeyStore.Data, docs);
                                 }
                                 if (doc) {
                                     docs.Data.push(doc);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 2bdf0baa6..659cff9fe 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -12,7 +12,7 @@ import { EditableView } from "../EditableView";
 import "./CollectionTreeView.scss";
 import { CollectionView } from "./CollectionView";
 import { CollectionSubView } from "./CollectionSubView";
-import React = require("react")
+import React = require("react");
 import { COLLECTION_BORDER_WIDTH } from './CollectionBaseView';
 import { props } from 'bluebird';
 
@@ -58,7 +58,7 @@ class TreeView extends React.Component<TreeViewProps> {
             return true;
         }
         //TODO This should check if it was removed
-        this.remove(document)
+        this.remove(document);
         return addDoc(document);
     }
 
@@ -69,7 +69,7 @@ class TreeView extends React.Component<TreeViewProps> {
             case BulletType.Collapsed: bullet = "caret-right"; break;
             case BulletType.Collapsible: bullet = "caret-down"; break;
         }
-        return <div className="bullet" onClick={onClicked}>{bullet ? <FontAwesomeIcon icon={bullet} /> : ""} </div>
+        return <div className="bullet" onClick={onClicked}>{bullet ? <FontAwesomeIcon icon={bullet} /> : ""} </div>;
     }
 
     /**
@@ -93,7 +93,7 @@ class TreeView extends React.Component<TreeViewProps> {
             <div className="docContainer" ref={reference} onPointerDown={onItemDown}>
                 {editableView(this.props.document.Title)}
                 <div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>
-            </div >)
+            </div >);
     }
 
     render() {
@@ -105,7 +105,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 bulletType = BulletType.Collapsible;
                 childElements = <ul>
                     {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} moveDocument={this.move} copyOnDrag={this.props.copyOnDrag} />)}
-                </ul >
+                </ul >;
             }
             else bulletType = BulletType.Collapsed;
         }
@@ -115,7 +115,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 {this.renderTitle()}
                 {childElements ? childElements : (null)}
             </li>
-        </div>
+        </div>;
     }
 }
 
@@ -136,7 +136,7 @@ export class CollectionTreeView extends CollectionSubView {
         let childrenElement = !children || children === FieldWaiting ? (null) :
             (children.Data.map(value =>
                 <TreeView document={value} key={value.Id} deleteDoc={this.remove} moveDocument={this.props.moveDocument} copyOnDrag={copyOnDrag} />)
-            )
+            );
 
         return (
             <div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}>
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 1acc76c85..b02983a2e 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -4,7 +4,7 @@ import { KeyStore } from "../../../fields/KeyStore";
 import { ContextMenu } from "../ContextMenu";
 import { CollectionViewType, CollectionBaseView, CollectionRenderProps } from "./CollectionBaseView";
 import React = require("react");
-import "./CollectionVideoView.scss"
+import "./CollectionVideoView.scss";
 import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 
@@ -111,7 +111,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 <CollectionFreeFormView {...props} />
                 {this.props.isSelected() ? this.uIButtons : (null)}
             </>
-        )
+        );
     }
 
     render() {
@@ -119,6 +119,6 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
         return (
             <CollectionBaseView {...this.props} className="collectionVideoView-cont" contentRef={this.mainCont} onContextMenu={this.onContextMenu}>
                 {this.subView}
-            </CollectionBaseView>)
+            </CollectionBaseView>);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index b31dcc888..8abd0a02d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,4 +1,4 @@
-import * as React from 'react'
+import * as React from 'react';
 import { FieldViewProps, FieldView } from '../nodes/FieldView';
 import { CollectionBaseView, CollectionViewType, CollectionRenderProps } from './CollectionBaseView';
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
@@ -13,26 +13,26 @@ import { undoBatch } from '../../util/UndoManager';
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(CollectionView, fieldStr) }
+    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(CollectionView, fieldStr); }
 
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
         switch (type) {
-            case CollectionViewType.Schema: return (<CollectionSchemaView {...props} />)
-            case CollectionViewType.Docking: return (<CollectionDockingView {...props} />)
-            case CollectionViewType.Tree: return (<CollectionTreeView {...props} />)
+            case CollectionViewType.Schema: return (<CollectionSchemaView {...props} />);
+            case CollectionViewType.Docking: return (<CollectionDockingView {...props} />);
+            case CollectionViewType.Tree: return (<CollectionTreeView {...props} />);
             case CollectionViewType.Freeform:
             default:
-                return (<CollectionFreeFormView {...props} />)
+                return (<CollectionFreeFormView {...props} />);
         }
         return (null);
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
         if (!e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
-            ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) })
-            ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) })
-            ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) })
+            ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)) });
+            ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema)) });
+            ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree)) });
         }
     }
 
@@ -41,6 +41,6 @@ export class CollectionView extends React.Component<FieldViewProps> {
             <CollectionBaseView {...this.props} onContextMenu={this.onContextMenu}>
                 {this.SubView}
             </CollectionBaseView>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 3dfd74ec8..081b3eb6c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -32,6 +32,6 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
                 style={{ strokeWidth: `${l.length * 5}` }}
                 x1={`${x1}`} y1={`${y1}`}
                 x2={`${x2}`} y2={`${y2}`} />
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index c288e7abf..cf058090d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -17,7 +17,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
 
     HackToAvoidReactionFiringUnnecessarily?: Document = undefined;
     componentDidMount() {
-        this.HackToAvoidReactionFiringUnnecessarily = this.props.Document
+        this.HackToAvoidReactionFiringUnnecessarily = this.props.Document;
         reaction(() =>
             DocumentManager.Instance.getAllDocumentViews(this.HackToAvoidReactionFiringUnnecessarily!).
                 map(dv => dv.props.Document.GetNumber(KeyStore.X, 0)),
@@ -31,13 +31,14 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                         let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
                         let x2 = dstDoc.GetNumber(KeyStore.X, 0);
                         let x2w = dstDoc.GetNumber(KeyStore.Width, -1);
-                        if (x1w < 0 || x2w < 0 || i === j)
+                        if (x1w < 0 || x2w < 0 || i === j) {
                             continue;
+                        }
                         let dstTarg = dstDoc;
                         let srcTarg = srcDoc;
                         let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => {
                             let bdocs = brush ? brush.GetList(KeyStore.BrushingDocs, [] as Document[]) : [];
-                            return (bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false)
+                            return (bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false);
                         });
                         let brushAction = (field: ListField<Document>) => {
                             let found = findBrush(field);
@@ -64,13 +65,13 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
 
                     }
                 }
-            })
+            });
     }
     documentAnchors(view: DocumentView) {
         let equalViews = [view];
         let containerDoc = view.props.Document.GetT(KeyStore.AnnotationOn, Document);
         if (containerDoc && containerDoc instanceof Document) {
-            equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.GetPrototype()!)
+            equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.GetPrototype()!);
         }
         return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document);
     }
@@ -86,15 +87,16 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                 if (!drawnPairs.reduce((found, drawnPair) => {
                     let match = (possiblePair.a === drawnPair.a && possiblePair.b === drawnPair.b);
                     if (match) {
-                        if (!drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false))
+                        if (!drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false)) {
                             drawnPair.l.push(connection.l);
+                        }
                     }
                     return match || found;
                 }, false)) {
                     drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] });
                 }
-            })
-            return drawnPairs
+            });
+            return drawnPairs;
         }, [] as { a: Document, b: Document, l: Document[] }[]);
         return connections.map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 17656e4ae..fc832264d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -57,7 +57,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
                 let id = entry.Data[0][0];
                 let email = entry.Data[0][1];
                 let point = entry.Data[1];
-                this.drawCrosshairs("#" + v5(id, v5.URL).substring(0, 6).toUpperCase() + "22")
+                this.drawCrosshairs("#" + v5(id, v5.URL).substring(0, 6).toUpperCase() + "22");
                 return (
                     <div
                         key={id}
@@ -69,7 +69,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
                         }}
                     >
                         <canvas
-                            ref={(el) => { if (el) this.crosshairs = el }}
+                            ref={(el) => { if (el) this.crosshairs = el; }}
                             width={20}
                             height={20}
                             style={{
@@ -93,7 +93,7 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
                     </div>
                 );
             }
-        })
+        });
     }
 
     render() {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 1c3899b24..e694bc7a7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -49,7 +49,7 @@ export class CollectionFreeFormView extends CollectionSubView {
             if (dv) {
                 SelectionManager.SelectDoc(dv, true);
             }
-        })
+        });
     }
 
     public getActiveDocuments = () => {
@@ -70,8 +70,8 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     private outerElement?: HTMLDivElement;
 
-    @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0) }
-    @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0) }
+    @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0); }
+    @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0); }
     @computed get scale(): number { return this.props.Document.GetNumber(KeyStore.Scale, 1); }
     @computed get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's?
     @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
@@ -109,7 +109,7 @@ export class CollectionFreeFormView extends CollectionSubView {
                             d.SetNumber(KeyStore.Height, 300);
                         }
                         this.bringToFront(d);
-                    })
+                    });
                 }
             }
             return true;
@@ -133,8 +133,9 @@ export class CollectionFreeFormView extends CollectionSubView {
             document.addEventListener("pointerup", this.onPointerUp);
             this._lastX = this.DownX = e.pageX;
             this._lastY = this.DownY = e.pageY;
-            if (this.props.isSelected())
+            if (this.props.isSelected()) {
                 e.stopPropagation();
+            }
         }
     }
 
@@ -182,12 +183,13 @@ export class CollectionFreeFormView extends CollectionSubView {
             let transform = this.getTransform();
 
             let deltaScale = (1 - (e.deltaY / coefficient));
-            if (deltaScale * this.zoomScaling < 1 && this.isAnnotationOverlay)
+            if (deltaScale * this.zoomScaling < 1 && this.isAnnotationOverlay) {
                 deltaScale = 1 / this.zoomScaling;
+            }
             let [x, y] = transform.transformPoint(e.clientX, e.clientY);
 
-            let localTransform = this.getLocalTransform()
-            localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y)
+            let localTransform = this.getLocalTransform();
+            localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y);
             // console.log(localTransform)
 
             this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale);
@@ -209,7 +211,7 @@ export class CollectionFreeFormView extends CollectionSubView {
     onDrop = (e: React.DragEvent): void => {
         var pt = this.getTransform().transformPoint(e.pageX, e.pageY);
         super.onDrop(e, { x: pt[0], y: pt[1] });
-    };
+    }
 
     onDragOver = (): void => {
     }
@@ -228,7 +230,7 @@ export class CollectionFreeFormView extends CollectionSubView {
             }
             return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0);
         }).map((doc, index) => {
-            doc.SetNumber(KeyStore.ZIndex, index + 1)
+            doc.SetNumber(KeyStore.ZIndex, index + 1);
         });
     }
 
@@ -268,7 +270,7 @@ export class CollectionFreeFormView extends CollectionSubView {
             focus: this.focusDocument,
             parentActive: this.props.active,
             onActiveChanged: this.props.active,
-        }
+        };
     }
 
     @computed
@@ -276,10 +278,11 @@ export class CollectionFreeFormView extends CollectionSubView {
         var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
         return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => {
             var page = doc.GetNumber(KeyStore.Page, -1);
-            if (page === curPage || page === -1)
+            if (page === curPage || page === -1) {
                 prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />);
+            }
             return prev;
-        }, [] as JSX.Element[])
+        }, [] as JSX.Element[]);
     }
 
     @computed
@@ -295,8 +298,8 @@ export class CollectionFreeFormView extends CollectionSubView {
                 layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={() => false} select={() => { }} />);
     }
 
-    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform())
-    getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH)
+    getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
+    getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH);
     getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY);
     noScaling = () => 1;
     childViews = () => this.views;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 704db1d4a..1e6faafb3 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -37,7 +37,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     @action
     cleanupInteractions = (all: boolean = false) => {
         if (all) {
-            document.removeEventListener("pointermove", this.onPointerMove, true)
+            document.removeEventListener("pointermove", this.onPointerMove, true);
             document.removeEventListener("pointerup", this.onPointerUp, true);
         } else {
             this._used = true;
@@ -52,7 +52,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             this._downX = this._lastX = e.pageX;
             this._downY = this._lastY = e.pageY;
             this._used = false;
-            document.addEventListener("pointermove", this.onPointerMove, true)
+            document.addEventListener("pointermove", this.onPointerMove, true);
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
         }
@@ -94,7 +94,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         let top = this._downY < this._lastY ? this._downY : this._lastY;
         let topLeft = this.props.getTransform().transformPoint(left, top);
         let size = this.props.getTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
-        return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }
+        return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) };
     }
 
     @action
@@ -180,9 +180,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             var y = doc.GetNumber(KeyStore.Y, 0);
             var w = doc.GetNumber(KeyStore.Width, 0);
             var h = doc.GetNumber(KeyStore.Height, 0);
-            if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect))
-                selection.push(doc)
-        })
+            if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) {
+                selection.push(doc);
+            }
+        });
         return selection;
     }
 
@@ -190,7 +191,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     get marqueeDiv() {
         let p = this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY);
         let v = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
-        return <div className="marquee" style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, width: `${Math.abs(v[0])}`, height: `${Math.abs(v[1])}` }} />
+        return <div className="marquee" style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, width: `${Math.abs(v[0])}`, height: `${Math.abs(v[1])}` }} />;
     }
 
     render() {
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
index 599461f85..8eabb020a 100644
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
+++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
@@ -90,7 +90,7 @@ export class PreviewCursor extends React.Component<PreviewCursorProps>  {
                 {this.props.children}
                 <PreviewCursorPrompt setVisible={this.setVisible} getPoint={this.getPoint} getVisible={this.getVisible} />
             </div>
-        )
+        );
     }
 }
 
@@ -109,8 +109,9 @@ export class PreviewCursorPrompt extends React.Component<PromptProps> {
 
     render() {
         let p = this.props.getPoint();
-        if (this.props.getVisible() && this._promptRef.current)
+        if (this.props.getVisible() && this._promptRef.current) {
             this._promptRef.current.focus();
+        }
         return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._promptRef}
             style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, opacity: this.props.getVisible() ? 1 : 0 }}>
             I
diff --git a/src/client/views/nodes/Annotation.tsx b/src/client/views/nodes/Annotation.tsx
index e4f17940c..3e4ed6bf1 100644
--- a/src/client/views/nodes/Annotation.tsx
+++ b/src/client/views/nodes/Annotation.tsx
@@ -1,8 +1,8 @@
 import "./ImageBox.scss";
-import React = require("react")
-import { observer } from "mobx-react"
+import React = require("react");
+import { observer } from "mobx-react";
 import { observable, action } from 'mobx';
-import 'react-pdf/dist/Page/AnnotationLayer.css'
+import 'react-pdf/dist/Page/AnnotationLayer.css';
 
 interface IProps {
     Span: HTMLSpanElement;
@@ -29,13 +29,13 @@ export class Annotation extends React.Component<IProps> {
      */
     onColorChange = (e: React.PointerEvent) => {
         if (e.currentTarget.innerHTML === "r") {
-            this.props.Span.style.backgroundColor = "rgba(255,0,0, 0.3)"
+            this.props.Span.style.backgroundColor = "rgba(255,0,0, 0.3)";
         } else if (e.currentTarget.innerHTML === "b") {
-            this.props.Span.style.backgroundColor = "rgba(0,255, 255, 0.3)"
+            this.props.Span.style.backgroundColor = "rgba(0,255, 255, 0.3)";
         } else if (e.currentTarget.innerHTML === "y") {
-            this.props.Span.style.backgroundColor = "rgba(255,255,0, 0.3)"
+            this.props.Span.style.backgroundColor = "rgba(255,255,0, 0.3)";
         } else if (e.currentTarget.innerHTML === "g") {
-            this.props.Span.style.backgroundColor = "rgba(76, 175, 80, 0.3)"
+            this.props.Span.style.backgroundColor = "rgba(76, 175, 80, 0.3)";
         }
 
     }
@@ -54,11 +54,11 @@ export class Annotation extends React.Component<IProps> {
                     this.props.Highlights.splice(index, 1);
                 }
             }
-        })
+        });
 
         //removing from CurrAnno and Annotation array 
         this.props.Annotations.splice(index, 1);
-        this.props.CurrAnno.pop()
+        this.props.CurrAnno.pop();
 
         //removing span from div
         if (this.props.Span.parentElement) {
@@ -70,11 +70,11 @@ export class Annotation extends React.Component<IProps> {
                             if (item === e) {
                                 item.remove();
                             }
-                        })
+                        });
                         e.remove();
                     }
                 }
-            })
+            });
         }
 
 
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 1bd934c25..1493ff25b 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -1,18 +1,18 @@
-import React = require("react")
+import React = require("react");
 import { FieldViewProps, FieldView } from './FieldView';
 import { FieldWaiting } from '../../../fields/Field';
-import { observer } from "mobx-react"
+import { observer } from "mobx-react";
 import { ContextMenu } from "../../views/ContextMenu";
 import { observable, action } from 'mobx';
 import { KeyStore } from '../../../fields/KeyStore';
 import { AudioField } from "../../../fields/AudioField";
-import "./AudioBox.scss"
+import "./AudioBox.scss";
 import { NumberField } from "../../../fields/NumberField";
 
 @observer
 export class AudioBox extends React.Component<FieldViewProps> {
 
-    public static LayoutString() { return FieldView.LayoutString(AudioBox) }
+    public static LayoutString() { return FieldView.LayoutString(AudioBox); }
 
     constructor(props: FieldViewProps) {
         super(props);
@@ -28,7 +28,7 @@ export class AudioBox extends React.Component<FieldViewProps> {
 
 
     render() {
-        let field = this.props.Document.Get(this.props.fieldKey)
+        let field = this.props.Document.Get(this.props.fieldKey);
         let path = field === FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3" :
             field instanceof AudioField ? field.Data.href : "http://techslides.com/demos/samples/sample.mp3";
 
@@ -39,6 +39,6 @@ export class AudioBox extends React.Component<FieldViewProps> {
                     Not supported.
                 </audio>
             </div>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index dcf82ccd4..77f41105f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -35,24 +35,24 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
     @computed get nativeHeight(): number { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
 
     set width(w: number) {
-        this.props.Document.SetData(KeyStore.Width, w, NumberField)
+        this.props.Document.SetData(KeyStore.Width, w, NumberField);
         if (this.nativeWidth && this.nativeHeight) {
-            this.props.Document.SetNumber(KeyStore.Height, this.nativeHeight / this.nativeWidth * w)
+            this.props.Document.SetNumber(KeyStore.Height, this.nativeHeight / this.nativeWidth * w);
         }
     }
 
     set height(h: number) {
         this.props.Document.SetData(KeyStore.Height, h, NumberField);
         if (this.nativeWidth && this.nativeHeight) {
-            this.props.Document.SetNumber(KeyStore.Width, this.nativeWidth / this.nativeHeight * h)
+            this.props.Document.SetNumber(KeyStore.Width, this.nativeWidth / this.nativeHeight * h);
         }
     }
 
     set zIndex(h: number) {
-        this.props.Document.SetData(KeyStore.ZIndex, h, NumberField)
+        this.props.Document.SetData(KeyStore.ZIndex, h, NumberField);
     }
 
-    contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1
+    contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
 
     getTransform = (): Transform =>
         this.props.ScreenToLocalTransform()
@@ -66,7 +66,7 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView
             ScreenToLocalTransform={this.getTransform}
             PanelWidth={this.panelWidth}
             PanelHeight={this.panelHeight}
-        />
+        />;
     }
     panelWidth = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelWidth();
     panelHeight = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelHeight();
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 34cc326aa..5836da396 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -26,7 +26,7 @@ import { FieldViewProps } from "./FieldView";
 import { Without } from "../../../Utils";
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
-type BindingProps = Without<FieldViewProps, 'fieldKey'>
+type BindingProps = Without<FieldViewProps, 'fieldKey'>;
 export interface JsxBindings {
     props: BindingProps;
     [keyName: string]: BindingProps | Field;
@@ -92,7 +92,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
             bindings={this.CreateBindings()}
             jsx={this.layout}
             showWarnings={true}
-            onError={(test: any) => { console.log(test) }}
-        />
+            onError={(test: any) => { console.log(test); }}
+        />;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ab9cd2d53..9670ca6b2 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -100,8 +100,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (e.shiftKey && e.buttons === 2) {
             if (this.props.isTopMost) {
                 this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
-            } else
+            } else {
                 CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
+            }
             e.stopPropagation();
         } else {
             if (this.active && !e.isDefaultPrevented()) {
@@ -112,7 +113,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                 document.addEventListener("pointerup", this.onPointerUp);
             }
         }
-    };
+    }
 
     private dropDisposer?: DragManager.DragDropDisposer;
 
@@ -179,7 +180,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         }
         e.stopPropagation();
         e.preventDefault();
-    };
+    }
     onPointerUp = (e: PointerEvent): void => {
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
@@ -190,22 +191,22 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         ) {
             SelectionManager.SelectDoc(this, e.ctrlKey);
         }
-    };
+    }
     stopPropogation = (e: React.SyntheticEvent) => {
         e.stopPropagation();
-    };
+    }
 
     deleteClicked = (): void => {
         if (this.props.removeDocument) {
             this.props.removeDocument(this.props.Document);
         }
-    };
+    }
 
     fieldsClicked = (e: React.MouseEvent): void => {
         if (this.props.addDocument) {
             this.props.addDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false);
         }
-    };
+    }
     fullScreenClicked = (e: React.MouseEvent): void => {
         CollectionDockingView.Instance.OpenFullScreen(this.props.Document);
         ContextMenu.Instance.clearItems();
@@ -214,7 +215,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             event: this.closeFullScreenClicked
         });
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
-    };
+    }
 
     closeFullScreenClicked = (e: React.MouseEvent): void => {
         CollectionDockingView.Instance.CloseFullScreen();
@@ -224,7 +225,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             event: this.fullScreenClicked
         });
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
-    };
+    }
 
     @action
     public minimize = (): void => {
@@ -234,7 +235,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             BooleanField
         );
         SelectionManager.DeselectAll();
-    };
+    }
 
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
@@ -276,7 +277,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             );
             e.stopPropagation();
         }
-    };
+    }
 
     onDrop = (e: React.DragEvent) => {
         if (e.isDefaultPrevented()) {
@@ -290,7 +291,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             e.stopPropagation();
             e.preventDefault();
         }
-    };
+    }
 
     @action
     onContextMenu = (e: React.MouseEvent): void => {
@@ -352,14 +353,14 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         });
         ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
         SelectionManager.SelectDoc(this, e.ctrlKey);
-    };
+    }
 
     isMinimized = () => {
         let field = this.props.Document.GetT(KeyStore.Minimized, BooleanField);
         if (field && field !== FieldWaiting) {
             return field.Data;
         }
-    };
+    }
 
     @action
     expand = () => {
@@ -368,13 +369,13 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             false as boolean,
             BooleanField
         );
-    };
+    }
 
-    isSelected = () => SelectionManager.IsSelected(this)
+    isSelected = () => SelectionManager.IsSelected(this);
 
     select = (ctrlPressed: boolean) => {
         SelectionManager.SelectDoc(this, ctrlPressed);
-    };
+    }
 
     render() {
         if (!this.props.Document) {
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index d9422ae9b..07c5b332c 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 import { observer } from "mobx-react";
 import { computed } from "mobx";
 import { Field, FieldWaiting, FieldValue } from "../../../fields/Field";
@@ -7,7 +7,7 @@ import { TextField } from "../../../fields/TextField";
 import { NumberField } from "../../../fields/NumberField";
 import { RichTextField } from "../../../fields/RichTextField";
 import { ImageField } from "../../../fields/ImageField";
-import { VideoField } from "../../../fields/VideoField"
+import { VideoField } from "../../../fields/VideoField";
 import { Key } from "../../../fields/Key";
 import { FormattedTextBox } from "./FormattedTextBox";
 import { ImageBox } from "./ImageBox";
@@ -57,22 +57,22 @@ export class FieldView extends React.Component<FieldViewProps> {
     render() {
         const field = this.field;
         if (!field) {
-            return <p>{'<null>'}</p>
+            return <p>{'<null>'}</p>;
         }
         if (field instanceof TextField) {
-            return <p>{field.Data}</p>
+            return <p>{field.Data}</p>;
         }
         else if (field instanceof RichTextField) {
-            return <FormattedTextBox {...this.props} />
+            return <FormattedTextBox {...this.props} />;
         }
         else if (field instanceof ImageField) {
-            return <ImageBox {...this.props} />
+            return <ImageBox {...this.props} />;
         }
         else if (field instanceof VideoField) {
-            return <VideoBox {...this.props} />
+            return <VideoBox {...this.props} />;
         }
         else if (field instanceof AudioField) {
-            return <AudioBox {...this.props} />
+            return <AudioBox {...this.props} />;
         }
         else if (field instanceof Document) {
             return (
@@ -92,25 +92,26 @@ export class FieldView extends React.Component<FieldViewProps> {
                     ContainingCollectionView={undefined}
                     parentActive={this.props.active}
                     onActiveChanged={this.props.onActiveChanged} />
-            )
+            );
         }
         else if (field instanceof ListField) {
             return (<div>
                 {(field as ListField<Field>).Data.map(f => f instanceof Document ? f.Title : f.GetValue().toString()).join(", ")}
-            </div>)
+            </div>);
         }
         // bcz: this belongs here, but it doesn't render well so taking it out for now
         // else if (field instanceof HtmlField) {
         //     return <WebBox {...this.props} />
         // }
         else if (field instanceof NumberField) {
-            return <p>{field.Data}</p>
+            return <p>{field.Data}</p>;
         }
         else if (field !== FieldWaiting) {
-            return <p>{JSON.stringify(field.GetValue())}</p>
+            return <p>{JSON.stringify(field.GetValue())}</p>;
         }
-        else
-            return <p> {"Waiting for server..."} </p>
+        else {
+            return <p> {"Waiting for server..."} </p>;
+ }
     }
 
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 7a94be12b..beca6cdc6 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -61,7 +61,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             );
             // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
         }
-    };
+    }
 
     get FieldDoc() { return this.props.fieldKey === KeyStore.Archives ? Main.Instance._textDoc! : this.props.Document; }
     get FieldKey() { return this.props.fieldKey === KeyStore.Archives ? KeyStore.Data : this.props.fieldKey; }
@@ -81,12 +81,13 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         if (this.props.fieldKey === KeyStore.Archives) {
             this._inputReactionDisposer = reaction(() => Main.Instance._textDoc && Main.Instance._textDoc.Id,
                 () => {
-                    if (this._editorView)
-                        this._editorView!.destroy();
+                    if (this._editorView) {
+                        this._editorView.destroy();
+                    }
 
                     this.setupEditor(config);
                 }
-            )
+            );
         }
 
         this._reactionDisposer = reaction(
@@ -153,7 +154,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
             e.stopPropagation();
         }
-    };
+    }
     onPointerUp = (e: React.PointerEvent): void => {
         if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
             e.stopPropagation();
@@ -162,7 +163,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             e.preventDefault();
             Main.Instance.SetTextDoc(this.props.Document, this._ref.current!);
         }
-    };
+    }
 
     onFocused = (e: React.FocusEvent): void => {
         if (this.props.fieldKey !== KeyStore.Archives) {
@@ -191,11 +192,11 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         //     ]
         // })
         // e.stopPropagation()
-    };
+    }
 
     onPointerWheel = (e: React.WheelEvent): void => {
         e.stopPropagation();
-    };
+    }
 
     tooltipMenuPlugin() {
         return new Plugin({
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index c5f29f7b0..6b0a3a799 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -9,13 +9,13 @@ import { KeyStore } from '../../../fields/KeyStore';
 import { ContextMenu } from "../../views/ContextMenu";
 import { FieldView, FieldViewProps } from './FieldView';
 import "./ImageBox.scss";
-import React = require("react")
+import React = require("react");
 import { Utils } from '../../../Utils';
 
 @observer
 export class ImageBox extends React.Component<FieldViewProps> {
 
-    public static LayoutString() { return FieldView.LayoutString(ImageBox) }
+    public static LayoutString() { return FieldView.LayoutString(ImageBox); }
     private _ref: React.RefObject<HTMLDivElement>;
     private _imgRef: React.RefObject<HTMLImageElement>;
     private _downX: number = 0;
@@ -39,7 +39,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
     onLoad = (target: any) => {
         var h = this._imgRef.current!.naturalHeight;
         var w = this._imgRef.current!.naturalWidth;
-        this.props.Document.SetNumber(KeyStore.NativeHeight, this.props.Document.GetNumber(KeyStore.NativeWidth, 0) * h / w)
+        this.props.Document.SetNumber(KeyStore.NativeHeight, this.props.Document.GetNumber(KeyStore.NativeWidth, 0) * h / w);
     }
 
     componentDidMount() {
@@ -86,7 +86,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
                 onMoveNextRequest={action(() =>
                     this._photoIndex = (this._photoIndex + 1) % images.length
                 )}
-            />)
+            />);
         }
     }
 
@@ -96,7 +96,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
             let url = field.Data.href;
             ContextMenu.Instance.addItem({
                 description: "Copy path", event: () => {
-                    Utils.CopyText(url)
+                    Utils.CopyText(url);
                 }
             });
         }
@@ -111,6 +111,6 @@ export class ImageBox extends React.Component<FieldViewProps> {
             <div className="imageBox-cont" onPointerDown={this.onPointerDown} ref={this._ref} onContextMenu={this.specificContextMenu}>
                 <img src={path} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
                 {this.lightbox(path)}
-            </div>)
+            </div>);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 8a7f32e6d..bcac113f0 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -7,7 +7,7 @@ import { KeyStore } from '../../../fields/KeyStore';
 import { FieldView, FieldViewProps } from './FieldView';
 import "./KeyValueBox.scss";
 import { KeyValuePair } from "./KeyValuePair";
-import React = require("react")
+import React = require("react");
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Key } from '../../../fields/Key';
 import { observable, action } from "mobx";
@@ -15,7 +15,7 @@ import { observable, action } from "mobx";
 @observer
 export class KeyValueBox extends React.Component<FieldViewProps> {
 
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr) }
+    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr); }
     @observable private _keyInput: string = "";
     @observable private _valueInput: string = "";
 
@@ -36,7 +36,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
             if (this._keyInput && this._valueInput) {
                 let doc = this.props.Document.GetT(KeyStore.Data, Document);
                 if (!doc || doc === FieldWaiting) {
-                    return
+                    return;
                 }
                 let realDoc = doc;
 
@@ -55,8 +55,8 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
                         realDoc.Set(new Key(this._keyInput), dataField);
                     }
                 }
-                this._keyInput = ""
-                this._valueInput = ""
+                this._keyInput = "";
+                this._valueInput = "";
             }
         }
     }
@@ -73,7 +73,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     createTable = () => {
         let doc = this.props.Document.GetT(KeyStore.Data, Document);
         if (!doc || doc === FieldWaiting) {
-            return <tr><td>Loading...</td></tr>
+            return <tr><td>Loading...</td></tr>;
         }
         let realDoc = doc;
 
@@ -84,13 +84,13 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
                 if (!(key in ids)) {
                     ids[key] = key;
                 }
-            })
+            });
         }
 
         let rows: JSX.Element[] = [];
         let i = 0;
         for (let key in ids) {
-            rows.push(<KeyValuePair doc={realDoc} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} fieldId={key} key={key} />)
+            rows.push(<KeyValuePair doc={realDoc} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} fieldId={key} key={key} />);
         }
         return rows;
     }
@@ -125,6 +125,6 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
                     {this.newKeyValue()}
                 </tbody>
             </table>
-        </div>)
+        </div>);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index c6a0a7296..a1050dc6e 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -1,14 +1,14 @@
 import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
 import "./KeyValueBox.scss";
 import "./KeyValuePair.scss";
-import React = require("react")
+import React = require("react");
 import { FieldViewProps, FieldView } from './FieldView';
 import { Opt, Field } from '../../../fields/Field';
-import { observer } from "mobx-react"
+import { observer } from "mobx-react";
 import { observable, action } from 'mobx';
 import { Document } from '../../../fields/Document';
 import { Key } from '../../../fields/Key';
-import { Server } from "../../Server"
+import { Server } from "../../Server";
 import { EditableView } from "../EditableView";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from '../../util/Transform';
@@ -25,7 +25,7 @@ export interface KeyValuePairProps {
 export class KeyValuePair extends React.Component<KeyValuePairProps> {
 
     @observable
-    private key: Opt<Key>
+    private key: Opt<Key>;
 
     constructor(props: KeyValuePairProps) {
         super(props);
@@ -41,7 +41,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
 
     render() {
         if (!this.key) {
-            return <tr><td>error</td><td></td></tr>
+            return <tr><td>error</td><td></td></tr>;
 
         }
         let props: FieldViewProps = {
@@ -55,7 +55,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             onActiveChanged: emptyFunction,
             ScreenToLocalTransform: Transform.Identity,
             focus: emptyFunction,
-        }
+        };
         let contents = (
             <FieldView {...props} />
         );
@@ -101,6 +101,6 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
                         return false;
                     }}></EditableView></td>
             </tr>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 4791d6029..b016a3d48 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -2,8 +2,8 @@ import { observable, computed, action } from "mobx";
 import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 import { observer } from "mobx-react";
-import './LinkBox.scss'
-import { KeyStore } from '../../../fields/KeyStore'
+import './LinkBox.scss';
+import { KeyStore } from '../../../fields/KeyStore';
 import { props } from "bluebird";
 import { DocumentView } from "./DocumentView";
 import { Document } from "../../../fields/Document";
@@ -30,7 +30,7 @@ interface Props {
     linkName: String;
     pairedDoc: Document;
     type: String;
-    showEditor: () => void
+    showEditor: () => void;
 }
 
 @observer
@@ -49,15 +49,16 @@ export class LinkBox extends React.Component<Props> {
                 } else if (contextDoc instanceof Document) {
                     this.props.pairedDoc.GetTAsync(KeyStore.Page, NumberField).then((pfield: any) => {
                         contextDoc.GetTAsync(KeyStore.CurPage, NumberField).then((cfield: any) => {
-                            if (pfield !== cfield)
+                            if (pfield !== cfield) {
                                 contextDoc.SetNumber(KeyStore.CurPage, pfield.Data);
+                            }
                             let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
                             if (contextView) {
                                 contextView.props.focus(contextDoc);
                             } else {
                                 CollectionDockingView.Instance.AddRightSplit(contextDoc);
                             }
-                        })
+                        });
                     });
                 }
             });
@@ -80,7 +81,7 @@ export class LinkBox extends React.Component<Props> {
                     if (field) {
                         field.Data.splice(field.Data.indexOf(this.props.linkDoc));
                     }
-                })
+                });
             }
         });
         this.props.linkDoc.GetTAsync(KeyStore.LinkedToDocs, Document, field => {
@@ -89,7 +90,7 @@ export class LinkBox extends React.Component<Props> {
                     if (field) {
                         field.Data.splice(field.Data.indexOf(this.props.linkDoc));
                     }
-                })
+                });
             }
         });
     }
@@ -117,6 +118,6 @@ export class LinkBox extends React.Component<Props> {
                         <FontAwesomeIcon className="fa-icon-delete" icon="times" size="sm" /></div>
                 </div>
             </div>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx
index 3f7b4bf2d..bde50fed8 100644
--- a/src/client/views/nodes/LinkEditor.tsx
+++ b/src/client/views/nodes/LinkEditor.tsx
@@ -2,8 +2,8 @@ import { observable, computed, action } from "mobx";
 import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 import { observer } from "mobx-react";
-import './LinkEditor.scss'
-import { KeyStore } from '../../../fields/KeyStore'
+import './LinkEditor.scss';
+import { KeyStore } from '../../../fields/KeyStore';
 import { props } from "bluebird";
 import { DocumentView } from "./DocumentView";
 import { Document } from "../../../fields/Document";
@@ -43,7 +43,7 @@ export class LinkEditor extends React.Component<Props> {
                 <div className="save-button" onPointerDown={this.onSaveButtonPressed}>SAVE</div>
             </div>
 
-        )
+        );
     }
 
     @action
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 6c2d24630..ac09da305 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -13,7 +13,7 @@ import React = require("react");
 
 interface Props {
     docView: DocumentView;
-    changeFlyout: () => void
+    changeFlyout: () => void;
 }
 
 @observer
@@ -25,9 +25,9 @@ export class LinkMenu extends React.Component<Props> {
         return links.map(link => {
             let doc = link.GetT(key, Document);
             if (doc && doc !== FieldWaiting) {
-                return <LinkBox key={doc.Id} linkDoc={link} linkName={link.Title} pairedDoc={doc} showEditor={action(() => this._editingLink = link)} type={type} />
+                return <LinkBox key={doc.Id} linkDoc={link} linkName={link.Title} pairedDoc={doc} showEditor={action(() => this._editingLink = link)} type={type} />;
             }
-        })
+        });
     }
 
     render() {
@@ -43,11 +43,11 @@ export class LinkMenu extends React.Component<Props> {
                         {this.renderLinkItems(linkFrom, KeyStore.LinkedFromDocs, "Source: ")}
                     </div>
                 </div>
-            )
+            );
         } else {
             return (
                 <LinkEditor linkDoc={this._editingLink} showLinks={action(() => this._editingLink = undefined)}></LinkEditor>
-            )
+            );
         }
 
     }
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 774d9be3e..81ceb37f6 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -17,7 +17,7 @@ import { FieldView, FieldViewProps } from './FieldView';
 import "./ImageBox.scss";
 import "./PDFBox.scss";
 import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here
-import React = require("react")
+import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 
 /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
@@ -55,7 +55,7 @@ import { SelectionManager } from "../../util/SelectionManager";
 export class PDFBox extends React.Component<FieldViewProps> {
     public static LayoutString() { return FieldView.LayoutString(PDFBox); }
 
-    private _mainDiv = React.createRef<HTMLDivElement>()
+    private _mainDiv = React.createRef<HTMLDivElement>();
     private _pdf = React.createRef<HTMLCanvasElement>();
 
     @observable private _renderAsSvg = true;
@@ -72,7 +72,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
 
     private _currTool: any; //keeps track of current tool button reference
     private _drawToolOn: boolean = false; //boolean that keeps track of the drawing tool 
-    private _drawTool = React.createRef<HTMLButtonElement>()//drawing tool button reference
+    private _drawTool = React.createRef<HTMLButtonElement>();//drawing tool button reference
 
     private _colorTool = React.createRef<HTMLButtonElement>(); //color button reference
     private _currColor: string = "black"; //current color that user selected (for ink/pen)
@@ -85,7 +85,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
     @observable private _perPageInfo: Object[] = []; //stores pageInfo
     @observable private _pageInfo: any = { area: [], divs: [], anno: [] }; //divs is array of objects linked to anno
 
-    @observable private _currAnno: any = []
+    @observable private _currAnno: any = [];
     @observable private _interactive: boolean = false;
     @observable private _loaded: boolean = false;
 
@@ -168,24 +168,24 @@ export class PDFBox extends React.Component<FieldViewProps> {
             let obj: Object = { parentDivs: [], spans: [] };
             //@ts-ignore
             if (range.commonAncestorContainer.className === 'react-pdf__Page__textContent') { //multiline highlighting case
-                obj = this.highlightNodes(range.commonAncestorContainer.childNodes)
+                obj = this.highlightNodes(range.commonAncestorContainer.childNodes);
             } else { //single line highlighting case
-                let parentDiv = range.commonAncestorContainer.parentElement
+                let parentDiv = range.commonAncestorContainer.parentElement;
                 if (parentDiv) {
                     if (parentDiv.className === 'react-pdf__Page__textContent') { //when highlight is overwritten
-                        obj = this.highlightNodes(parentDiv.childNodes)
+                        obj = this.highlightNodes(parentDiv.childNodes);
                     } else {
                         parentDiv.childNodes.forEach((child) => {
                             if (child.nodeName === 'SPAN') {
                                 //@ts-ignore
-                                obj.parentDivs.push(parentDiv)
+                                obj.parentDivs.push(parentDiv);
                                 //@ts-ignore
-                                child.id = "highlighted"
+                                child.id = "highlighted";
                                 //@ts-ignore
-                                obj.spans.push(child)
+                                obj.spans.push(child);
                                 child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
                             }
-                        })
+                        });
                     }
                 }
             }
@@ -196,21 +196,21 @@ export class PDFBox extends React.Component<FieldViewProps> {
     }
 
     highlightNodes = (nodes: NodeListOf<ChildNode>) => {
-        let temp = { parentDivs: [], spans: [] }
+        let temp = { parentDivs: [], spans: [] };
         nodes.forEach((div) => {
             div.childNodes.forEach((child) => {
                 if (child.nodeName === 'SPAN') {
                     //@ts-ignore
-                    temp.parentDivs.push(div)
+                    temp.parentDivs.push(div);
                     //@ts-ignore
-                    child.id = "highlighted"
+                    child.id = "highlighted";
                     //@ts-ignore
-                    temp.spans.push(child)
+                    temp.spans.push(child);
                     child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
                 }
-            })
+            });
 
-        })
+        });
         return temp;
     }
 
@@ -228,8 +228,8 @@ export class PDFBox extends React.Component<FieldViewProps> {
                         index = this._pageInfo.divs.indexOf(obj);
                     }
                 }
-            })
-        })
+            });
+        });
 
         if (this._pageInfo.anno.length >= index + 1) {
             if (this._currAnno.length === 0) {
@@ -239,13 +239,13 @@ export class PDFBox extends React.Component<FieldViewProps> {
             if (this._currAnno.length === 0) { //if there are no current annotation
                 let div = span.offsetParent;
                 //@ts-ignore
-                let divX = div.style.left
+                let divX = div.style.left;
                 //@ts-ignore
-                let divY = div.style.top
+                let divY = div.style.top;
                 //slicing "px" from the end
                 divX = divX.slice(0, divX.length - 2); //gets X of the DIV element (parent of Span)
                 divY = divY.slice(0, divY.length - 2); //gets Y of the DIV element (parent of Span)
-                let annotation = <Annotation key={Utils.GenerateGuid()} Span={span} X={divX} Y={divY - 300} Highlights={this._pageInfo.divs} Annotations={this._pageInfo.anno} CurrAnno={this._currAnno} />
+                let annotation = <Annotation key={Utils.GenerateGuid()} Span={span} X={divX} Y={divY - 300} Highlights={this._pageInfo.divs} Annotations={this._pageInfo.anno} CurrAnno={this._currAnno} />;
                 this._pageInfo.anno.push(annotation);
                 this._currAnno.push(annotation);
             }
@@ -263,7 +263,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
                     this.makeEditableAndHighlight(color);
                 }
             } catch (ex) {
-                this.makeEditableAndHighlight(color)
+                this.makeEditableAndHighlight(color);
             }
         }
     }
@@ -305,7 +305,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
             }
 
             if (this._mainDiv.current) {
-                let sticky = <Sticky key={Utils.GenerateGuid()} Height={height} Width={width} X={this.initX} Y={this.initY} />
+                let sticky = <Sticky key={Utils.GenerateGuid()} Height={height} Width={width} X={this.initX} Y={this.initY} />;
                 this._pageInfo.area.push(sticky);
             }
             this._toolOn = false;
@@ -404,19 +404,19 @@ export class PDFBox extends React.Component<FieldViewProps> {
 
                         if (e instanceof HTMLCanvasElement) {
                             this._pdfCanvas = e;
-                            this._pdfContext = e.getContext("2d")
+                            this._pdfContext = e.getContext("2d");
 
                         }
 
-                    })
+                    });
                 }
-            })
+            });
         }
 
         // bcz: the number of pages should really be set when the document is imported.
         this.props.Document.SetNumber(KeyStore.NumPages, page._transport.numPages);
         if (this._perPageInfo.length === 0) { //Makes sure it only runs once
-            this._perPageInfo = [...Array(page._transport.numPages)]
+            this._perPageInfo = [...Array(page._transport.numPages)];
         }
         this._loaded = true;
     }
diff --git a/src/client/views/nodes/Sticky.tsx b/src/client/views/nodes/Sticky.tsx
index 4a4d69e90..11719831b 100644
--- a/src/client/views/nodes/Sticky.tsx
+++ b/src/client/views/nodes/Sticky.tsx
@@ -39,7 +39,7 @@ export class Sticky extends React.Component<IProps> {
       document.addEventListener("pointermove", this.drawMove);
       document.addEventListener("pointerup", this.drawUp);
     }
-  };
+  }
 
   //when user drags
   drawMove = (e: PointerEvent): void => {
@@ -49,7 +49,7 @@ export class Sticky extends React.Component<IProps> {
     //connects the point
     this.ctx.lineTo(x, y);
     this.ctx.stroke();
-  };
+  }
 
   /**
    * when user lifts the mouse, the drawing ends
@@ -58,7 +58,7 @@ export class Sticky extends React.Component<IProps> {
     this.ctx.closePath();
     console.log(this.ctx);
     document.removeEventListener("pointermove", this.drawMove);
-  };
+  }
 
   render() {
     return (
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index a08b320e8..314af64c9 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -1,4 +1,4 @@
-import React = require("react")
+import React = require("react");
 import { observer } from "mobx-react";
 import { FieldWaiting, Opt } from '../../../fields/Field';
 import { VideoField } from '../../../fields/VideoField';
@@ -13,8 +13,8 @@ import { number } from "prop-types";
 export class VideoBox extends React.Component<FieldViewProps> {
 
     private _reactionDisposer: Opt<IReactionDisposer>;
-    private _videoRef = React.createRef<HTMLVideoElement>()
-    public static LayoutString() { return FieldView.LayoutString(VideoBox) }
+    private _videoRef = React.createRef<HTMLVideoElement>();
+    public static LayoutString() { return FieldView.LayoutString(VideoBox); }
 
     constructor(props: FieldViewProps) {
         super(props);
@@ -58,7 +58,7 @@ export class VideoBox extends React.Component<FieldViewProps> {
     render() {
         let field = this.props.Document.GetT(this.props.fieldKey, VideoField);
         if (!field || field === FieldWaiting) {
-            return <div>Loading</div>
+            return <div>Loading</div>;
         }
         let path = field.Data.href;
         trace();
@@ -73,6 +73,6 @@ export class VideoBox extends React.Component<FieldViewProps> {
                     </div>
                 }
             </Measure>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index c1d389001..90ce72c41 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,9 +1,9 @@
 import "./WebBox.scss";
-import React = require("react")
+import React = require("react");
 import { WebField } from '../../../fields/WebField';
 import { FieldViewProps, FieldView } from './FieldView';
 import { FieldWaiting } from '../../../fields/Field';
-import { observer } from "mobx-react"
+import { observer } from "mobx-react";
 import { computed } from 'mobx';
 import { KeyStore } from '../../../fields/KeyStore';
 
@@ -33,6 +33,6 @@ export class WebBox extends React.Component<FieldViewProps> {
         return (
             <div className="webBox-cont"  >
                 {content}
-            </div>)
+            </div>);
     }
 }
\ No newline at end of file
diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx
index c8de33f41..11f2b0c4e 100644
--- a/src/debug/Test.tsx
+++ b/src/debug/Test.tsx
@@ -1,10 +1,10 @@
 import * as React from 'react';
 import * as ReactDOM from 'react-dom';
-import JsxParser from 'react-jsx-parser'
+import JsxParser from 'react-jsx-parser';
 
 class Hello extends React.Component<{ firstName: string, lastName: string }> {
     render() {
-        return <div>Hello {this.props.firstName} {this.props.lastName}</div>
+        return <div>Hello {this.props.firstName} {this.props.lastName}</div>;
     }
 }
 
@@ -16,8 +16,8 @@ class Test extends React.Component {
                 firstName: "First",
                 lastName: "Last"
             }
-        }
-        return <JsxParser jsx={jsx} bindings={bindings} components={{ Hello }}></JsxParser>
+        };
+        return <JsxParser jsx={jsx} bindings={bindings} components={{ Hello }}></JsxParser>;
     }
 }
 
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index f13cccd24..857da1ebb 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -40,22 +40,22 @@ class ListViewer extends React.Component<{ field: ListField<Field> }>{
                 <div>
                     {this.props.field.Data.map(field => <DebugViewer fieldId={field.Id} key={field.Id} />)}
                 </div>
-            )
+            );
         } else {
-            content = <>[...] ({this.props.field.Id})</>
+            content = <>[...] ({this.props.field.Id})</>;
         }
         return (
             <div>
                 <button onClick={action(() => this.expanded = !this.expanded)}>Toggle</button>
                 {content}
             </div >
-        )
+        );
     }
 }
 
 @observer
 class DocumentViewer extends React.Component<{ field: Document }> {
-    private keyMap: ObservableMap<string, Key> = new ObservableMap
+    private keyMap: ObservableMap<string, Key> = new ObservableMap;
 
     private disposer?: Lambda;
 
@@ -67,12 +67,12 @@ class DocumentViewer extends React.Component<{ field: Document }> {
                         if (field && field instanceof Key) {
                             this.keyMap.set(id, field);
                         }
-                    })
+                    });
                 }
             });
-        }
-        this.disposer = this.props.field._proxies.observe(f)
-        f()
+        };
+        this.disposer = this.props.field._proxies.observe(f);
+        f();
     }
 
     componentWillUnmount() {
@@ -89,8 +89,8 @@ class DocumentViewer extends React.Component<{ field: Document }> {
                     <b>({key ? key.Name : kv[0]}): </b>
                     <DebugViewer fieldId={kv[1]}></DebugViewer>
                 </div>
-            )
-        })
+            );
+        });
         return (
             <div>
                 Document ({this.props.field.Id})
@@ -98,7 +98,7 @@ class DocumentViewer extends React.Component<{ field: Document }> {
                     {fields}
                 </div>
             </div>
-        )
+        );
     }
 }
 
@@ -111,15 +111,15 @@ class DebugViewer extends React.Component<{ fieldId: string }> {
     private error?: string;
 
     constructor(props: { fieldId: string }) {
-        super(props)
-        this.update()
+        super(props);
+        this.update();
     }
 
     update() {
         Server.GetField(this.props.fieldId, action((field: Opt<Field>) => {
             this.field = field;
             if (!field) {
-                this.error = `Field with id ${this.props.fieldId} not found`
+                this.error = `Field with id ${this.props.fieldId} not found`;
             }
         }));
 
@@ -130,20 +130,20 @@ class DebugViewer extends React.Component<{ fieldId: string }> {
         if (this.field) {
             // content = this.field.ToJson();
             if (this.field instanceof ListField) {
-                content = (<ListViewer field={this.field} />)
+                content = (<ListViewer field={this.field} />);
             } else if (this.field instanceof Document) {
-                content = (<DocumentViewer field={this.field} />)
+                content = (<DocumentViewer field={this.field} />);
             } else if (this.field instanceof BasicField) {
-                content = (<FieldViewer field={this.field} />)
+                content = (<FieldViewer field={this.field} />);
             } else if (this.field instanceof Key) {
-                content = (<KeyViewer field={this.field} />)
+                content = (<KeyViewer field={this.field} />);
             } else {
-                content = (<span>Unrecognized field type</span>)
+                content = (<span>Unrecognized field type</span>);
             }
         } else if (this.error) {
-            content = <span>Field <b>{this.props.fieldId}</b> not found <button onClick={() => this.update()}>Refresh</button></span>
+            content = <span>Field <b>{this.props.fieldId}</b> not found <button onClick={() => this.update()}>Refresh</button></span>;
         } else {
-            content = <span>Field loading: {this.props.fieldId}</span>
+            content = <span>Field loading: {this.props.fieldId}</span>;
         }
         return content;
     }
@@ -165,8 +165,8 @@ class Viewer extends React.Component {
     @action
     onKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
         if (e.key === "Enter") {
-            this.ids.push(this.idToAdd)
-            this.idToAdd = ""
+            this.ids.push(this.idToAdd);
+            this.idToAdd = "";
         }
     }
 
@@ -180,7 +180,7 @@ class Viewer extends React.Component {
                     {this.ids.map(id => <DebugViewer fieldId={id} key={id}></DebugViewer>)}
                 </div>
             </>
-        )
+        );
     }
 }
 
diff --git a/src/fields/AudioField.ts b/src/fields/AudioField.ts
index 252a5b74e..996d2556d 100644
--- a/src/fields/AudioField.ts
+++ b/src/fields/AudioField.ts
@@ -25,7 +25,7 @@ export class AudioField extends BasicField<URL> {
             type: Types.Audio,
             data: this.Data.href,
             _id: this.Id
-        }
+        };
     }
 
 }
\ No newline at end of file
diff --git a/src/fields/BasicField.ts b/src/fields/BasicField.ts
index 3083a1937..17b1fc4e8 100644
--- a/src/fields/BasicField.ts
+++ b/src/fields/BasicField.ts
@@ -1,4 +1,4 @@
-import { Field, FieldId } from "./Field"
+import { Field, FieldId } from "./Field";
 import { observable, computed, action } from "mobx";
 import { Server } from "../client/Server";
 import { UndoManager } from "../client/util/UndoManager";
@@ -9,7 +9,7 @@ export abstract class BasicField<T> extends Field {
 
         this.data = data;
         if (save) {
-            Server.UpdateField(this)
+            Server.UpdateField(this);
         }
     }
 
@@ -36,7 +36,7 @@ export abstract class BasicField<T> extends Field {
         UndoManager.AddEvent({
             undo: () => this.Data = oldValue,
             redo: () => this.Data = value
-        })
+        });
         Server.UpdateField(this);
     }
 
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 4fa478f32..4584660fb 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -37,21 +37,24 @@ export class Document extends Field {
         }
     }
 
-    public Width = () => this.GetNumber(KeyStore.Width, 0)
+    public Width = () => this.GetNumber(KeyStore.Width, 0);
     public Height = () => this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? (this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0)) * this.GetNumber(KeyStore.Width, 0) : 0);
-    public Scale = () => this.GetNumber(KeyStore.Scale, 1)
+    public Scale = () => this.GetNumber(KeyStore.Scale, 1);
 
     @computed
     public get Title(): string {
         let title = this.Get(KeyStore.Title, true);
-        if (title)
-            if (title !== FieldWaiting && title instanceof TextField)
+        if (title) {
+            if (title !== FieldWaiting && title instanceof TextField) {
                 return title.Data;
+            }
             else return "-waiting-";
+        }
         let parTitle = this.GetT(KeyStore.Title, TextField);
-        if (parTitle)
+        if (parTitle) {
             if (parTitle !== FieldWaiting) return parTitle.Data + ".alias";
             else return "-waiting-.alias";
+        }
         return "-untitled-";
     }
 
@@ -398,11 +401,13 @@ export class Document extends Field {
                         }
                     }
                     else
-                        if (field instanceof Document)  // ... TODO bcz: should we copy documents or reference them
-                            copy.Set(key!, field)
-                        else if (field)
-                            copy.Set(key!, field.Copy())
-                })
+                        if (field instanceof Document) {  // ... TODO bcz: should we copy documents or reference them
+                            copy.Set(key!, field);
+                        }
+                        else if (field) {
+                            copy.Set(key!, field.Copy());
+ }
+                });
             }
         });
         return copy;
diff --git a/src/fields/DocumentReference.ts b/src/fields/DocumentReference.ts
index 9d3c209b4..6c0c1ef82 100644
--- a/src/fields/DocumentReference.ts
+++ b/src/fields/DocumentReference.ts
@@ -52,6 +52,6 @@ export class DocumentReference extends Field {
             type: Types.DocumentReference,
             data: this.document.Id,
             _id: this.Id
-        }
+        };
     }
 }
\ No newline at end of file
diff --git a/src/fields/Field.ts b/src/fields/Field.ts
index 0d0e56f77..d9db23b9e 100644
--- a/src/fields/Field.ts
+++ b/src/fields/Field.ts
@@ -65,5 +65,5 @@ export abstract class Field {
 
     abstract Copy(): Field;
 
-    abstract ToJson(): { _id: string, type: Types, data: any }
+    abstract ToJson(): { _id: string, type: Types, data: any };
 }
\ No newline at end of file
diff --git a/src/fields/HtmlField.ts b/src/fields/HtmlField.ts
index 7cbdf7e58..65665cf7a 100644
--- a/src/fields/HtmlField.ts
+++ b/src/fields/HtmlField.ts
@@ -20,6 +20,6 @@ export class HtmlField extends BasicField<string> {
             type: Types.Html,
             data: this.Data,
             _id: this.Id,
-        }
+        };
     }
 }
\ No newline at end of file
diff --git a/src/fields/ImageField.ts b/src/fields/ImageField.ts
index ef616b2ad..dd843026f 100644
--- a/src/fields/ImageField.ts
+++ b/src/fields/ImageField.ts
@@ -24,6 +24,6 @@ export class ImageField extends BasicField<URL> {
             type: Types.Image,
             data: this.Data.href,
             _id: this.Id
-        }
+        };
     }
 }
\ No newline at end of file
diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts
index 2a4ed18e7..ab706ee30 100644
--- a/src/fields/InkField.ts
+++ b/src/fields/InkField.ts
@@ -36,7 +36,7 @@ export class InkField extends BasicField<StrokeMap> {
             type: Types.Ink,
             data: this.Data,
             _id: this.Id,
-        }
+        };
     }
 
     UpdateFromServer(data: any) {
diff --git a/src/fields/Key.ts b/src/fields/Key.ts
index 00d78d516..c7f806b88 100644
--- a/src/fields/Key.ts
+++ b/src/fields/Key.ts
@@ -1,4 +1,4 @@
-import { Field, FieldId } from "./Field"
+import { Field, FieldId } from "./Field";
 import { Utils } from "../Utils";
 import { observable } from "mobx";
 import { Types } from "../server/Message";
@@ -16,7 +16,7 @@ export class Key extends Field {
 
         this.name = name;
         if (save) {
-            Server.UpdateField(this)
+            Server.UpdateField(this);
         }
     }
 
@@ -45,6 +45,6 @@ export class Key extends Field {
             type: Types.Key,
             data: this.name,
             _id: this.Id
-        }
+        };
     }
 }
\ No newline at end of file
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index e24e9c8ec..425408273 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -56,8 +56,9 @@ export namespace KeyStore {
     ];
     export function KeyLookup(keyid: string) {
         for (const key of KeyList) {
-            if (key.Id === keyid)
+            if (key.Id === keyid) {
                 return key;
+            }
         }
         return undefined;
     }
diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts
index 815a3df73..b6eab5f86 100644
--- a/src/fields/ListField.ts
+++ b/src/fields/ListField.ts
@@ -7,7 +7,7 @@ import { Field, FieldId } from "./Field";
 import { FieldMap } from "../client/SocketStub";
 
 export class ListField<T extends Field> extends BasicField<T[]> {
-    private _proxies: string[] = []
+    private _proxies: string[] = [];
     constructor(data: T[] = [], id?: FieldId, save: boolean = true) {
         super(data, save, id);
         this.updateProxies();
@@ -22,23 +22,24 @@ export class ListField<T extends Field> extends BasicField<T[]> {
     private observeDisposer: Lambda | undefined;
     private observeList(): void {
         if (this.observeDisposer) {
-            this.observeDisposer()
+            this.observeDisposer();
         }
         this.observeDisposer = observe(this.Data as IObservableArray<T>, (change: IArrayChange<T> | IArraySplice<T>) => {
-            this.updateProxies()
+            this.updateProxies();
             if (change.type === "splice") {
                 UndoManager.AddEvent({
                     undo: () => this.Data.splice(change.index, change.addedCount, ...change.removed),
                     redo: () => this.Data.splice(change.index, change.removedCount, ...change.added)
-                })
+                });
             } else {
                 UndoManager.AddEvent({
                     undo: () => this.Data[change.index] = change.oldValue,
                     redo: () => this.Data[change.index] = change.newValue
-                })
+                });
             }
-            if (!this._processingServerUpdate)
+            if (!this._processingServerUpdate) {
                 Server.UpdateField(this);
+            }
         });
     }
 
@@ -78,19 +79,23 @@ export class ListField<T extends Field> extends BasicField<T[]> {
                 var proxies = this._proxies.map(p => p);
                 var added = this.data.length < this._proxies.length;
                 var deleted = this.data.length > this._proxies.length;
-                for (let i = 0; i < dataids.length && added; i++)
+                for (let i = 0; i < dataids.length && added; i++) {
                     added = proxies.indexOf(dataids[i]) !== -1;
-                for (let i = 0; i < this._proxies.length && deleted; i++)
+                }
+                for (let i = 0; i < this._proxies.length && deleted; i++) {
                     deleted = dataids.indexOf(proxies[i]) !== -1;
+                }
 
                 this._processingServerUpdate = true;
                 for (let i = 0; i < proxies.length && added; i++) {
-                    if (dataids.indexOf(proxies[i]) === -1)
+                    if (dataids.indexOf(proxies[i]) === -1) {
                         this.Data.splice(i, 0, fields[proxies[i]] as T);
+                    }
                 }
                 for (let i = dataids.length - 1; i >= 0 && deleted; i--) {
-                    if (proxies.indexOf(dataids[i]) === -1)
+                    if (proxies.indexOf(dataids[i]) === -1) {
                         this.Data.splice(i, 1);
+                    }
                 }
                 if (!added && !deleted) {// otherwise, just rebuild the whole list
                     this.setData(proxies.map(id => fields[id] as T));
@@ -98,7 +103,7 @@ export class ListField<T extends Field> extends BasicField<T[]> {
                 this._processingServerUpdate = false;
             }
             callback(this);
-        }))
+        }));
     }
 
     ToScriptString(): string {
@@ -114,12 +119,12 @@ export class ListField<T extends Field> extends BasicField<T[]> {
             type: Types.List,
             data: this._proxies || [],
             _id: this.Id
-        }
+        };
     }
 
     static FromJson(id: string, ids: string[]): ListField<Field> {
         let list = new ListField([], id, false);
         list._proxies = ids;
-        return list
+        return list;
     }
 }
\ No newline at end of file
diff --git a/src/fields/NumberField.ts b/src/fields/NumberField.ts
index e0c8648de..45b920e31 100644
--- a/src/fields/NumberField.ts
+++ b/src/fields/NumberField.ts
@@ -1,4 +1,4 @@
-import { BasicField } from "./BasicField"
+import { BasicField } from "./BasicField";
 import { Types } from "../server/Message";
 import { FieldId } from "./Field";
 
@@ -20,6 +20,6 @@ export class NumberField extends BasicField<number> {
             _id: this.Id,
             type: Types.Number,
             data: this.Data
-        }
+        };
     }
 }
\ No newline at end of file
diff --git a/src/fields/PDFField.ts b/src/fields/PDFField.ts
index 436c1cf2b..65e179894 100644
--- a/src/fields/PDFField.ts
+++ b/src/fields/PDFField.ts
@@ -1,6 +1,6 @@
 import { BasicField } from "./BasicField";
 import { Field, FieldId } from "./Field";
-import { observable } from "mobx"
+import { observable } from "mobx";
 import { Types } from "../server/Message";
 
 
@@ -27,7 +27,7 @@ export class PDFField extends BasicField<URL> {
             type: Types.PDF,
             data: this.Data.href,
             _id: this.Id
-        }
+        };
     }
 
     @observable
diff --git a/src/fields/RichTextField.ts b/src/fields/RichTextField.ts
index 5efb43314..6f7b3074a 100644
--- a/src/fields/RichTextField.ts
+++ b/src/fields/RichTextField.ts
@@ -20,7 +20,7 @@ export class RichTextField extends BasicField<string> {
             type: Types.RichText,
             data: this.Data,
             _id: this.Id
-        }
+        };
     }
 
 }
\ No newline at end of file
diff --git a/src/fields/TextField.ts b/src/fields/TextField.ts
index 71d8ea310..69d26f42f 100644
--- a/src/fields/TextField.ts
+++ b/src/fields/TextField.ts
@@ -1,4 +1,4 @@
-import { BasicField } from "./BasicField"
+import { BasicField } from "./BasicField";
 import { FieldId } from "./Field";
 import { Types } from "../server/Message";
 
@@ -20,6 +20,6 @@ export class TextField extends BasicField<string> {
             type: Types.Text,
             data: this.Data,
             _id: this.Id
-        }
+        };
     }
 }
\ No newline at end of file
diff --git a/src/fields/TupleField.ts b/src/fields/TupleField.ts
index e2162c751..ad0f6f350 100644
--- a/src/fields/TupleField.ts
+++ b/src/fields/TupleField.ts
@@ -21,7 +21,7 @@ export class TupleField<T, U> extends BasicField<[T, U]> {
                 UndoManager.AddEvent({
                     undo: () => this.Data[change.index] = change.oldValue,
                     redo: () => this.Data[change.index] = change.newValue
-                })
+                });
                 Server.UpdateField(this);
             } else {
                 throw new Error("Why are you messing with the length of a tuple, huh?");
@@ -31,7 +31,7 @@ export class TupleField<T, U> extends BasicField<[T, U]> {
 
     protected setData(value: [T, U]) {
         if (this.observeDisposer) {
-            this.observeDisposer()
+            this.observeDisposer();
         }
         this.data = observable(value) as (T | U)[] as [T, U];
         this.observeTuple();
@@ -54,6 +54,6 @@ export class TupleField<T, U> extends BasicField<[T, U]> {
             type: Types.Tuple,
             data: this.Data,
             _id: this.Id
-        }
+        };
     }
 }
\ No newline at end of file
diff --git a/src/fields/VideoField.ts b/src/fields/VideoField.ts
index 992cc1641..d7cd7e968 100644
--- a/src/fields/VideoField.ts
+++ b/src/fields/VideoField.ts
@@ -24,7 +24,7 @@ export class VideoField extends BasicField<URL> {
             type: Types.Video,
             data: this.Data.href,
             _id: this.Id
-        }
+        };
     }
 
 }
\ No newline at end of file
diff --git a/src/fields/WebField.ts b/src/fields/WebField.ts
index 0cbcc6d33..6023e9e6b 100644
--- a/src/fields/WebField.ts
+++ b/src/fields/WebField.ts
@@ -24,7 +24,7 @@ export class WebField extends BasicField<URL> {
             type: Types.Web,
             data: this.Data.href,
             _id: this.Id
-        }
+        };
     }
 
 }
\ No newline at end of file
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index c3684a0eb..ec89a1194 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -22,7 +22,7 @@ import { Opt } from '../fields/Field';
 // }
 
 const onFileLoad = async (file: any) => {
-    let imgPrev = document.getElementById("img_preview")
+    let imgPrev = document.getElementById("img_preview");
     if (imgPrev) {
         let files: File[] = file.target.files;
         if (files.length !== 0) {
@@ -30,15 +30,15 @@ const onFileLoad = async (file: any) => {
             let formData = new FormData();
             formData.append("file", files[0]);
 
-            const upload = window.location.origin + "/upload"
+            const upload = window.location.origin + "/upload";
             const res = await fetch(upload, {
                 method: 'POST',
                 body: formData
             });
             const json = await res.json();
             json.map(async (file: any) => {
-                let path = window.location.origin + file
-                var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 })
+                let path = window.location.origin + file;
+                var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 });
 
                 const res = await rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId));
                 if (!res) {
@@ -47,12 +47,12 @@ const onFileLoad = async (file: any) => {
                 const field = await Server.GetField(res);
                 let pending: Opt<Document>;
                 if (field instanceof Document) {
-                    pending = await field.GetTAsync(KeyStore.OptionalRightCollection, Document)
+                    pending = await field.GetTAsync(KeyStore.OptionalRightCollection, Document);
                 }
                 if (pending) {
                     pending.GetOrCreateAsync(KeyStore.Data, ListField, list => {
                         list.Data.push(doc);
-                    })
+                    });
                 }
             });
 
@@ -61,7 +61,7 @@ const onFileLoad = async (file: any) => {
             //imgPrev.setAttribute("src", window.location.origin + files[0].name)
         }
     }
-}
+};
 
 ReactDOM.render((
     <div className="imgupload_cont">
diff --git a/src/server/Client.ts b/src/server/Client.ts
index 6b8841658..02402a5a0 100644
--- a/src/server/Client.ts
+++ b/src/server/Client.ts
@@ -2,14 +2,14 @@ import { computed } from "mobx";
 
 export class Client {
     constructor(guid: string) {
-        this.guid = guid
+        this.guid = guid;
     }
 
     private guid: string;
 
     @computed
     public get GUID(): string {
-        return this.guid
+        return this.guid;
     }
 
 }
\ No newline at end of file
diff --git a/src/server/authentication/config/passport.ts b/src/server/authentication/config/passport.ts
index b6fe15655..d42741410 100644
--- a/src/server/authentication/config/passport.ts
+++ b/src/server/authentication/config/passport.ts
@@ -1,4 +1,4 @@
-import * as passport from 'passport'
+import * as passport from 'passport';
 import * as passportLocal from 'passport-local';
 import * as mongodb from 'mongodb';
 import * as _ from "lodash";
@@ -22,7 +22,7 @@ passport.deserializeUser<any, any>((id, done) => {
 passport.use(new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => {
     User.findOne({ email: email.toLowerCase() }, (error: any, user: any) => {
         if (error) return done(error);
-        if (!user) return done(undefined, false, { message: "Invalid email or password" }) // invalid email
+        if (!user) return done(undefined, false, { message: "Invalid email or password" }); // invalid email
         user.comparePassword(password, (error: Error, isMatch: boolean) => {
             if (error) return done(error);
             if (!isMatch) return done(undefined, false, { message: "Invalid email or password" }); // invalid password
@@ -37,7 +37,7 @@ export let isAuthenticated = (req: Request, res: Response, next: NextFunction) =
         return next();
     }
     return res.redirect(RouteStore.login);
-}
+};
 
 export let isAuthorized = (req: Request, res: Response, next: NextFunction) => {
     const provider = req.path.split("/").slice(-1)[0];
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 835432c8e..b08c1aebe 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -1,7 +1,7 @@
 import * as React from 'react';
 import { observable, action, configure, reaction, computed, ObservableMap, runInAction } from 'mobx';
 import { observer } from "mobx-react";
-import './WorkspacesMenu.css'
+import './WorkspacesMenu.css';
 import { Document } from '../../../fields/Document';
 import { EditableView } from '../../../client/views/EditableView';
 import { KeyStore } from '../../../fields/KeyStore';
diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts
index 2bbb334b5..1dacdf3fa 100644
--- a/src/server/authentication/controllers/user_controller.ts
+++ b/src/server/authentication/controllers/user_controller.ts
@@ -109,12 +109,12 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
     }
 
     passport.authenticate("local", (err: Error, user: DashUserModel, info: IVerifyOptions) => {
-        if (err) { next(err); return }
+        if (err) { next(err); return; }
         if (!user) {
             return res.redirect(RouteStore.signup);
         }
         req.logIn(user, (err) => {
-            if (err) { next(err); return }
+            if (err) { next(err); return; }
             res.redirect(RouteStore.home);
         });
     })(req, res, next);
@@ -132,14 +132,14 @@ export let getLogout = (req: Request, res: Response) => {
         sess.destroy((err) => { if (err) { console.log(err); } });
     }
     res.redirect(RouteStore.login);
-}
+};
 
 export let getForgot = function (req: Request, res: Response) {
     res.render("forgot.pug", {
         title: "Recover Password",
         user: req.user,
     });
-}
+};
 
 export let postForgot = function (req: Request, res: Response, next: NextFunction) {
     const email = req.body.email;
@@ -152,14 +152,14 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio
                     return;
                 }
                 done(null, buffer.toString('hex'));
-            })
+            });
         },
         function (token: string, done: any) {
             User.findOne({ email }, function (err, user: DashUserModel) {
                 if (!user) {
                     // NO ACCOUNT WITH SUBMITTED EMAIL
                     res.redirect(RouteStore.forgot);
-                    return
+                    return;
                 }
                 user.passwordResetToken = token;
                 user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 HOUR
@@ -193,8 +193,8 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio
     ], function (err) {
         if (err) return next(err);
         res.redirect(RouteStore.forgot);
-    })
-}
+    });
+};
 
 export let getReset = function (req: Request, res: Response) {
     User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err, user: DashUserModel) {
@@ -206,7 +206,7 @@ export let getReset = function (req: Request, res: Response) {
             user: req.user,
         });
     });
-}
+};
 
 export let postReset = function (req: Request, res: Response) {
     async.waterfall([
@@ -263,4 +263,4 @@ export let postReset = function (req: Request, res: Response) {
     ], function (err) {
         res.redirect(RouteStore.login);
     });
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 0ac85b446..13eddafbf 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -70,7 +70,7 @@ export class CurrentUserUtils {
         let doc = new Document(id);
 
         doc.Set(KeyStore.Workspaces, new ListField<Document>());
-        doc.Set(KeyStore.OptionalRightCollection, Documents.SchemaDocument([], { title: "Pending documents" }))
+        doc.Set(KeyStore.OptionalRightCollection, Documents.SchemaDocument([], { title: "Pending documents" }));
         return doc;
     }
 
@@ -81,7 +81,7 @@ export class CurrentUserUtils {
                 CurrentUserUtils.curr_id = obj.id as string;
                 CurrentUserUtils.curr_email = obj.email as string;
             } else {
-                throw new Error("There should be a user! Why does Dash think there isn't one?")
+                throw new Error("There should be a user! Why does Dash think there isn't one?");
             }
         });
         let userDocPromise = rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(id => {
@@ -92,9 +92,9 @@ export class CurrentUserUtils {
                     } else {
                         this.user_document = this.createUserDocument(id);
                     }
-                })
+                });
             } else {
-                throw new Error("There should be a user id! Why does Dash think there isn't one?")
+                throw new Error("There should be a user id! Why does Dash think there isn't one?");
             }
         });
         return Promise.all([userPromise, userDocPromise]);
diff --git a/src/server/authentication/models/user_model.ts b/src/server/authentication/models/user_model.ts
index 81580aad5..1c6926517 100644
--- a/src/server/authentication/models/user_model.ts
+++ b/src/server/authentication/models/user_model.ts
@@ -2,7 +2,7 @@
 import * as bcrypt from "bcrypt-nodejs";
 //@ts-ignore
 import * as mongoose from "mongoose";
-var url = 'mongodb://localhost:27017/Dash'
+var url = 'mongodb://localhost:27017/Dash';
 
 mongoose.connect(url, { useNewUrlParser: true });
 
diff --git a/src/server/database.ts b/src/server/database.ts
index 415acc09a..0bc806253 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -1,15 +1,15 @@
 import * as mongodb from 'mongodb';
 
 export class Database {
-    public static Instance = new Database()
+    public static Instance = new Database();
     private MongoClient = mongodb.MongoClient;
     private url = 'mongodb://localhost:27017/Dash';
     private db?: mongodb.Db;
 
     constructor() {
         this.MongoClient.connect(this.url, (err, client) => {
-            this.db = client.db()
-        })
+            this.db = client.db();
+        });
     }
 
     private currentWrites: { [_id: string]: Promise<void> } = {};
@@ -30,19 +30,19 @@ export class Database {
                     //     console.log(JSON.stringify(res.result));
                     // }
                     if (this.currentWrites[id] === promise) {
-                        delete this.currentWrites[id]
+                        delete this.currentWrites[id];
                     }
                     if (resolve) {
                         resolve();
                     }
                     callback();
                 });
-            }
+            };
             if (prom) {
                 const newProm: Promise<void> = prom.then(() => run(newProm));
                 this.currentWrites[id] = newProm;
             } else {
-                const newProm: Promise<void> = new Promise<void>(res => run(newProm, res))
+                const newProm: Promise<void> = new Promise<void>(res => run(newProm, res));
                 this.currentWrites[id] = newProm;
             }
         }
@@ -61,7 +61,7 @@ export class Database {
                 let collection = this.db.collection(collectionName);
                 collection.deleteMany({}, res);
             }
-        })
+        });
     }
 
     public insert(kvpairs: any) {
@@ -70,7 +70,7 @@ export class Database {
             collection.insertOne(kvpairs, (err: any, res: any) => {
                 if (err) {
                     // console.log(err)
-                    return
+                    return;
                 }
             });
         }
@@ -81,30 +81,30 @@ export class Database {
         if (this.db) {
             let collection = this.db.collection('documents');
             collection.findOne({ _id: id }, (err: any, res: any) => {
-                result = res
+                result = res;
                 if (!result) {
-                    fn(undefined)
+                    fn(undefined);
                 }
-                fn(result)
-            })
-        };
+                fn(result);
+            });
+        }
     }
 
     public getDocuments(ids: string[], fn: (res: any) => void) {
         if (this.db) {
             let collection = this.db.collection('documents');
-            let cursor = collection.find({ _id: { "$in": ids } })
+            let cursor = collection.find({ _id: { "$in": ids } });
             cursor.toArray((err, docs) => {
                 if (err) {
                     console.log(err.message);
                     console.log(err.errmsg);
                 }
                 fn(docs);
-            })
-        };
+            });
+        }
     }
 
     public print() {
-        console.log("db says hi!")
+        console.log("db says hi!");
     }
 }
diff --git a/src/server/index.ts b/src/server/index.ts
index f60e6e293..b9c7448b4 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1,10 +1,10 @@
-import * as express from 'express'
-const app = express()
-import * as webpack from 'webpack'
+import * as express from 'express';
+const app = express();
+import * as webpack from 'webpack';
 import * as wdm from 'webpack-dev-middleware';
 import * as whm from 'webpack-hot-middleware';
-import * as path from 'path'
-import * as formidable from 'formidable'
+import * as path from 'path';
+import * as formidable from 'formidable';
 import * as passport from 'passport';
 import { MessageStore, Transferable } from "./Message";
 import { Client } from './Client';
@@ -13,7 +13,7 @@ import { Utils } from '../Utils';
 import { ObservableMap } from 'mobx';
 import { FieldId, Field } from '../fields/Field';
 import { Database } from './database';
-import * as io from 'socket.io'
+import * as io from 'socket.io';
 import { getLogin, postLogin, getSignup, postSignup, getLogout, postReset, getForgot, postForgot, getReset } from './authentication/controllers/user_controller';
 const config = require('../../webpack.config');
 const compiler = webpack(config);
@@ -31,19 +31,19 @@ const MongoStore = require('connect-mongo')(session);
 const mongoose = require('mongoose');
 import { DashUserModel } from './authentication/models/user_model';
 import * as fs from 'fs';
-import * as request from 'request'
+import * as request from 'request';
 import { RouteStore } from './RouteStore';
-import { exec } from 'child_process'
+import { exec } from 'child_process';
 
 const download = (url: string, dest: fs.PathLike) => {
     request.get(url).pipe(fs.createWriteStream(dest));
-}
+};
 
 const mongoUrl = 'mongodb://localhost:27017/Dash';
-mongoose.connect(mongoUrl)
+mongoose.connect(mongoUrl);
 mongoose.connection.on('connected', function () {
     console.log("connected");
-})
+});
 
 // SESSION MANAGEMENT AND AUTHENTICATION MIDDLEWARE
 // ORDER OF IMPORTS MATTERS
@@ -73,7 +73,7 @@ app.use((req, res, next) => {
 
 app.get("/hello", (req, res) => {
     res.send("<p>Hello</p>");
-})
+});
 
 enum Method {
     GET,
@@ -98,7 +98,7 @@ function addSecureRoute(method: Method,
         const dashUser: DashUserModel = req.user;
         if (!dashUser) return onRejection(res);
         handler(dashUser, res, req);
-    }
+    };
     subscribers.forEach(route => {
         switch (method) {
             case Method.GET:
@@ -116,7 +116,7 @@ function addSecureRoute(method: Method,
 let FieldStore: ObservableMap<FieldId, Field> = new ObservableMap();
 
 app.use(express.static(__dirname + RouteStore.public));
-app.use(RouteStore.images, express.static(__dirname + RouteStore.public))
+app.use(RouteStore.images, express.static(__dirname + RouteStore.public));
 
 app.get("/pull", (req, res) => {
     exec('"C:\\Program Files\\Git\\git-bash.exe" -c "git pull"', (err, stdout, stderr) => {
@@ -125,7 +125,7 @@ app.get("/pull", (req, res) => {
             return;
         }
         res.redirect("/");
-    })
+    });
 });
 
 // GETTERS
@@ -178,13 +178,13 @@ addSecureRoute(
 addSecureRoute(
     Method.POST,
     (user, res, req) => {
-        let form = new formidable.IncomingForm()
-        form.uploadDir = __dirname + "/public/files/"
-        form.keepExtensions = true
+        let form = new formidable.IncomingForm();
+        form.uploadDir = __dirname + "/public/files/";
+        form.keepExtensions = true;
         // let path = req.body.path;
-        console.log("upload")
+        console.log("upload");
         form.parse(req, (err, fields, files) => {
-            console.log("parsing")
+            console.log("parsing");
             let names: any[] = [];
             for (const name in files) {
                 let file = files[name];
@@ -211,8 +211,8 @@ app.post(RouteStore.login, postLogin);
 app.get(RouteStore.logout, getLogout);
 
 // FORGOT PASSWORD EMAIL HANDLING
-app.get(RouteStore.forgot, getForgot)
-app.post(RouteStore.forgot, postForgot)
+app.get(RouteStore.forgot, getForgot);
+app.post(RouteStore.forgot, postForgot);
 
 // RESET PASSWORD EMAIL HANDLING
 app.get(RouteStore.reset, getReset);
@@ -232,32 +232,32 @@ app.get(RouteStore.deleteAll, (req, res) => {
 
 app.use(wdm(compiler, {
     publicPath: config.output.publicPath
-}))
+}));
 
-app.use(whm(compiler))
+app.use(whm(compiler));
 
 // start the Express server
 app.listen(port, () => {
     console.log(`server started at http://localhost:${port}`);
-})
+});
 
 const server = io();
 interface Map {
     [key: string]: Client;
 }
-let clients: Map = {}
+let clients: Map = {};
 
 server.on("connection", function (socket: Socket) {
-    console.log("a user has connected")
+    console.log("a user has connected");
 
-    Utils.Emit(socket, MessageStore.Foo, "handshooken")
+    Utils.Emit(socket, MessageStore.Foo, "handshooken");
 
-    Utils.AddServerHandler(socket, MessageStore.Bar, barReceived)
-    Utils.AddServerHandler(socket, MessageStore.SetField, (args) => setField(socket, args))
-    Utils.AddServerHandlerCallback(socket, MessageStore.GetField, getField)
-    Utils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields)
-    Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields)
-})
+    Utils.AddServerHandler(socket, MessageStore.Bar, barReceived);
+    Utils.AddServerHandler(socket, MessageStore.SetField, (args) => setField(socket, args));
+    Utils.AddServerHandlerCallback(socket, MessageStore.GetField, getField);
+    Utils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields);
+    Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields);
+});
 
 function deleteFields() {
     return Database.Instance.deleteAll();
@@ -276,12 +276,12 @@ function barReceived(guid: String) {
 function getField([id, callback]: [string, (result: any) => void]) {
     Database.Instance.getDocument(id, (result: any) => {
         if (result) {
-            callback(result)
+            callback(result);
         }
         else {
-            callback(undefined)
+            callback(undefined);
         }
-    })
+    });
 }
 
 function getFields([ids, callback]: [string[], (result: any) => void]) {
@@ -291,7 +291,7 @@ function getFields([ids, callback]: [string[], (result: any) => void]) {
 function setField(socket: Socket, newValue: Transferable) {
     Database.Instance.update(newValue._id, newValue, () => {
         socket.broadcast.emit(MessageStore.SetField.Message, newValue);
-    })
+    });
 }
 
 server.listen(serverPort);
diff --git a/test/test.ts b/test/test.ts
index db24cae5f..16cace026 100644
--- a/test/test.ts
+++ b/test/test.ts
@@ -1,6 +1,6 @@
 import { NumberField } from "../src/fields/NumberField";
 import { expect } from 'chai';
-import 'mocha'
+import 'mocha';
 import { Key } from "../src/fields/Key";
 import { Document } from "../src/fields/Document";
 import { autorun, reaction } from "mobx";
@@ -17,7 +17,7 @@ describe('Number Controller', () => {
     it('Should update', () => {
         const numController = new NumberField(15);
         let ran = false;
-        reaction(() => numController.Data, (data) => { ran = true; })
+        reaction(() => numController.Data, (data) => { ran = true; });
         expect(ran).to.equal(false);
         numController.Data = 5;
         expect(ran).to.equal(true);
@@ -42,7 +42,7 @@ describe("Document", () => {
         let key = new Key("Test");
         let key2 = new Key("Test2");
         let ran = false;
-        reaction(() => doc.Get(key), (field) => { ran = true });
+        reaction(() => doc.Get(key), (field) => { ran = true; });
         expect(ran).to.equal(false);
 
         doc.Set(key2, new NumberField(4));
diff --git a/tslint.json b/tslint.json
index 54876916e..aa4dee4e5 100644
--- a/tslint.json
+++ b/tslint.json
@@ -27,14 +27,14 @@
         "arrow-return-shorthand": true,
         // "object-literal-shorthand": true,
         // "object-literal-sort-keys": true,
-        // "semicolon": [
-        //     true,
-        //     "always"
-        // ],
-        // "curly": [
-        //     true,
-        //     "ignore-same-line"
-        // ],
+        "semicolon": [
+            true,
+            "always"
+        ],
+        "curly": [
+            true,
+            "ignore-same-line"
+        ],
         // "quotemark": [
         //     true,
         //     "double",
-- 
cgit v1.2.3-70-g09d2


From 78e098c4ecb95b90482e7d27fd82fb857de96bb4 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 9 Apr 2019 08:46:15 -0400
Subject: fixed dragging linkbutton to show linked docs

---
 src/client/views/DocumentDecorations.tsx            |  7 +++----
 src/client/views/collections/CollectionViewBase.tsx | 18 ------------------
 2 files changed, 3 insertions(+), 22 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 4a7502072..40da98d34 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -266,7 +266,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     if (doc)
                         moddrag.push(doc);
                 }
-                let dragData = new DragManager.DocumentDragData(moddrag);
+                let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
                 DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, {
                     handlers: {
                         dragComplete: action(() => { }),
@@ -407,9 +407,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             let linkCount = linkToSize + linkFromSize;
             linkButton = (<Flyout
                 anchorPoint={anchorPoints.RIGHT_TOP}
-                content={
-                    <LinkMenu docView={selFirst} changeFlyout={this.changeFlyoutContent} />
-                }>
+                content={<LinkMenu docView={selFirst}
+                    changeFlyout={this.changeFlyoutContent} />}>
                 <div className={"linkButton-" + (selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length ? "nonempty" : "empty")} onPointerDown={this.onLinkButtonDown} >{linkCount}</div>
             </Flyout>);
         }
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 7cf49e215..1f16e8313 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -94,24 +94,6 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             e.stopPropagation();
             return added;
         }
-        if (de.data instanceof DragManager.LinkDragData) {
-            let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
-            if (sourceDoc) runInAction(() => {
-                let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document)
-                if (srcTarg && srcTarg != FieldWaiting) {
-                    let linkDocs = srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]);
-                    linkDocs.map(linkDoc => {
-                        let targDoc = linkDoc.GetT(KeyStore.LinkedToDocs, Document);
-                        if (targDoc && targDoc != FieldWaiting) {
-                            let dropdoc = targDoc.MakeDelegate();
-                            de.data.droppedDocuments.push(dropdoc);
-                            this.props.addDocument(dropdoc, false);
-                        }
-                    })
-                }
-            })
-            return true;
-        }
         return false;
     }
 
-- 
cgit v1.2.3-70-g09d2


From e0b3c759880639bf56f9b8b39ea2e38c5cbad8a6 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 10 Apr 2019 14:28:25 -0400
Subject: fixed extra rendering for collections.

---
 src/client/Server.ts                               | 10 +++----
 .../dash-nodes/HistogramBoxPrimitives.tsx          |  6 ++--
 src/client/util/DragManager.ts                     |  4 +--
 src/client/util/SelectionManager.ts                |  2 +-
 src/client/views/DocumentDecorations.tsx           |  5 ++--
 src/client/views/Main.scss                         | 24 +++++++--------
 src/client/views/Main.tsx                          | 19 ++++++++----
 .../views/collections/CollectionDockingView.tsx    |  4 +--
 src/client/views/collections/CollectionPDFView.tsx |  3 +-
 .../views/collections/CollectionSchemaView.tsx     |  4 +--
 src/client/views/collections/CollectionSubView.tsx |  3 +-
 .../views/collections/CollectionVideoView.tsx      |  3 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  7 +++--
 src/client/views/nodes/DocumentView.tsx            | 35 ++++++++++++++--------
 src/client/views/nodes/FieldView.tsx               | 10 +++----
 src/client/views/nodes/FormattedTextBox.tsx        |  4 +--
 src/client/views/nodes/VideoBox.tsx                |  2 +-
 17 files changed, 84 insertions(+), 61 deletions(-)

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

diff --git a/src/client/Server.ts b/src/client/Server.ts
index 857101a33..228d94a7b 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -1,10 +1,10 @@
 import { Key } from "../fields/Key";
-import { ObservableMap, action, reaction } from "mobx";
+import { ObservableMap, action, reaction, runInAction } from "mobx";
 import { Field, FieldWaiting, FIELD_WAITING, Opt, FieldId } from "../fields/Field";
 import { Document } from "../fields/Document";
 import { SocketStub, FieldMap } from "./SocketStub";
 import * as OpenSocket from 'socket.io-client';
-import { Utils } from "./../Utils";
+import { Utils, emptyFunction } from "./../Utils";
 import { MessageStore, Types } from "./../server/Message";
 
 export class Server {
@@ -59,7 +59,7 @@ export class Server {
     public static GetFields(fieldIds: FieldId[]): Promise<{ [id: string]: Field }>;
     public static GetFields(fieldIds: FieldId[], callback: (fields: FieldMap) => any): void;
     public static GetFields(fieldIds: FieldId[], callback?: (fields: FieldMap) => any): Promise<FieldMap> | void {
-        let fn = (cb: (fields: FieldMap) => void) => {
+        let fn = (cb: (fields: FieldMap) => void) => runInAction(() => {
 
             let neededFieldIds: FieldId[] = [];
             let waitingFieldIds: FieldId[] = [];
@@ -104,7 +104,7 @@ export class Server {
                         }
                     }, { fireImmediately: true });
             }));
-        };
+        });
         if (callback) {
             fn(callback);
         } else {
@@ -167,7 +167,7 @@ export class Server {
             if (f) {
                 // console.log("Applying        : " + field._id);
                 f.UpdateFromServer(field.data);
-                f.init(() => { });
+                f.init(emptyFunction);
             } else {
                 // console.log("Not applying wa : " + field._id);
             }
diff --git a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
index 4c5bdb14b..721bf6a89 100644
--- a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
@@ -1,7 +1,7 @@
 import React = require("react");
 import { computed, observable, reaction, runInAction, trace, action } from "mobx";
 import { observer } from "mobx-react";
-import { Utils as DashUtils } from '../../../Utils';
+import { Utils as DashUtils, emptyFunction } from '../../../Utils';
 import { FilterModel } from "../../northstar/core/filter/FilterModel";
 import { ModelHelpers } from "../../northstar/model/ModelHelpers";
 import { ArrayUtil } from "../../northstar/utils/ArrayUtil";
@@ -49,7 +49,7 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
     private getSelectionToggle(binPrimitives: HistogramBinPrimitive[], allBrushIndex: number, filterModel: FilterModel) {
         let rawAllBrushPrim = ArrayUtil.FirstOrDefault(binPrimitives, bp => bp.BrushIndex === allBrushIndex);
         if (!rawAllBrushPrim) {
-            return () => { };
+            return emptyFunction;
         }
         let allBrushPrim = rawAllBrushPrim;
         return () => runInAction(() => {
@@ -97,7 +97,7 @@ export class HistogramBoxPrimitives extends React.Component<HistogramPrimitivesP
         let trans1Ypercent = `${yFrom / this.renderDimension * 100}%`;
         return <line className="histogramboxprimitives-line" key={DashUtils.GenerateGuid()} x1={trans1Xpercent} x2={`${trans2Xpercent}`} y1={trans1Ypercent} y2={`${trans2Ypercent}`} />;
     }
-    drawRect(r: PIXIRectangle, barAxis: number, color: number | undefined, classExt: string, tapHandler: () => void = () => { }) {
+    drawRect(r: PIXIRectangle, barAxis: number, color: number | undefined, classExt: string, tapHandler: () => void = emptyFunction) {
         if (r.height < 0) {
             r.y += r.height;
             r.height = -r.height;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4849ae9f7..f7395578f 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -4,7 +4,7 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie
 import { CollectionView } from "../views/collections/CollectionView";
 import { DocumentDecorations } from "../views/DocumentDecorations";
 import { DocumentView } from "../views/nodes/DocumentView";
-import { returnFalse } from "../../Utils";
+import { returnFalse, emptyFunction } from "../../Utils";
 
 export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
     let onRowMove = action((e: PointerEvent): void => {
@@ -224,7 +224,7 @@ export namespace DragManager {
                 CollectionDockingView.Instance.StartOtherDrag(docs, {
                     pageX: e.pageX,
                     pageY: e.pageY,
-                    preventDefault: () => { },
+                    preventDefault: emptyFunction,
                     button: 0
                 });
             }
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 5ddaafc72..c6b8c7b0d 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -48,7 +48,7 @@ export namespace SelectionManager {
 
         manager.DeselectAll();
         if (found) manager.SelectDoc(found, false);
-        Main.Instance.SetTextDoc(undefined, undefined);
+        Main.Instance.SetTextDoc(undefined, undefined, undefined);
     }
 
     export function SelectedDocuments(): Array<DocumentView> {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 28af46358..b7bf727f1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -15,6 +15,7 @@ import { DocumentView } from "./nodes/DocumentView";
 import { LinkMenu } from "./nodes/LinkMenu";
 import React = require("react");
 import { FieldWaiting } from "../../fields/Field";
+import { emptyFunction } from "../../Utils";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -217,7 +218,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
             DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, {
                 handlers: {
-                    dragComplete: action(() => { }),
+                    dragComplete: action(emptyFunction),
                 },
                 hideSource: false
             });
@@ -262,7 +263,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
                 DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, {
                     handlers: {
-                        dragComplete: action(() => { }),
+                        dragComplete: action(emptyFunction),
                     },
                     hideSource: false
                 });
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index fe7f007b0..8ef6b83f1 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -169,21 +169,21 @@ button:hover {
     overflow: scroll;
 }
 .mainDiv-textInput {
-    background:pink;
-        width: 200px;
-        height: 200px;
+    background-color: rgba(248, 6, 6, 0.1);
+    width: 200px;
+    height: 200px;
+    position:absolute;
+    overflow: visible;
+    top: 0;
+    left: 0;
+    .formattedTextBox-cont {
+        background-color: rgba(248, 6, 6, 0.1);
+        width: 100%;
+        height: 100%;
         position:absolute;
-        overflow: visible;
         top: 0;
         left: 0;
-        .formattedTextBox-cont {
-            background:pink;
-            width: 100%;
-            height: 100%;
-            position:absolute;
-            top: 0;
-            left: 0;
-    }
+}
 }
 #mainContent-div {
     width:100%;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 012633bed..2751b1899 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -23,7 +23,7 @@ import { Documents } from '../documents/Documents';
 import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
 import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
 import { Gateway, Settings } from '../northstar/manager/Gateway';
-import { AggregateFunction, Catalog } from '../northstar/model/idea/idea';
+import { AggregateFunction, Catalog, Point } from '../northstar/model/idea/idea';
 import '../northstar/model/ModelExtensions';
 import { HistogramOperation } from '../northstar/operations/HistogramOperation';
 import '../northstar/utils/Extensions';
@@ -204,10 +204,12 @@ export class Main extends React.Component {
 
     @observable _textDoc?: Document = undefined;
     _textRect: any;
+    _textXf: Transform = Transform.Identity();
     @action
-    SetTextDoc(textDoc?: Document, div?: HTMLDivElement) {
+    SetTextDoc(textDoc?: Document, div?: HTMLDivElement, tx?: Transform) {
         this._textDoc = undefined;
         this._textDoc = textDoc;
+        this._textXf = tx ? tx : Transform.Identity();
         if (div) {
             this._textRect = div.getBoundingClientRect();
         }
@@ -220,8 +222,15 @@ export class Main extends React.Component {
             let y: number = this._textRect.y;
             let w: number = this._textRect.width;
             let h: number = this._textRect.height;
-            return <div className="mainDiv-textInput" style={{ transform: `translate(${x}px, ${y}px)`, width: `${w}px`, height: `${h}px` }} >
-                <FormattedTextBox fieldKey={KeyStore.Archives} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={Transform.Identity} focus={(doc) => { }} />
+            let t = this._textXf.transformPoint(0, 0);
+            let s = this._textXf.transformPoint(1, 0);
+            s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
+            return <div className="mainDiv-textInput" style={{ transform: `translate(${x}px, ${y}px) scale(${s[0]},${s[0]})` }} >
+                <div className="mainDiv-textInput" style={{ transform: `scale(${1 / s[0]}, ${1 / s[0]})`, width: `${w / s[0]}px`, height: `${h / s[0]}px` }}>
+
+                    <FormattedTextBox fieldKey={KeyStore.Archives} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={Transform.Identity} focus={(doc) => { }} />
+
+                </div>
             </ div>;
         }
         else return (null);
@@ -310,7 +319,7 @@ export class Main extends React.Component {
             <div className="main-buttonDiv" key="workspaces" style={{ top: '34px', left: '2px', position: 'absolute' }} ref={workspacesRef}>
                 <button onClick={this.toggleWorkspaces}>Workspaces</button></div>,
             <div className="main-buttonDiv" key="logout" style={{ top: '34px', right: '1px', position: 'absolute' }} ref={logoutRef}>
-                <button onClick={() => request.get(ServerUtils.prepend(RouteStore.logout), () => { })}>Log Out</button></div>
+                <button onClick={() => request.get(ServerUtils.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
         ];
     }
 
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index ea6d3a247..212cf8a69 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -50,7 +50,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     public StartOtherDrag(dragDocs: Document[], e: any) {
         dragDocs.map(dragDoc =>
             this.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.
-                onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }));
+                onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 }));
     }
 
     @action
@@ -204,7 +204,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                     DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), e.pageX, e.pageY,
                         {
                             handlers: {
-                                dragComplete: action(() => { }),
+                                dragComplete: action(emptyFunction),
                             },
                             hideSource: false
                         });
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 97bac745c..6cbe59012 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -7,6 +7,7 @@ import React = require("react");
 import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView";
+import { emptyFunction } from "../../../Utils";
 
 
 @observer
@@ -33,7 +34,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
 
     onContextMenu = (e: React.MouseEvent): void => {
         if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
-            ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } });
+            ContextMenu.Instance.addItem({ description: "PDFOptions", event: emptyFunction });
         }
     }
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 587f60b3d..c67f8cd97 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -77,8 +77,8 @@ export class CollectionSchemaView extends CollectionSubView {
         let props: FieldViewProps = {
             Document: rowProps.value[0],
             fieldKey: rowProps.value[1],
-            isSelected: () => false,
-            select: () => { },
+            isSelected: returnFalse,
+            select: emptyFunction,
             isTopMost: false,
             selectOnLoad: false,
             ScreenToLocalTransform: Transform.Identity,
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 588ff9483..ef0684955 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -15,6 +15,7 @@ import { ServerUtils } from "../../../server/ServerUtil";
 import { Server } from "../../Server";
 import { FieldViewProps } from "../nodes/FieldView";
 import * as rp from 'request-promise';
+import { emptyFunction } from "../../../Utils";
 
 export interface CollectionViewProps extends FieldViewProps {
     addDocument: (document: Document, allowDuplicates?: boolean) => boolean;
@@ -213,7 +214,7 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
         }
 
         if (promises.length) {
-            Promise.all(promises).catch(() => { }).then(() => batch.end());
+            Promise.all(promises).catch(emptyFunction).then(() => batch.end());
         } else {
             batch.end();
         }
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index b02983a2e..6c9780adb 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -7,6 +7,7 @@ import React = require("react");
 import "./CollectionVideoView.scss";
 import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
+import { emptyFunction } from "../../../Utils";
 
 
 @observer
@@ -100,7 +101,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
 
     onContextMenu = (e: React.MouseEvent): void => {
         if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
-            ContextMenu.Instance.addItem({ description: "VideoOptions", event: () => { } });
+            ContextMenu.Instance.addItem({ description: "VideoOptions", event: emptyFunction });
         }
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 1feb30db1..102455d27 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -25,6 +25,7 @@ import { SelectionManager } from "../../../util/SelectionManager";
 import { NumberField } from "../../../../fields/NumberField";
 import { Main } from "../../Main";
 import Measure from "react-measure";
+import { returnFalse, emptyFunction } from "../../../../Utils";
 
 @observer
 export class CollectionFreeFormView extends CollectionSubView {
@@ -200,7 +201,7 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     @action
     private SetPan(panX: number, panY: number) {
-        Main.Instance.SetTextDoc(undefined, undefined);
+        Main.Instance.SetTextDoc(undefined, undefined, undefined);
         var x1 = this.getLocalTransform().inverse().Scale;
         const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX));
         const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY));
@@ -290,13 +291,13 @@ export class CollectionFreeFormView extends CollectionSubView {
     get backgroundView() {
         return !this.backgroundLayout ? (null) :
             (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document)}
-                layoutKey={KeyStore.BackgroundLayout} isTopMost={this.props.isTopMost} isSelected={() => false} select={() => { }} />);
+                layoutKey={KeyStore.BackgroundLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
     @computed
     get overlayView() {
         return !this.overlayLayout ? (null) :
             (<DocumentContentsView {...this.getDocumentViewProps(this.props.Document)}
-                layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={() => false} select={() => { }} />);
+                layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
     }
 
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9670ca6b2..42967eb22 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, reaction, runInAction, trace } from "mobx";
 import { observer } from "mobx-react";
 import { Document } from "../../../fields/Document";
 import { Field, FieldWaiting, Opt } from "../../../fields/Field";
@@ -8,7 +8,7 @@ import { ListField } from "../../../fields/ListField";
 import { BooleanField } from "../../../fields/BooleanField";
 import { TextField } from "../../../fields/TextField";
 import { ServerUtils } from "../../../server/ServerUtil";
-import { Utils } from "../../../Utils";
+import { Utils, emptyFunction } from "../../../Utils";
 import { Documents } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
 import { DragManager } from "../../util/DragManager";
@@ -62,12 +62,12 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
     let Keys: { [name: string]: any } = {};
     let Fields: { [name: string]: any } = {};
     for (const key of keys) {
-        let fn = () => { };
+        let fn = emptyFunction;
         Object.defineProperty(fn, "name", { value: key + "Key" });
         Keys[key] = fn;
     }
     for (const field of fields) {
-        let fn = () => { };
+        let fn = emptyFunction;
         Object.defineProperty(fn, "name", { value: field });
         Fields[field] = fn;
     }
@@ -157,7 +157,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             dragData.moveDocument = this.props.moveDocument;
             DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, {
                 handlers: {
-                    dragComplete: action(() => { })
+                    dragComplete: action(emptyFunction)
                 },
                 hideSource: !dropAliasOfDraggedDoc
             });
@@ -377,14 +377,28 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         SelectionManager.SelectDoc(this, ctrlPressed);
     }
 
+    @computed get nativeWidth(): number { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); }
+    @computed get nativeHeight(): number { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
+    @computed
+    get contents() {
+        trace();
+        return (<DocumentContentsView
+            {...this.props}
+            isSelected={this.isSelected}
+            select={this.select}
+            layoutKey={KeyStore.Layout}
+        />);
+    }
+
     render() {
         if (!this.props.Document) {
             return null;
         }
+        trace();
 
         var scaling = this.props.ContentScaling();
-        var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
-        var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
+        var nativeWidth = this.nativeWidth;
+        var nativeHeight = this.nativeHeight;
 
         if (this.isMinimized()) {
             return (
@@ -420,12 +434,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                     onContextMenu={this.onContextMenu}
                     onPointerDown={this.onPointerDown}
                 >
-                    <DocumentContentsView
-                        {...this.props}
-                        isSelected={this.isSelected}
-                        select={this.select}
-                        layoutKey={KeyStore.Layout}
-                    />
+                    {this.contents}
                 </div>
             );
         }
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 07c5b332c..40b44aae5 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -19,7 +19,7 @@ import { ListField } from "../../../fields/ListField";
 import { DocumentContentsView } from "./DocumentContentsView";
 import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
-import { returnFalse } from "../../../Utils";
+import { returnFalse, emptyFunction } from "../../../Utils";
 
 
 //
@@ -85,9 +85,9 @@ export class FieldView extends React.Component<FieldViewProps> {
                     PanelHeight={() => 100}
                     isTopMost={true} //TODO Why is this top most?
                     selectOnLoad={false}
-                    focus={() => { }}
-                    isSelected={() => false}
-                    select={() => false}
+                    focus={emptyFunction}
+                    isSelected={returnFalse}
+                    select={returnFalse}
                     layoutKey={KeyStore.Layout}
                     ContainingCollectionView={undefined}
                     parentActive={this.props.active}
@@ -111,7 +111,7 @@ export class FieldView extends React.Component<FieldViewProps> {
         }
         else {
             return <p> {"Waiting for server..."} </p>;
- }
+        }
     }
 
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index beca6cdc6..bb1bc4fb0 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -161,13 +161,13 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         }
         if (this.props.fieldKey !== KeyStore.Archives) {
             e.preventDefault();
-            Main.Instance.SetTextDoc(this.props.Document, this._ref.current!);
+            Main.Instance.SetTextDoc(this.props.Document, this._ref.current!, this.props.ScreenToLocalTransform());
         }
     }
 
     onFocused = (e: React.FocusEvent): void => {
         if (this.props.fieldKey !== KeyStore.Archives) {
-            Main.Instance.SetTextDoc(this.props.Document, this._ref.current!);
+            Main.Instance.SetTextDoc(this.props.Document, this._ref.current!, this.props.ScreenToLocalTransform());
         }
     }
 
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 314af64c9..9d7c2bc56 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -66,7 +66,7 @@ export class VideoBox extends React.Component<FieldViewProps> {
             <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
                     <div style={{ width: "100%", height: "auto" }} ref={measureRef}>
-                        <video className="videobox-cont" onClick={() => { }} ref={this.setVideoRef}>
+                        <video className="videobox-cont" ref={this.setVideoRef}>
                             <source src={path} type="video/mp4" />
                             Not supported.
                         </video>
-- 
cgit v1.2.3-70-g09d2


From d4326a225f3e801c98e4acdc6558af1c3fe6ae07 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 10 Apr 2019 15:18:10 -0400
Subject: improved text editing.

---
 src/client/util/DragManager.ts              |  2 ++
 src/client/views/DocumentDecorations.tsx    |  2 ++
 src/client/views/Main.scss                  |  4 ++--
 src/client/views/Main.tsx                   | 18 +++++++++++++++---
 src/client/views/nodes/DocumentView.tsx     |  2 --
 src/client/views/nodes/FormattedTextBox.tsx | 10 +++++++---
 6 files changed, 28 insertions(+), 10 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index f7395578f..b8a35a4d1 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -5,6 +5,7 @@ import { CollectionView } from "../views/collections/CollectionView";
 import { DocumentDecorations } from "../views/DocumentDecorations";
 import { DocumentView } from "../views/nodes/DocumentView";
 import { returnFalse, emptyFunction } from "../../Utils";
+import { Main } from "../views/Main";
 
 export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
     let onRowMove = action((e: PointerEvent): void => {
@@ -147,6 +148,7 @@ export namespace DragManager {
             dragDiv.className = "dragManager-dragDiv";
             DragManager.Root().appendChild(dragDiv);
         }
+        Main.Instance.SetTextDoc(undefined, undefined, undefined);
 
         let scaleXs: number[] = [];
         let scaleYs: number[] = [];
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b7bf727f1..fa521b7e2 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -16,6 +16,7 @@ import { LinkMenu } from "./nodes/LinkMenu";
 import React = require("react");
 import { FieldWaiting } from "../../fields/Field";
 import { emptyFunction } from "../../Utils";
+import { Main } from "./Main";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -321,6 +322,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 break;
         }
 
+        Main.Instance.SetTextDoc(undefined, undefined, undefined);
         SelectionManager.SelectedDocuments().forEach(element => {
             const rect = element.screenRect();
             if (rect.width !== 0) {
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 8ef6b83f1..c4da47e0e 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -169,7 +169,7 @@ button:hover {
     overflow: scroll;
 }
 .mainDiv-textInput {
-    background-color: rgba(248, 6, 6, 0.1);
+    background-color: rgba(248, 6, 6, 0.001);
     width: 200px;
     height: 200px;
     position:absolute;
@@ -177,7 +177,7 @@ button:hover {
     top: 0;
     left: 0;
     .formattedTextBox-cont {
-        background-color: rgba(248, 6, 6, 0.1);
+        background-color: rgba(248, 6, 6, 0.001);
         width: 100%;
         height: 100%;
         position:absolute;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 2751b1899..e96e4cbf8 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -66,6 +66,7 @@ export class Main extends React.Component {
 
     constructor(props: Readonly<{}>) {
         super(props);
+        this._textProxyDiv = React.createRef();
         Main.Instance = this;
         // causes errors to be generated when modifying an observable outside of an action
         configure({ enforceActions: "observed" });
@@ -205,13 +206,25 @@ export class Main extends React.Component {
     @observable _textDoc?: Document = undefined;
     _textRect: any;
     _textXf: Transform = Transform.Identity();
+    _textScroll: number = 0;
+    _textTargetDiv: HTMLDivElement | undefined;
+    _textProxyDiv: React.RefObject<HTMLDivElement>;
     @action
     SetTextDoc(textDoc?: Document, div?: HTMLDivElement, tx?: Transform) {
         this._textDoc = undefined;
         this._textDoc = textDoc;
         this._textXf = tx ? tx : Transform.Identity();
+        this._textTargetDiv = div;
         if (div) {
             this._textRect = div.getBoundingClientRect();
+            this._textScroll = div.scrollTop;
+        }
+    }
+
+    @action
+    textScroll = (e: React.UIEvent) => {
+        if (this._textProxyDiv.current && this._textTargetDiv) {
+            this._textTargetDiv.scrollTop = this._textScroll = this._textProxyDiv.current.children[0].scrollTop
         }
     }
 
@@ -225,9 +238,8 @@ export class Main extends React.Component {
             let t = this._textXf.transformPoint(0, 0);
             let s = this._textXf.transformPoint(1, 0);
             s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
-            return <div className="mainDiv-textInput" style={{ transform: `translate(${x}px, ${y}px) scale(${s[0]},${s[0]})` }} >
-                <div className="mainDiv-textInput" style={{ transform: `scale(${1 / s[0]}, ${1 / s[0]})`, width: `${w / s[0]}px`, height: `${h / s[0]}px` }}>
-
+            return <div className="mainDiv-textInput" style={{ transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
+                <div className="mainDiv-textInput" ref={this._textProxyDiv} onScroll={this.textScroll} style={{ transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
                     <FormattedTextBox fieldKey={KeyStore.Archives} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={Transform.Identity} focus={(doc) => { }} />
 
                 </div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 42967eb22..6b585ec4b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -381,7 +381,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     @computed get nativeHeight(): number { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); }
     @computed
     get contents() {
-        trace();
         return (<DocumentContentsView
             {...this.props}
             isSelected={this.isSelected}
@@ -394,7 +393,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (!this.props.Document) {
             return null;
         }
-        trace();
 
         var scaling = this.props.ContentScaling();
         var nativeWidth = this.nativeWidth;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index bb1bc4fb0..eb40a03a5 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -92,7 +92,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
 
         this._reactionDisposer = reaction(
             () => {
-                const field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
+                const field = this.FieldDoc ? this.FieldDoc.GetT(this.FieldKey, RichTextField) : undefined;
                 return field && field !== FieldWaiting ? field.Data : undefined;
             },
             field => {
@@ -107,9 +107,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
     }
 
     private setupEditor(config: any) {
-
         let state: EditorState;
-        let field = this.FieldDoc.GetT(this.FieldKey, RichTextField);
+        let field = this.FieldDoc ? this.FieldDoc.GetT(this.FieldKey, RichTextField) : undefined;
         if (field && field !== FieldWaiting && field.Data) {
             state = EditorState.fromJSON(config, JSON.parse(field.Data));
         } else {
@@ -168,6 +167,10 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
     onFocused = (e: React.FocusEvent): void => {
         if (this.props.fieldKey !== KeyStore.Archives) {
             Main.Instance.SetTextDoc(this.props.Document, this._ref.current!, this.props.ScreenToLocalTransform());
+        } else {
+            if (this._ref.current) {
+                this._ref.current.scrollTop = Main.Instance._textScroll;
+            }
         }
     }
 
@@ -219,6 +222,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
                 onKeyPress={this.onKeyPress}
                 onPointerUp={this.onPointerUp}
                 onPointerDown={this.onPointerDown}
+                onFocus={this.onFocused}
                 onContextMenu={this.specificContextMenu}
                 // tfs: do we need this event handler
                 onWheel={this.onPointerWheel}
-- 
cgit v1.2.3-70-g09d2


From 50be8cb7a93110821c972c679567ddb6aae8bc6f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 11 Apr 2019 11:56:40 -0400
Subject: made css globals avabile from code.  cleaned up formattedText overlay
 api..

---
 src/client/util/DragManager.ts                     |  12 +-
 src/client/util/SelectionManager.ts                |   2 +-
 src/client/views/DocumentDecorations.tsx           |   2 +-
 src/client/views/Main.tsx                          |   7 +-
 src/client/views/_global_variables.scss            |   2 +-
 src/client/views/_global_variables.scss.d.ts       |  11 +-
 src/client/views/_global_variables.ts              |   8 +
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   2 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  31 ++--
 tsconfig.json                                      |  42 ++---
 webpack.config.js                                  | 180 ++++++++++-----------
 11 files changed, 154 insertions(+), 145 deletions(-)
 create mode 100644 src/client/views/_global_variables.ts

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index e500b0274..d66c6e90f 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,12 +1,12 @@
 import { action } from "mobx";
 import { Document } from "../../fields/Document";
+import { emptyFunction } from "../../Utils";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
-import { CollectionView } from "../views/collections/CollectionView";
 import { DocumentDecorations } from "../views/DocumentDecorations";
-import { DocumentView } from "../views/nodes/DocumentView";
-import { returnFalse, emptyFunction } from "../../Utils";
 import { Main } from "../views/Main";
-import globalStyles from '../views/_global_variables.scss';
+import { DocumentView } from "../views/nodes/DocumentView";
+import globalStyles from "../views/_global_variables";
+// import globalStyleVariables from "../views/_global_variables.scss"; // bcz: why doesn't this work?
 
 export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
     let onRowMove = action((e: PointerEvent): void => {
@@ -149,7 +149,7 @@ export namespace DragManager {
             dragDiv.className = "dragManager-dragDiv";
             DragManager.Root().appendChild(dragDiv);
         }
-        Main.Instance.SetTextDoc(undefined, undefined, undefined);
+        Main.Instance.SetTextDoc();
 
         let scaleXs: number[] = [];
         let scaleYs: number[] = [];
@@ -178,7 +178,7 @@ export namespace DragManager {
             dragElement.style.bottom = "";
             dragElement.style.left = "0";
             dragElement.style.transformOrigin = "0 0";
-            dragElement.style.zIndex = "1000";// globalStyles.contextMenuZindex.toString();
+            dragElement.style.zIndex = globalStyles.contextMenuZindex;// "1000";
             dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
             dragElement.style.width = `${rect.width / scaleX}px`;
             dragElement.style.height = `${rect.height / scaleY}px`;
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 2638e3b7d..2fa45a086 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -25,7 +25,7 @@ export namespace SelectionManager {
         DeselectAll(): void {
             manager.SelectedDocuments.map(dv => dv.props.onActiveChanged(false));
             manager.SelectedDocuments = [];
-            Main.Instance.SetTextDoc(undefined, undefined, undefined);
+            Main.Instance.SetTextDoc();
         }
     }
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index fa521b7e2..29cca286d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -322,7 +322,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 break;
         }
 
-        Main.Instance.SetTextDoc(undefined, undefined, undefined);
+        Main.Instance.SetTextDoc();
         SelectionManager.SelectedDocuments().forEach(element => {
             const rect = element.screenRect();
             if (rect.width !== 0) {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 5fd778c7e..c4c4a6bf9 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -39,6 +39,7 @@ import "./Main.scss";
 import { DocumentView } from './nodes/DocumentView';
 import { FormattedTextBox } from './nodes/FormattedTextBox';
 import { REPLCommand } from 'repl';
+import { Key } from '../../fields/Key';
 
 @observer
 export class Main extends React.Component {
@@ -208,17 +209,19 @@ export class Main extends React.Component {
     _textRect: any;
     _textXf: Transform = Transform.Identity();
     _textScroll: number = 0;
+    _textFieldKey: Key = KeyStore.Data;
     _textColor: string | null = null;
     _textTargetDiv: HTMLDivElement | undefined;
     _textProxyDiv: React.RefObject<HTMLDivElement>;
     @action
-    SetTextDoc(textDoc?: Document, div?: HTMLDivElement, tx?: Transform) {
+    SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: Transform) {
         if (this._textTargetDiv) {
             this._textTargetDiv.style.color = this._textColor;
         }
 
         this._textDoc = undefined;
         this._textDoc = textDoc;
+        this._textFieldKey = textFieldKey!;
         this._textXf = tx ? tx : Transform.Identity();
         this._textTargetDiv = div;
         if (div) {
@@ -277,7 +280,7 @@ export class Main extends React.Component {
             s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
             return <div className="mainDiv-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
                 <div className="mainDiv-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
-                    <FormattedTextBox fieldKey={KeyStore.Archives} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={(doc) => { }} />
+                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={(doc) => { }} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/_global_variables.scss b/src/client/views/_global_variables.scss
index 238351a77..cd6af2dac 100644
--- a/src/client/views/_global_variables.scss
+++ b/src/client/views/_global_variables.scss
@@ -24,5 +24,5 @@ $docDecorations-zindex: 998; // then doc decorations appear over everything else
 $remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right?
 
 :export  {
-    contextMenuZindex: $contextMenu-zindex
+    contextMenuZindex: $contextMenu-zindex;
 }
\ No newline at end of file
diff --git a/src/client/views/_global_variables.scss.d.ts b/src/client/views/_global_variables.scss.d.ts
index 12008aeef..c902d473f 100644
--- a/src/client/views/_global_variables.scss.d.ts
+++ b/src/client/views/_global_variables.scss.d.ts
@@ -1,10 +1,7 @@
+
 export interface I_globalScss {
-    contextMenuZindex: number;  // context menu shows up over everything
-    mainTextInputZindex: number; // then text input overlay so that it's context menu will appear over decorations, etc
-    docDecorationsZindex: number; // then doc decorations appear over everything else
-    remoteCursorsZindex: number; // ... not sure what level the remote cursors should go -- is this right?
+    contextMenuZindex: string;  // context menu shows up over everything
 }
+export const globalStyleVariables: I_globalScss;
 
-export const globalStyles: I_globalScss;
-
-export default globalStyles;
\ No newline at end of file
+export default globalStyleVariables;
\ No newline at end of file
diff --git a/src/client/views/_global_variables.ts b/src/client/views/_global_variables.ts
new file mode 100644
index 000000000..e70bfd56c
--- /dev/null
+++ b/src/client/views/_global_variables.ts
@@ -0,0 +1,8 @@
+import * as globalStyleVariables from "../views/_global_variables.scss"
+
+export interface I_globalScss {
+    contextMenuZindex: string;  // context menu shows up over everything
+}
+let globalStyles = globalStyleVariables as any as I_globalScss;
+
+export default globalStyles;
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b40e36e77..01ebbe0e1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -198,7 +198,7 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     @action
     private SetPan(panX: number, panY: number) {
-        Main.Instance.SetTextDoc(undefined, undefined, undefined);
+        Main.Instance.SetTextDoc();
         var x1 = this.getLocalTransform().inverse().Scale;
         const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX));
         const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY));
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 468cbcd1e..8ea747b1c 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -5,7 +5,6 @@ import { keymap } from "prosemirror-keymap";
 import { EditorState, Plugin, Transaction } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { FieldWaiting, Opt } from "../../../fields/Field";
-import { KeyStore } from "../../../fields/KeyStore";
 import { RichTextField } from "../../../fields/RichTextField";
 import { inpRules } from "../../util/RichTextRules";
 import { schema } from "../../util/RichTextSchema";
@@ -14,7 +13,6 @@ import { ContextMenu } from "../../views/ContextMenu";
 import { Main } from "../Main";
 import { FieldView, FieldViewProps } from "./FieldView";
 import "./FormattedTextBox.scss";
-import { emptyFunction } from '../../../Utils';
 import React = require("react");
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
@@ -35,7 +33,12 @@ const { menuBar } = require("prosemirror-menu");
 //  specified Key and assigns it to an HTML input node.  When changes are made to this node,
 //  this will edit the document and assign the new value to that field.
 //]
-export class FormattedTextBox extends React.Component<FieldViewProps> {
+
+export interface FormattedTextBoxOverlay {
+    isOverlay?: boolean;
+}
+
+export class FormattedTextBox extends React.Component<(FieldViewProps & FormattedTextBoxOverlay)> {
     public static LayoutString(fieldStr: string = "DataKey") {
         return FieldView.LayoutString(FormattedTextBox, fieldStr);
     }
@@ -56,8 +59,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         if (this._editorView) {
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
-            this.FieldDoc.SetDataOnPrototype(
-                this.FieldKey,
+            this.props.Document.SetDataOnPrototype(
+                this.props.fieldKey,
                 JSON.stringify(state.toJSON()),
                 RichTextField
             );
@@ -65,14 +68,11 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         }
     }
 
-    get FieldDoc() { return this.props.fieldKey === KeyStore.Archives ? Main.Instance._textDoc! : this.props.Document; }
-    get FieldKey() { return this.props.fieldKey === KeyStore.Archives ? KeyStore.Data : this.props.fieldKey; }
-
     componentDidMount() {
         const config = {
             schema,
             inpRules, //these currently don't do anything, but could eventually be helpful
-            plugins: this.props.fieldKey === KeyStore.Archives ? [
+            plugins: this.props.isOverlay ? [
                 history(),
                 keymap({ "Mod-z": undo, "Mod-y": redo }),
                 keymap(baseKeymap),
@@ -84,7 +84,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
                 ]
         };
 
-        if (this.props.fieldKey === KeyStore.Archives) {
+        if (this.props.isOverlay) {
             this._inputReactionDisposer = reaction(() => Main.Instance._textDoc && Main.Instance._textDoc.Id,
                 () => {
                     if (this._editorView) {
@@ -96,12 +96,12 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             );
         } else {
             this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
-                () => this.props.isSelected() && Main.Instance.SetTextDoc(this.props.Document, this._ref.current!, this.props.ScreenToLocalTransform()));
+                () => this.props.isSelected() && Main.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform()));
         }
 
         this._reactionDisposer = reaction(
             () => {
-                const field = this.FieldDoc ? this.FieldDoc.GetT(this.FieldKey, RichTextField) : undefined;
+                const field = this.props.Document ? this.props.Document.GetT(this.props.fieldKey, RichTextField) : undefined;
                 return field && field !== FieldWaiting ? field.Data : undefined;
             },
             field => {
@@ -117,7 +117,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
 
     private setupEditor(config: any) {
         let state: EditorState;
-        let field = this.FieldDoc ? this.FieldDoc.GetT(this.FieldKey, RichTextField) : undefined;
+        let field = this.props.Document ? this.props.Document.GetT(this.props.fieldKey, RichTextField) : undefined;
         if (field && field !== FieldWaiting && field.Data) {
             state = EditorState.fromJSON(config, JSON.parse(field.Data));
         } else {
@@ -176,8 +176,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
     }
 
     onFocused = (e: React.FocusEvent): void => {
-        if (this.props.fieldKey !== KeyStore.Archives) {
-            Main.Instance.SetTextDoc(this.props.Document, this._ref.current!, this.props.ScreenToLocalTransform());
+        if (!this.props.isOverlay) {
+            Main.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform());
         } else {
             if (this._ref.current) {
                 this._ref.current.scrollTop = Main.Instance._textScroll;
@@ -232,6 +232,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
                 className={`formattedTextBox-cont`}
                 onKeyDown={this.onKeyPress}
                 onKeyPress={this.onKeyPress}
+                onFocus={this.onFocused}
                 onPointerUp={this.onPointerUp}
                 onPointerDown={this.onPointerDown}
                 onContextMenu={this.specificContextMenu}
diff --git a/tsconfig.json b/tsconfig.json
index 41db1d0a7..0d4d77002 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,23 +1,23 @@
 {
-  "compilerOptions": {
-    "target": "es5",
-    "removeComments": true,
-    "experimentalDecorators": true,
-    "strict": true,
-    "jsx": "react",
-    "sourceMap": true,
-    "outDir": "dist",
-    "lib": [
-      "dom",
-      "es2015"
-    ],
-  },
-  // "exclude": [
-  //   "node_modules",
-  //   "static"
-  // ],
-  "typeRoots": [
-    "./node_modules/@types",
-    "./src/typings"
-  ]
+    "compilerOptions": {
+        "target": "es5",
+        "removeComments": true,
+        "experimentalDecorators": true,
+        "strict": true,
+        "jsx": "react",
+        "sourceMap": true,
+        "outDir": "dist",
+        "lib": [
+            "dom",
+            "es2015"
+        ],
+    },
+    // "exclude": [
+    //   "node_modules",
+    //   "static"
+    // ],
+    "typeRoots": [
+        "./node_modules/@types",
+        "./src/typings"
+    ]
 }
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index 50079255f..574401807 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,95 +3,95 @@ var webpack = require('webpack');
 const CopyWebpackPlugin = require("copy-webpack-plugin");
 
 module.exports = {
-  mode: 'development',
-  entry: {
-    bundle: ["./src/client/views/Main.tsx", 'webpack-hot-middleware/client?reload=true'],
-    viewer: ["./src/debug/Viewer.tsx", 'webpack-hot-middleware/client?reload=true'],
-    test: ["./src/debug/Test.tsx", 'webpack-hot-middleware/client?reload=true'],
-    inkControls: ["./src/mobile/InkControls.tsx", 'webpack-hot-middleware/client?reload=true'],
-    imageUpload: ["./src/mobile/ImageUpload.tsx", 'webpack-hot-middleware/client?reload=true'],
-  },
-  devtool: "source-map",
-  node: {
-    fs: 'empty',
-    module: 'empty',
-    dns: 'mock',
-    tls: 'mock',
-    net: 'mock'
-  },
-  output: {
-    filename: "[name].js",
-    path: path.resolve(__dirname, "build"),
-    publicPath: "/"
-  },
-  resolve: {
-    extensions: ['.js', '.ts', '.tsx']
-  },
-  module: {
-    rules: [
-      {
-        test: [/\.tsx?$/, /\.ts?$/,],
-        enforce: 'pre',
-        use: [
-          {
-            loader: "tslint-loader",
-          }
-        ]
-      }, {
-        test: [/\.tsx?$/, /\.ts?$/,],
-        loader: "awesome-typescript-loader",
-        include: path.join(__dirname, 'src')
-      },
-      {
-        test: /\.scss|css$/,
-        use: [
-          {
-            loader: "style-loader"
-          },
-          {
-            loader: "css-loader"
-          },
-          {
-            loader: "sass-loader"
-          }
-        ]
-      },
-      {
-        test: /\.(jpg|png|pdf)$/,
-        use: [
-          {
-            loader: 'file-loader'
-          }
-        ]
-      },
-      {
-        test: /\.(png|jpg|gif)$/i,
-        use: [
-          {
-            loader: 'url-loader',
-            options: {
-              limit: 8192
-            }
-          }
-        ]
-      }]
-  },
-  plugins: [
-    new CopyWebpackPlugin([{ from: "deploy", to: path.join(__dirname, "build") }]),
-    new webpack.optimize.OccurrenceOrderPlugin(),
-    new webpack.HotModuleReplacementPlugin(),
-    new webpack.NoEmitOnErrorsPlugin()
-  ],
-  devServer: {
-    compress: false,
-    host: "localhost",
-    contentBase: path.join(__dirname, 'deploy'),
-    port: 4321,
-    hot: true,
-    https: false,
-    overlay: {
-      warnings: true,
-      errors: true
+    mode: 'development',
+    entry: {
+        bundle: ["./src/client/views/Main.tsx", 'webpack-hot-middleware/client?reload=true'],
+        viewer: ["./src/debug/Viewer.tsx", 'webpack-hot-middleware/client?reload=true'],
+        test: ["./src/debug/Test.tsx", 'webpack-hot-middleware/client?reload=true'],
+        inkControls: ["./src/mobile/InkControls.tsx", 'webpack-hot-middleware/client?reload=true'],
+        imageUpload: ["./src/mobile/ImageUpload.tsx", 'webpack-hot-middleware/client?reload=true'],
+    },
+    devtool: "source-map",
+    node: {
+        fs: 'empty',
+        module: 'empty',
+        dns: 'mock',
+        tls: 'mock',
+        net: 'mock'
+    },
+    output: {
+        filename: "[name].js",
+        path: path.resolve(__dirname, "build"),
+        publicPath: "/"
+    },
+    resolve: {
+        extensions: ['.js', '.ts', '.tsx']
+    },
+    module: {
+        rules: [
+            {
+                test: [/\.tsx?$/, /\.ts?$/,],
+                enforce: 'pre',
+                use: [
+                    {
+                        loader: "tslint-loader",
+                    }
+                ]
+            }, {
+                test: [/\.tsx?$/, /\.ts?$/,],
+                loader: "awesome-typescript-loader",
+                include: path.join(__dirname, 'src')
+            },
+            {
+                test: /\.scss|css$/,
+                use: [
+                    {
+                        loader: "style-loader"
+                    },
+                    {
+                        loader: "css-loader"
+                    },
+                    {
+                        loader: "sass-loader"
+                    }
+                ]
+            },
+            {
+                test: /\.(jpg|png|pdf)$/,
+                use: [
+                    {
+                        loader: 'file-loader'
+                    }
+                ]
+            },
+            {
+                test: /\.(png|jpg|gif)$/i,
+                use: [
+                    {
+                        loader: 'url-loader',
+                        options: {
+                            limit: 8192
+                        }
+                    }
+                ]
+            }]
+    },
+    plugins: [
+        new CopyWebpackPlugin([{ from: "deploy", to: path.join(__dirname, "build") }]),
+        new webpack.optimize.OccurrenceOrderPlugin(),
+        new webpack.HotModuleReplacementPlugin(),
+        new webpack.NoEmitOnErrorsPlugin()
+    ],
+    devServer: {
+        compress: false,
+        host: "localhost",
+        contentBase: path.join(__dirname, 'deploy'),
+        port: 4321,
+        hot: true,
+        https: false,
+        overlay: {
+            warnings: true,
+            errors: true
+        }
     }
-  }
 };
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 343aeabf2cc3cab641944de16a95e5eb459a8e5f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 11:02:30 -0400
Subject: added link count to tabs.  changed tabs to drag document with no
 mods, and drag tab with shift

---
 src/client/util/DragManager.ts                     |  6 +-
 src/client/views/DocumentDecorations.tsx           |  2 +-
 .../views/collections/CollectionDockingView.scss   | 15 ++++
 .../views/collections/CollectionDockingView.tsx    | 96 +++++++++++++++++-----
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 5 files changed, 96 insertions(+), 25 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 3d8bbb49c..2562ba18a 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -130,11 +130,11 @@ export namespace DragManager {
     }
 
     export class LinkDragData {
-        constructor(linkSourceDoc: DocumentView) {
-            this.linkSourceDocumentView = linkSourceDoc;
+        constructor(linkSourceDoc: Document) {
+            this.linkSourceDocument = linkSourceDoc;
         }
         droppedDocuments: Document[] = [];
-        linkSourceDocumentView: DocumentView;
+        linkSourceDocument: Document;
         [id: string]: any;
     }
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 29cca286d..69623b8f0 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -216,7 +216,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (this._linkerButton.current !== null) {
             document.removeEventListener("pointermove", this.onLinkerButtonMoved);
             document.removeEventListener("pointerup", this.onLinkerButtonUp);
-            let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
+            let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0].props.Document);
             DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, {
                 handlers: {
                     dragComplete: action(emptyFunction),
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 13dd9faa8..0e7e0afa7 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -3,6 +3,21 @@
 .collectiondockingview-content {
     height: 100%;
 }
+.lm_active .messageCounter{
+    color:white;
+    background: #999999;
+}
+.messageCounter {
+    width:18px;
+    height:20px;
+    text-align: center;
+    border-radius: 20px;
+    margin-left: 5px;
+    transform: translate(0px, -8px);
+    display: inline-block;
+    background: transparent;
+    border: 1px #999999 solid;
+}
 
 .collectiondockingview-container {
     width: 100%;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 05470f405..f2f41e821 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -7,7 +7,7 @@ import * as ReactDOM from 'react-dom';
 import { Document } from "../../../fields/Document";
 import { KeyStore } from "../../../fields/KeyStore";
 import Measure from "react-measure";
-import { FieldId, Opt, Field } from "../../../fields/Field";
+import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field";
 import { Utils, returnTrue, emptyFunction } from "../../../Utils";
 import { Server } from "../../Server";
 import { undoBatch } from "../../util/UndoManager";
@@ -18,6 +18,7 @@ import { SubCollectionViewProps } from "./CollectionSubView";
 import { ServerUtils } from "../../../server/ServerUtil";
 import { DragManager } from "../../util/DragManager";
 import { TextField } from "../../../fields/TextField";
+import { ListField } from "../../../fields/ListField";
 
 @observer
 export class CollectionDockingView extends React.Component<SubCollectionViewProps> {
@@ -193,23 +194,59 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         var className = (e.target as any).className;
-        if ((className === "lm_title" || className === "lm_tab lm_active") && (e.ctrlKey || e.altKey)) {
+        if (className === "messageCounter") {
             e.stopPropagation();
             e.preventDefault();
+            let x = e.clientX;
+            let y = e.clientY;
             let docid = (e.target as any).DashDocId;
             let tab = (e.target as any).parentElement as HTMLElement;
-            Server.GetField(docid, action((f: Opt<Field>) => {
-                if (f instanceof Document) {
-                    DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), e.pageX, e.pageY,
-                        {
+            Server.GetField(docid, action(async (sourceDoc: Opt<Field>) => {
+                if (sourceDoc instanceof Document) {
+                    let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
+                    let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+                        srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
+                            (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
+                    let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+                        srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
+                            (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
+                    draggedDocs.push(...draggedFromDocs);
+                    if (draggedDocs.length) {
+                        let moddrag = [] as Document[];
+                        for (const draggedDoc of draggedDocs) {
+                            let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
+                            if (doc) moddrag.push(doc);
+                        }
+                        let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
+                        DragManager.StartDocumentDrag([tab], dragData, x, y, {
                             handlers: {
                                 dragComplete: action(emptyFunction),
                             },
                             hideSource: false
                         });
+                    }
                 }
             }));
-        }
+        } else
+            if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) {
+                e.stopPropagation();
+                e.preventDefault();
+                let x = e.clientX;
+                let y = e.clientY;
+                let docid = (e.target as any).DashDocId;
+                let tab = (e.target as any).parentElement as HTMLElement;
+                Server.GetField(docid, action((f: Opt<Field>) => {
+                    if (f instanceof Document) {
+                        DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), x, y,
+                            {
+                                handlers: {
+                                    dragComplete: action(emptyFunction),
+                                },
+                                hideSource: false
+                            });
+                    }
+                }));
+            }
         if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") {
             this._flush = true;
         }
@@ -228,24 +265,43 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         this.stateChanged();
     }
 
+    htmlToElement(html: string) {
+        var template = document.createElement('template');
+        html = html.trim(); // Never return a text node of whitespace as the result
+        template.innerHTML = html;
+        return template.content.firstChild;
+    }
+
     tabCreated = (tab: any) => {
         if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
-            if (tab.titleElement[0].textContent.indexOf("-waiting") !== -1) {
-                Server.GetField(tab.contentItem.config.props.documentId, action((f: Opt<Field>) => {
-                    if (f !== undefined && f instanceof Document) {
-                        f.GetTAsync(KeyStore.Title, TextField, (tfield) => {
-                            if (tfield !== undefined) {
-                                tab.titleElement[0].textContent = f.Title;
-                            }
-                        });
-                    }
-                }));
-                tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
-            }
-            tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
+            Server.GetField(tab.contentItem.config.props.documentId, action((f: Opt<Field>) => {
+                if (f !== undefined && f instanceof Document) {
+                    f.GetTAsync(KeyStore.Title, TextField, (tfield) => {
+                        if (tfield !== undefined) {
+                            tab.titleElement[0].textContent = f.Title;
+                        }
+                    });
+                    f.GetTAsync(KeyStore.LinkedFromDocs, ListField).then(lf =>
+                        f.GetTAsync(KeyStore.LinkedToDocs, ListField).then(lt => {
+                            let count = (lf ? lf.Data.length : 0) + (lt ? lt.Data.length : 0);
+                            let counter: any = this.htmlToElement(`<div class="messageCounter">${count}</div>`);
+                            tab.element.append(counter);
+                            counter.DashDocId = tab.contentItem.config.props.documentId;
+                            (tab as any).reactionDisposer = reaction(() => [f.GetT(KeyStore.LinkedFromDocs, ListField), f.GetT(KeyStore.LinkedToDocs, ListField)],
+                                (lists) => {
+                                    let count = (lists.length > 0 && lists[0] && lists[0]!.Data ? lists[0]!.Data.length : 0) +
+                                        (lists.length > 1 && lists[1] && lists[1]!.Data ? lists[1]!.Data.length : 0);
+                                    counter.innerHTML = count;
+                                });
+                        }));
+                    tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
+                }
+            }));
         }
         tab.closeElement.off('click') //unbind the current click handler
             .click(function () {
+                if (tab.reactionDisposer)
+                    tab.reactionDisposer();
                 tab.contentItem.remove();
             });
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9c31a83c1..649104d6c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -241,7 +241,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.LinkDragData) {
-            let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
+            let sourceDoc: Document = de.data.linkSourceDocument;
             let destDoc: Document = this.props.Document;
             if (this.props.isTopMost) {
                 return;
-- 
cgit v1.2.3-70-g09d2


From 0c9d3637bde9825efe93c55afce8270b2a2e979c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 11:18:23 -0400
Subject: cleaned up and enabled linking to a top-level document

---
 src/client/util/DragManager.ts                     | 29 ++++++++++++++++++++-
 src/client/views/DocumentDecorations.tsx           | 27 ++-----------------
 src/client/views/Main.tsx                          |  4 +--
 .../views/collections/CollectionDockingView.tsx    | 30 +++-------------------
 .../views/collections/CollectionSchemaView.tsx     |  4 +--
 .../views/collections/CollectionTreeView.tsx       |  4 +--
 src/client/views/nodes/DocumentView.tsx            |  3 ---
 7 files changed, 39 insertions(+), 62 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 2562ba18a..6a7047725 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -6,8 +6,10 @@ import { DocumentDecorations } from "../views/DocumentDecorations";
 import { Main } from "../views/Main";
 import { DocumentView } from "../views/nodes/DocumentView";
 import * as globalCssVariables from "../views/globalCssVariables.scss";
+import { KeyStore } from "../../fields/KeyStore";
+import { FieldWaiting } from "../../fields/Field";
 
-export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
+export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
     let onRowMove = action((e: PointerEvent): void => {
         e.stopPropagation();
         e.preventDefault();
@@ -39,6 +41,31 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
     return onItemDown;
 }
 
+export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Document) {
+    let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
+    let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+        srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
+            (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
+    let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
+        srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
+            (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
+    draggedDocs.push(...draggedFromDocs);
+    if (draggedDocs.length) {
+        let moddrag = [] as Document[];
+        for (const draggedDoc of draggedDocs) {
+            let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
+            if (doc) moddrag.push(doc);
+        }
+        let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
+        DragManager.StartDocumentDrag([dragEle], dragData, x, y, {
+            handlers: {
+                dragComplete: action(emptyFunction),
+            },
+            hideSource: false
+        });
+    }
+}
+
 export namespace DragManager {
     export function Root() {
         const root = document.getElementById("root");
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 69623b8f0..03b16fb0b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -7,7 +7,7 @@ import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
 import { Document } from "../../fields/Document";
 import { TextField } from "../../fields/TextField";
-import { DragManager } from "../util/DragManager";
+import { DragManager, DragLinksAsDocuments } from "../util/DragManager";
 import { SelectionManager } from "../util/SelectionManager";
 import { CollectionView } from "./collections/CollectionView";
 import './DocumentDecorations.scss';
@@ -246,34 +246,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             document.removeEventListener("pointermove", this.onLinkButtonMoved);
             document.removeEventListener("pointerup", this.onLinkButtonUp);
 
-            let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document;
-            let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
-            let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
-                    (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
-            let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
-                    (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
-            draggedDocs.push(...draggedFromDocs);
-            if (draggedDocs.length) {
-                let moddrag = [] as Document[];
-                for (const draggedDoc of draggedDocs) {
-                    let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
-                    if (doc) moddrag.push(doc);
-                }
-                let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
-                DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, {
-                    handlers: {
-                        dragComplete: action(emptyFunction),
-                    },
-                    hideSource: false
-                });
-            }
+            DragLinksAsDocuments(this._linkButton.current, e.x, e.y, SelectionManager.SelectedDocuments()[0].props.Document);
         }
         e.stopPropagation();
     }
 
-
     onPointerMove = (e: PointerEvent): void => {
         e.stopPropagation();
         e.preventDefault();
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c4c4a6bf9..60f7098fb 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -28,7 +28,7 @@ import '../northstar/model/ModelExtensions';
 import { HistogramOperation } from '../northstar/operations/HistogramOperation';
 import '../northstar/utils/Extensions';
 import { Server } from '../Server';
-import { setupDrag, DragManager } from '../util/DragManager';
+import { SetupDrag, DragManager } from '../util/DragManager';
 import { Transform } from '../util/Transform';
 import { UndoManager } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
@@ -344,7 +344,7 @@ export class Main extends React.Component {
                 <ul id="add-options-list">
                     {btns.map(btn =>
                         <li key={btn[1]} ><div ref={btn[0]}>
-                            <button className="round-button add-button" title={btn[2]} onPointerDown={setupDrag(btn[0], btn[3])}>
+                            <button className="round-button add-button" title={btn[2]} onPointerDown={SetupDrag(btn[0], btn[3])}>
                                 <FontAwesomeIcon icon={btn[1]} size="sm" />
                             </button>
                         </div></li>)}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f2f41e821..e54c25474 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -16,7 +16,7 @@ import "./CollectionDockingView.scss";
 import React = require("react");
 import { SubCollectionViewProps } from "./CollectionSubView";
 import { ServerUtils } from "../../../server/ServerUtil";
-import { DragManager } from "../../util/DragManager";
+import { DragManager, DragLinksAsDocuments } from "../../util/DragManager";
 import { TextField } from "../../../fields/TextField";
 import { ListField } from "../../../fields/ListField";
 
@@ -201,32 +201,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             let y = e.clientY;
             let docid = (e.target as any).DashDocId;
             let tab = (e.target as any).parentElement as HTMLElement;
-            Server.GetField(docid, action(async (sourceDoc: Opt<Field>) => {
-                if (sourceDoc instanceof Document) {
-                    let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document);
-                    let draggedDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                        srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc =>
-                            (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : [];
-                    let draggedFromDocs = (srcTarg && srcTarg !== FieldWaiting) ?
-                        srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc =>
-                            (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : [];
-                    draggedDocs.push(...draggedFromDocs);
-                    if (draggedDocs.length) {
-                        let moddrag = [] as Document[];
-                        for (const draggedDoc of draggedDocs) {
-                            let doc = await draggedDoc.GetTAsync(KeyStore.AnnotationOn, Document);
-                            if (doc) moddrag.push(doc);
-                        }
-                        let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
-                        DragManager.StartDocumentDrag([tab], dragData, x, y, {
-                            handlers: {
-                                dragComplete: action(emptyFunction),
-                            },
-                            hideSource: false
-                        });
-                    }
-                }
-            }));
+            Server.GetField(docid, action(async (sourceDoc: Opt<Field>) =>
+                (sourceDoc instanceof Document) && DragLinksAsDocuments(tab, x, y, sourceDoc)));
         } else
             if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) {
                 e.stopPropagation();
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0cb88eab0..f53b2a76e 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -13,7 +13,7 @@ import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
 import { Server } from "../../Server";
-import { setupDrag } from "../../util/DragManager";
+import { SetupDrag } from "../../util/DragManager";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from "../../util/Transform";
 import { anchorPoints, Flyout } from "../DocumentDecorations";
@@ -90,7 +90,7 @@ export class CollectionSchemaView extends CollectionSubView {
             <FieldView {...props} />
         );
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = setupDrag(reference, () => props.Document, this.props.moveDocument);
+        let onItemDown = SetupDrag(reference, () => props.Document, this.props.moveDocument);
         let applyToDoc = (doc: Document, run: (args?: { [name: string]: any }) => any) => {
             const res = run({ this: doc });
             if (!res.success) return false;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 20ec16822..51a02fc25 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -7,7 +7,7 @@ import { Document } from "../../../fields/Document";
 import { FieldWaiting } from "../../../fields/Field";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { setupDrag, DragManager } from "../../util/DragManager";
+import { SetupDrag, DragManager } from "../../util/DragManager";
 import { EditableView } from "../EditableView";
 import "./CollectionTreeView.scss";
 import { CollectionView } from "./CollectionView";
@@ -77,7 +77,7 @@ class TreeView extends React.Component<TreeViewProps> {
      */
     renderTitle() {
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = setupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
+        let onItemDown = SetupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
         let editableView = (titleString: string) =>
             (<EditableView
                 display={"inline"}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 649104d6c..06182d1a6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -243,9 +243,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (de.data instanceof DragManager.LinkDragData) {
             let sourceDoc: Document = de.data.linkSourceDocument;
             let destDoc: Document = this.props.Document;
-            if (this.props.isTopMost) {
-                return;
-            }
             let linkDoc: Document = new Document();
 
             destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest =>
-- 
cgit v1.2.3-70-g09d2


From 3249a76b9fc1984b013ab4cf267602e1cfd4b5ae Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 11:25:02 -0400
Subject: added title bar dragging for decorations.

---
 src/client/views/DocumentDecorations.tsx | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 03b16fb0b..15ac0a8fc 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -108,7 +108,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         document.addEventListener("pointerup", this.onBackgroundUp);
         this._lastDrag = [e.clientX, e.clientY];
         e.stopPropagation();
-        e.preventDefault();
+        if (e.currentTarget.localName !== "input") {
+            e.preventDefault();
+        }
     }
 
     @action
@@ -404,7 +406,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 opacity: this._opacity
             }}>
                 <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>...</div>
-                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} />
+                <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onBackgroundDown} onKeyPress={this.enterPressed} />
                 <div className="documentDecorations-closeButton" onPointerDown={this.onCloseDown}>X</div>
                 <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
-- 
cgit v1.2.3-70-g09d2


From 0afa18bfc219c597ad55a52ffc5a2086c3d110d2 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Apr 2019 14:15:05 -0400
Subject: changed signatures of focus functions.

---
 src/Utils.ts                                       |  3 +++
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/Main.tsx                          |  8 ++++----
 .../views/collections/CollectionDockingView.tsx    |  4 ++--
 .../views/collections/CollectionSchemaView.tsx     |  8 +++-----
 src/client/views/nodes/FieldView.tsx               |  4 ++--
 src/client/views/nodes/KeyValuePair.tsx            |  4 ++--
 src/client/views/nodes/LinkBox.tsx                 | 24 ++++++++--------------
 8 files changed, 25 insertions(+), 32 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index b0e66787e..ae194bcc7 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -2,6 +2,7 @@ import v4 = require('uuid/v4');
 import v5 = require("uuid/v5");
 import { Socket } from 'socket.io';
 import { Message, Types } from './server/Message';
+import { Document } from './fields/Document';
 
 export class Utils {
 
@@ -96,4 +97,6 @@ export function returnFalse() {
 
 export function emptyFunction() { }
 
+export function emptyDocFunction(doc: Document) { console.log("focus " + doc.Title) }
+
 export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
\ No newline at end of file
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 15ac0a8fc..c172e870e 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -244,7 +244,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     onLinkButtonMoved = async (e: PointerEvent) => {
-        if (this._linkButton.current !== null) {
+        if (this._linkButton.current !== null && (e.movementX > 1 || e.movementY > 1)) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved);
             document.removeEventListener("pointerup", this.onLinkButtonUp);
 
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 60f7098fb..419de6fc1 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -15,7 +15,7 @@ import { ListField } from '../../fields/ListField';
 import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { MessageStore } from '../../server/Message';
-import { Utils, returnTrue, emptyFunction } from '../../Utils';
+import { Utils, returnTrue, emptyFunction, emptyDocFunction } from '../../Utils';
 import * as rp from 'request-promise';
 import { RouteStore } from '../../server/RouteStore';
 import { ServerUtils } from '../../server/ServerUtil';
@@ -202,7 +202,6 @@ export class Main extends React.Component {
 
     pwidthFunc = () => this.pwidth;
     pheightFunc = () => this.pheight;
-    focusDocument = (doc: Document) => { };
     noScaling = () => 1;
 
     @observable _textDoc?: Document = undefined;
@@ -280,7 +279,8 @@ export class Main extends React.Component {
             s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
             return <div className="mainDiv-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
                 <div className="mainDiv-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
-                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={(doc) => { }} />
+                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
+                        selectOnLoad={true} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
                 </div>
             </ div>;
         }
@@ -299,7 +299,7 @@ export class Main extends React.Component {
                 PanelHeight={this.pheightFunc}
                 isTopMost={true}
                 selectOnLoad={false}
-                focus={this.focusDocument}
+                focus={emptyDocFunction}
                 parentActive={returnTrue}
                 onActiveChanged={emptyFunction}
                 ContainingCollectionView={undefined} />;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e54c25474..77ffb4157 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -8,7 +8,7 @@ import { Document } from "../../../fields/Document";
 import { KeyStore } from "../../../fields/KeyStore";
 import Measure from "react-measure";
 import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field";
-import { Utils, returnTrue, emptyFunction } from "../../../Utils";
+import { Utils, returnTrue, emptyFunction, emptyDocFunction } from "../../../Utils";
 import { Server } from "../../Server";
 import { undoBatch } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
@@ -350,7 +350,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     selectOnLoad={false}
                     parentActive={returnTrue}
                     onActiveChanged={emptyFunction}
-                    focus={(doc: Document) => { }}
+                    focus={emptyDocFunction}
                     ContainingCollectionView={undefined} />
             </div>;
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f53b2a76e..4cf187963 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -26,7 +26,7 @@ import { CollectionView } from "./CollectionView";
 import { CollectionSubView } from "./CollectionSubView";
 import { TextField } from "../../../fields/TextField";
 import * as globalCssVariables from "../../views/globalCssVariables.scss";
-import { emptyFunction, returnFalse } from "../../../Utils";
+import { emptyFunction, returnFalse, emptyDocFunction } from "../../../Utils";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -82,7 +82,7 @@ export class CollectionSchemaView extends CollectionSubView {
             isTopMost: false,
             selectOnLoad: false,
             ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
+            focus: emptyDocFunction,
             active: returnFalse,
             onActiveChanged: emptyFunction,
         };
@@ -253,8 +253,6 @@ export class CollectionSchemaView extends CollectionSubView {
     getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling);
     getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
 
-    focusDocument = (doc: Document) => { };
-
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             e.stopPropagation();
@@ -317,7 +315,7 @@ export class CollectionSchemaView extends CollectionSubView {
                                 PanelWidth={this.getPanelWidth}
                                 PanelHeight={this.getPanelHeight}
                                 ContainingCollectionView={undefined}
-                                focus={this.focusDocument}
+                                focus={emptyDocFunction}
                                 parentActive={this.props.active}
                                 onActiveChanged={this.props.onActiveChanged} /> : null}
                         <input value={this.previewScript} onChange={this.onPreviewScriptChange}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 40b44aae5..0037d7b28 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -19,7 +19,7 @@ import { ListField } from "../../../fields/ListField";
 import { DocumentContentsView } from "./DocumentContentsView";
 import { Transform } from "../../util/Transform";
 import { KeyStore } from "../../../fields/KeyStore";
-import { returnFalse, emptyFunction } from "../../../Utils";
+import { returnFalse, emptyDocFunction } from "../../../Utils";
 
 
 //
@@ -85,7 +85,7 @@ export class FieldView extends React.Component<FieldViewProps> {
                     PanelHeight={() => 100}
                     isTopMost={true} //TODO Why is this top most?
                     selectOnLoad={false}
-                    focus={emptyFunction}
+                    focus={emptyDocFunction}
                     isSelected={returnFalse}
                     select={returnFalse}
                     layoutKey={KeyStore.Layout}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index a1050dc6e..7f43d8fdf 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -12,7 +12,7 @@ import { Server } from "../../Server";
 import { EditableView } from "../EditableView";
 import { CompileScript, ToField } from "../../util/Scripting";
 import { Transform } from '../../util/Transform';
-import { returnFalse, emptyFunction } from '../../../Utils';
+import { returnFalse, emptyFunction, emptyDocFunction } from '../../../Utils';
 
 // Represents one row in a key value plane
 
@@ -54,7 +54,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             active: returnFalse,
             onActiveChanged: emptyFunction,
             ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
+            focus: emptyDocFunction,
         };
         let contents = (
             <FieldView {...props} />
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index b016a3d48..1c0e316e8 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -1,24 +1,16 @@
-import { observable, computed, action } from "mobx";
-import React = require("react");
-import { SelectionManager } from "../../util/SelectionManager";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faEdit, faEye, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { observer } from "mobx-react";
-import './LinkBox.scss';
-import { KeyStore } from '../../../fields/KeyStore';
-import { props } from "bluebird";
-import { DocumentView } from "./DocumentView";
 import { Document } from "../../../fields/Document";
+import { KeyStore } from '../../../fields/KeyStore';
 import { ListField } from "../../../fields/ListField";
+import { NumberField } from "../../../fields/NumberField";
 import { DocumentManager } from "../../util/DocumentManager";
-import { LinkEditor } from "./LinkEditor";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faEye } from '@fortawesome/free-solid-svg-icons';
-import { faEdit } from '@fortawesome/free-solid-svg-icons';
-import { faTimes } from '@fortawesome/free-solid-svg-icons';
 import { undoBatch } from "../../util/UndoManager";
-import { FieldWaiting } from "../../../fields/Field";
-import { NumberField } from "../../../fields/NumberField";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import './LinkBox.scss';
+import React = require("react");
 
 
 library.add(faEye);
-- 
cgit v1.2.3-70-g09d2


From ed9bb54c6307e809c6c6aa40c7d77cd3480e7e73 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 13 Apr 2019 00:31:14 -0400
Subject: added some undo's

---
 src/client/views/DocumentDecorations.tsx                        | 3 +++
 src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 3 +++
 2 files changed, 6 insertions(+)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c172e870e..2dc496bc1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -17,6 +17,8 @@ import React = require("react");
 import { FieldWaiting } from "../../fields/Field";
 import { emptyFunction } from "../../Utils";
 import { Main } from "./Main";
+import { undo } from "prosemirror-history";
+import { undoBatch } from "../util/UndoManager";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -156,6 +158,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (e.button === 0) {
         }
     }
+    @undoBatch
     @action
     onCloseUp = (e: PointerEvent): void => {
         e.stopPropagation();
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 9c0d75c22..ccc2fcf0c 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -12,6 +12,8 @@ import { PreviewCursor } from "../../PreviewCursor";
 import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
 import React = require("react");
+import { undo } from "prosemirror-history";
+import { undoBatch } from "../../../util/UndoManager";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -128,6 +130,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) };
     }
 
+    @undoBatch
     @action
     marqueeCommand = (e: KeyboardEvent) => {
         if (e.key === "Backspace" || e.key === "Delete") {
-- 
cgit v1.2.3-70-g09d2


From 845057ef78f272faf488b5bbc2fe79d64fb64120 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 14 Apr 2019 19:44:38 -0400
Subject: mostly northstar cleanup, plus cleaning up main.tsx

---
 src/client/northstar/dash-nodes/HistogramBox.tsx   |   2 +-
 src/client/northstar/manager/Gateway.ts            |  16 +-
 .../model/binRanges/VisualBinRangeHelper.ts        |   2 +-
 src/client/util/DragManager.ts                     |   9 +-
 src/client/util/SelectionManager.ts                |   3 +-
 src/client/views/DocumentDecorations.tsx           |  16 +-
 src/client/views/Main.scss                         |  18 --
 src/client/views/Main.tsx                          | 279 ++++++---------------
 src/client/views/MainOverlayTextBox.scss           |  19 ++
 src/client/views/MainOverlayTextBox.tsx            | 110 ++++++++
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   3 +-
 src/client/views/nodes/FormattedTextBox.tsx        |   9 +-
 src/fields/KeyStore.ts                             |   2 +-
 .../authentication/models/current_user_utils.ts    |  99 +++-----
 src/server/authentication/models/user_model.ts     |  21 +-
 15 files changed, 286 insertions(+), 322 deletions(-)
 create mode 100644 src/client/views/MainOverlayTextBox.scss
 create mode 100644 src/client/views/MainOverlayTextBox.tsx

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

diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index 2084fc346..3e94fed81 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -8,7 +8,7 @@ import { KeyStore } from "../../../fields/KeyStore";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { ChartType, VisualBinRange } from '../../northstar/model/binRanges/VisualBinRange';
 import { VisualBinRangeHelper } from "../../northstar/model/binRanges/VisualBinRangeHelper";
-import { AggregateBinRange, AggregateFunction, BinRange, Catalog, DoubleValueAggregateResult, HistogramResult, Result } from "../../northstar/model/idea/idea";
+import { AggregateBinRange, AggregateFunction, BinRange, Catalog, DoubleValueAggregateResult, HistogramResult } from "../../northstar/model/idea/idea";
 import { ModelHelpers } from "../../northstar/model/ModelHelpers";
 import { HistogramOperation } from "../../northstar/operations/HistogramOperation";
 import { SizeConverter } from "../../northstar/utils/SizeConverter";
diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts
index 207a9ad19..d26f2724f 100644
--- a/src/client/northstar/manager/Gateway.ts
+++ b/src/client/northstar/manager/Gateway.ts
@@ -36,7 +36,7 @@ export class Gateway {
 
     public async ClearCatalog(): Promise<void> {
         try {
-            const json = await this.MakePostJsonRequest("Datamart/ClearAllAugmentations", {});
+            await this.MakePostJsonRequest("Datamart/ClearAllAugmentations", {});
         }
         catch (error) {
             throw new Error("can not reach northstar's backend");
@@ -180,18 +180,18 @@ export class Gateway {
 
 
     public static ConstructUrl(appendix: string): string {
-        let base = Settings.Instance.ServerUrl;
+        let base = NorthstarSettings.Instance.ServerUrl;
         if (base.slice(-1) === "/") {
             base = base.slice(0, -1);
         }
-        let url = base + "/" + Settings.Instance.ServerApiPath + "/" + appendix;
+        let url = base + "/" + NorthstarSettings.Instance.ServerApiPath + "/" + appendix;
         return url;
     }
 }
 
 declare var ENV: any;
 
-export class Settings {
+export class NorthstarSettings {
     private _environment: any;
 
     @observable
@@ -248,10 +248,10 @@ export class Settings {
         return window.location.origin + "/";
     }
 
-    private static _instance: Settings;
+    private static _instance: NorthstarSettings;
 
     @action
-    public Update(environment: any): void {
+    public UpdateEnvironment(environment: any): void {
         /*let serverParam = new URL(document.URL).searchParams.get("serverUrl");
         if (serverParam) {
             if (serverParam === "debug") {
@@ -278,9 +278,9 @@ export class Settings {
         this.DegreeOfParallelism = environment.DEGREE_OF_PARALLISM;
     }
 
-    public static get Instance(): Settings {
+    public static get Instance(): NorthstarSettings {
         if (!this._instance) {
-            this._instance = new Settings();
+            this._instance = new NorthstarSettings();
         }
         return this._instance;
     }
diff --git a/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts b/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
index 9671e55f8..a92412686 100644
--- a/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
+++ b/src/client/northstar/model/binRanges/VisualBinRangeHelper.ts
@@ -4,7 +4,7 @@ import { NominalVisualBinRange } from "./NominalVisualBinRange";
 import { QuantitativeVisualBinRange } from "./QuantitativeVisualBinRange";
 import { AlphabeticVisualBinRange } from "./AlphabeticVisualBinRange";
 import { DateTimeVisualBinRange } from "./DateTimeVisualBinRange";
-import { Settings } from "../../manager/Gateway";
+import { NorthstarSettings } from "../../manager/Gateway";
 import { ModelHelpers } from "../ModelHelpers";
 import { AttributeTransformationModel } from "../../core/attribute/AttributeTransformationModel";
 
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 2ee36d2ec..4bd654e15 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,13 +1,12 @@
 import { action } from "mobx";
 import { Document } from "../../fields/Document";
+import { FieldWaiting } from "../../fields/Field";
+import { KeyStore } from "../../fields/KeyStore";
 import { emptyFunction } from "../../Utils";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { DocumentDecorations } from "../views/DocumentDecorations";
-import { Main } from "../views/Main";
-import { DocumentView } from "../views/nodes/DocumentView";
 import * as globalCssVariables from "../views/globalCssVariables.scss";
-import { KeyStore } from "../../fields/KeyStore";
-import { FieldWaiting } from "../../fields/Field";
+import { MainOverlayTextBox } from "../views/MainOverlayTextBox";
 
 export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
     let onRowMove = action((e: PointerEvent): void => {
@@ -177,7 +176,7 @@ export namespace DragManager {
             dragDiv.className = "dragManager-dragDiv";
             DragManager.Root().appendChild(dragDiv);
         }
-        Main.Instance.SetTextDoc();
+        MainOverlayTextBox.Instance.SetTextDoc();
 
         let scaleXs: number[] = [];
         let scaleYs: number[] = [];
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 2fa45a086..c56f6a4ff 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -2,6 +2,7 @@ import { observable, action } from "mobx";
 import { DocumentView } from "../views/nodes/DocumentView";
 import { Document } from "../../fields/Document";
 import { Main } from "../views/Main";
+import { MainOverlayTextBox } from "../views/MainOverlayTextBox";
 
 export namespace SelectionManager {
     class Manager {
@@ -25,7 +26,7 @@ export namespace SelectionManager {
         DeselectAll(): void {
             manager.SelectedDocuments.map(dv => dv.props.onActiveChanged(false));
             manager.SelectedDocuments = [];
-            Main.Instance.SetTextDoc();
+            MainOverlayTextBox.Instance.SetTextDoc();
         }
     }
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 2dc496bc1..b97a47a3c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,24 +1,20 @@
-import { action, computed, observable, trace, runInAction } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Key } from "../../fields/Key";
 //import ContentEditable from 'react-contenteditable'
 import { KeyStore } from "../../fields/KeyStore";
 import { ListField } from "../../fields/ListField";
 import { NumberField } from "../../fields/NumberField";
-import { Document } from "../../fields/Document";
 import { TextField } from "../../fields/TextField";
-import { DragManager, DragLinksAsDocuments } from "../util/DragManager";
+import { emptyFunction } from "../../Utils";
+import { DragLinksAsDocuments, DragManager } from "../util/DragManager";
 import { SelectionManager } from "../util/SelectionManager";
-import { CollectionView } from "./collections/CollectionView";
+import { undoBatch } from "../util/UndoManager";
 import './DocumentDecorations.scss';
+import { MainOverlayTextBox } from "./MainOverlayTextBox";
 import { DocumentView } from "./nodes/DocumentView";
 import { LinkMenu } from "./nodes/LinkMenu";
 import React = require("react");
-import { FieldWaiting } from "../../fields/Field";
-import { emptyFunction } from "../../Utils";
-import { Main } from "./Main";
-import { undo } from "prosemirror-history";
-import { undoBatch } from "../util/UndoManager";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -304,7 +300,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 break;
         }
 
-        Main.Instance.SetTextDoc();
+        MainOverlayTextBox.Instance.SetTextDoc();
         SelectionManager.SelectedDocuments().forEach(element => {
             const rect = element.screenRect();
             if (rect.width !== 0) {
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 13cadb10d..4373534b2 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -168,24 +168,6 @@ button:hover {
     left:0;
     overflow: scroll;
 }
-.mainDiv-textInput {
-    background-color: rgba(248, 6, 6, 0.001);
-    width: 200px;
-    height: 200px;
-    position:absolute;
-    overflow: visible;
-    top: 0;
-    left: 0;
-    z-index: $mainTextInput-zindex;
-    .formattedTextBox-cont {
-        background-color: rgba(248, 6, 6, 0.001);
-        width: 100%;
-        height: 100%;
-        position:absolute;
-        top: 0;
-        left: 0;
-    }
-}
 #mainContent-div {
     width:100%;
     height:100%;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index f8c6ec0e2..51c076b14 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -15,20 +15,19 @@ import { ListField } from '../../fields/ListField';
 import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { MessageStore } from '../../server/Message';
-import { Utils, returnTrue, emptyFunction, emptyDocFunction } from '../../Utils';
-import * as rp from 'request-promise';
 import { RouteStore } from '../../server/RouteStore';
 import { ServerUtils } from '../../server/ServerUtil';
+import { emptyDocFunction, emptyFunction, returnTrue, Utils } from '../../Utils';
 import { Documents } from '../documents/Documents';
 import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
 import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
-import { Gateway, Settings } from '../northstar/manager/Gateway';
-import { AggregateFunction, Catalog, Point } from '../northstar/model/idea/idea';
+import { Gateway, NorthstarSettings } from '../northstar/manager/Gateway';
+import { AggregateFunction, Catalog } from '../northstar/model/idea/idea';
 import '../northstar/model/ModelExtensions';
 import { HistogramOperation } from '../northstar/operations/HistogramOperation';
 import '../northstar/utils/Extensions';
 import { Server } from '../Server';
-import { SetupDrag, DragManager } from '../util/DragManager';
+import { SetupDrag } from '../util/DragManager';
 import { Transform } from '../util/Transform';
 import { UndoManager } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
@@ -36,41 +35,28 @@ import { ContextMenu } from './ContextMenu';
 import { DocumentDecorations } from './DocumentDecorations';
 import { InkingControl } from './InkingControl';
 import "./Main.scss";
+import { MainOverlayTextBox } from './MainOverlayTextBox';
 import { DocumentView } from './nodes/DocumentView';
-import { FormattedTextBox } from './nodes/FormattedTextBox';
-import { REPLCommand } from 'repl';
-import { Key } from '../../fields/Key';
 import { PreviewCursor } from './PreviewCursor';
 
 
 @observer
 export class Main extends React.Component {
-    // dummy initializations keep the compiler happy
-    @observable private mainfreeform?: Document;
+    public static Instance: Main;
+    @observable private _workspacesShown: boolean = false;
     @observable public pwidth: number = 0;
     @observable public pheight: number = 0;
-    private _northstarSchemas: Document[] = [];
 
     @computed private get mainContainer(): Document | undefined {
-        let doc = this.userDocument.GetT(KeyStore.ActiveWorkspace, Document);
+        let doc = CurrentUserUtils.UserDocument.GetT(KeyStore.ActiveWorkspace, Document);
         return doc === FieldWaiting ? undefined : doc;
     }
-
     private set mainContainer(doc: Document | undefined) {
-        if (doc) {
-            this.userDocument.Set(KeyStore.ActiveWorkspace, doc);
-        }
+        doc && CurrentUserUtils.UserDocument.Set(KeyStore.ActiveWorkspace, doc);
     }
 
-    private get userDocument(): Document {
-        return CurrentUserUtils.UserDocument;
-    }
-
-    public static Instance: Main;
-
     constructor(props: Readonly<{}>) {
         super(props);
-        this._textProxyDiv = React.createRef();
         Main.Instance = this;
         // causes errors to be generated when modifying an observable outside of an action
         configure({ enforceActions: "observed" });
@@ -102,6 +88,10 @@ export class Main extends React.Component {
         this.initializeNorthstar();
     }
 
+    componentDidMount() { window.onpopstate = this.onHistory; }
+
+    componentWillUnmount() { window.onpopstate = null; }
+
     onHistory = () => {
         if (window.location.pathname !== RouteStore.home) {
             let pathname = window.location.pathname.split("/");
@@ -114,14 +104,6 @@ export class Main extends React.Component {
         }
     }
 
-    componentDidMount() {
-        window.onpopstate = this.onHistory;
-    }
-
-    componentWillUnmount() {
-        window.onpopstate = null;
-    }
-
     initEventListeners = () => {
         // window.addEventListener("pointermove", (e) => this.reportLocation(e))
         window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler
@@ -137,7 +119,7 @@ export class Main extends React.Component {
     initAuthenticationRouters = () => {
         // Load the user's active workspace, or create a new one if initial session after signup
         if (!CurrentUserUtils.MainDocId) {
-            this.userDocument.GetTAsync(KeyStore.ActiveWorkspace, Document).then(doc => {
+            CurrentUserUtils.UserDocument.GetTAsync(KeyStore.ActiveWorkspace, Document).then(doc => {
                 if (doc) {
                     CurrentUserUtils.MainDocId = doc.Id;
                     this.openWorkspace(doc);
@@ -158,7 +140,7 @@ export class Main extends React.Component {
 
     @action
     createNewWorkspace = (id?: string): void => {
-        this.userDocument.GetTAsync<ListField<Document>>(KeyStore.Workspaces, ListField).then(action((list: Opt<ListField<Document>>) => {
+        CurrentUserUtils.UserDocument.GetTAsync<ListField<Document>>(KeyStore.Workspaces, ListField).then(action((list: Opt<ListField<Document>>) => {
             if (list) {
                 let freeformDoc = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
                 var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc)] }] };
@@ -179,7 +161,7 @@ export class Main extends React.Component {
     openWorkspace = (doc: Document, fromHistory = false): void => {
         this.mainContainer = doc;
         fromHistory || window.history.pushState(null, doc.Title, "/doc/" + doc.Id);
-        this.userDocument.GetTAsync(KeyStore.OptionalRightCollection, Document).then(col => {
+        CurrentUserUtils.UserDocument.GetTAsync(KeyStore.OptionalRightCollection, Document).then(col => {
             // if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized)
             setTimeout(() => {
                 if (col) {
@@ -193,119 +175,33 @@ export class Main extends React.Component {
         });
     }
 
-    @observable
-    workspacesShown: boolean = false;
-
-    areWorkspacesShown = () => this.workspacesShown;
-    @action
-    toggleWorkspaces = () => {
-        this.workspacesShown = !this.workspacesShown;
-    }
-
-    pwidthFunc = () => this.pwidth;
-    pheightFunc = () => this.pheight;
-    noScaling = () => 1;
-
-    @observable _textDoc?: Document = undefined;
-    _textRect: any;
-    _textXf: Transform = Transform.Identity();
-    _textScroll: number = 0;
-    _textFieldKey: Key = KeyStore.Data;
-    _textColor: string | null = null;
-    _textTargetDiv: HTMLDivElement | undefined;
-    _textProxyDiv: React.RefObject<HTMLDivElement>;
-    @action
-    SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: Transform) {
-        if (this._textTargetDiv) {
-            this._textTargetDiv.style.color = this._textColor;
-        }
-
-        this._textDoc = undefined;
-        this._textDoc = textDoc;
-        this._textFieldKey = textFieldKey!;
-        this._textXf = tx ? tx : Transform.Identity();
-        this._textTargetDiv = div;
-        if (div) {
-            this._textColor = div.style.color;
-            div.style.color = "transparent";
-            this._textRect = div.getBoundingClientRect();
-            this._textScroll = div.scrollTop;
-        }
-    }
-
-    @action
-    textScroll = (e: React.UIEvent) => {
-        if (this._textProxyDiv.current && this._textTargetDiv) {
-            this._textTargetDiv.scrollTop = this._textScroll = this._textProxyDiv.current.children[0].scrollTop;
-        }
-    }
-
-    textBoxDown = (e: React.PointerEvent) => {
-        if (e.button !== 0 || e.metaKey || e.altKey) {
-            document.addEventListener("pointermove", this.textBoxMove);
-            document.addEventListener('pointerup', this.textBoxUp);
-        }
-    }
-    textBoxMove = (e: PointerEvent) => {
-        if (e.movementX > 1 || e.movementY > 1) {
-            document.removeEventListener("pointermove", this.textBoxMove);
-            document.removeEventListener('pointerup', this.textBoxUp);
-            let dragData = new DragManager.DocumentDragData([this._textDoc!]);
-            const [left, top] = this._textXf
-                .inverse()
-                .transformPoint(0, 0);
-            dragData.xOffset = e.clientX - left;
-            dragData.yOffset = e.clientY - top;
-            DragManager.StartDocumentDrag([this._textTargetDiv!], dragData, e.clientX, e.clientY, {
-                handlers: {
-                    dragComplete: action(emptyFunction),
-                },
-                hideSource: false
-            });
-        }
-    }
-    textBoxUp = (e: PointerEvent) => {
-        document.removeEventListener("pointermove", this.textBoxMove);
-        document.removeEventListener('pointerup', this.textBoxUp);
-    }
-
-    @computed
-    get activeTextBox() {
-        if (this._textDoc) {
-            let x: number = this._textRect.x;
-            let y: number = this._textRect.y;
-            let w: number = this._textRect.width;
-            let h: number = this._textRect.height;
-            let t = this._textXf.transformPoint(0, 0);
-            let s = this._textXf.transformPoint(1, 0);
-            s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
-            return <div className="mainDiv-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
-                <div className="mainDiv-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
-                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this._textDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
-                        selectOnLoad={true} ContainingCollectionView={undefined} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
-                </div>
-            </ div>;
-        }
-        else return (null);
-    }
-
     @computed
     get mainContent() {
-        return !this.mainContainer ? (null) :
-            <DocumentView Document={this.mainContainer}
-                addDocument={undefined}
-                removeDocument={undefined}
-                opacity={1}
-                ScreenToLocalTransform={Transform.Identity}
-                ContentScaling={this.noScaling}
-                PanelWidth={this.pwidthFunc}
-                PanelHeight={this.pheightFunc}
-                isTopMost={true}
-                selectOnLoad={false}
-                focus={emptyDocFunction}
-                parentActive={returnTrue}
-                onActiveChanged={emptyFunction}
-                ContainingCollectionView={undefined} />;
+        trace();
+        let pwidthFunc = () => this.pwidth;
+        let pheightFunc = () => this.pheight;
+        let noScaling = () => 1;
+        return <Measure onResize={action((r: any) => { this.pwidth = r.entry.width; this.pheight = r.entry.height; })}>
+            {({ measureRef }) =>
+                <div ref={measureRef} id="mainContent-div">
+                    {!this.mainContainer ? (null) :
+                        <DocumentView Document={this.mainContainer}
+                            addDocument={undefined}
+                            removeDocument={undefined}
+                            opacity={1}
+                            ScreenToLocalTransform={Transform.Identity}
+                            ContentScaling={noScaling}
+                            PanelWidth={pwidthFunc}
+                            PanelHeight={pheightFunc}
+                            isTopMost={true}
+                            selectOnLoad={false}
+                            focus={emptyDocFunction}
+                            parentActive={returnTrue}
+                            onActiveChanged={emptyFunction}
+                            ContainingCollectionView={undefined} />}
+                </div>
+            }
+        </Measure>;
     }
 
     /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */
@@ -361,6 +257,7 @@ export class Main extends React.Component {
     get miscButtons() {
         let workspacesRef = React.createRef<HTMLDivElement>();
         let logoutRef = React.createRef<HTMLDivElement>();
+        let toggleWorkspaces = () => runInAction(() => { this._workspacesShown = !this._workspacesShown; });
 
         let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}));
         return [
@@ -371,55 +268,50 @@ export class Main extends React.Component {
                 <button className="toolbar-button round-button" title="Ink" onClick={() => InkingControl.Instance.toggleDisplay()}><FontAwesomeIcon icon="pen-nib" size="sm" /></button>
             </div >,
             <div className="main-buttonDiv" key="workspaces" style={{ top: '34px', left: '2px', position: 'absolute' }} ref={workspacesRef}>
-                <button onClick={this.toggleWorkspaces}>Workspaces</button></div>,
+                <button onClick={toggleWorkspaces}>Workspaces</button></div>,
             <div className="main-buttonDiv" key="logout" style={{ top: '34px', right: '1px', position: 'absolute' }} ref={logoutRef}>
                 <button onClick={() => request.get(ServerUtils.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
         ];
     }
 
+    @computed
+    get workspaceMenu() {
+        let areWorkspacesShown = () => this._workspacesShown;
+        let toggleWorkspaces = () => runInAction(() => { this._workspacesShown = !this._workspacesShown; });
+        let workspaces = CurrentUserUtils.UserDocument.GetT<ListField<Document>>(KeyStore.Workspaces, ListField);
+        return (!workspaces || workspaces === FieldWaiting) ? (null) :
+            <WorkspacesMenu active={this.mainContainer} open={this.openWorkspace}
+                new={this.createNewWorkspace} allWorkspaces={workspaces.Data}
+                isShown={areWorkspacesShown} toggle={toggleWorkspaces} />;
+    }
+
     render() {
-        let workspaceMenu: any = null;
-        let workspaces = this.userDocument.GetT<ListField<Document>>(KeyStore.Workspaces, ListField);
-        if (workspaces && workspaces !== FieldWaiting) {
-            workspaceMenu = <WorkspacesMenu active={this.mainContainer} open={this.openWorkspace} new={this.createNewWorkspace} allWorkspaces={workspaces.Data}
-                isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />;
-        }
         return (
-            <>
-                <div id="main-div">
-                    <DocumentDecorations />
-                    <Measure onResize={(r: any) => runInAction(() => {
-                        this.pwidth = r.entry.width;
-                        this.pheight = r.entry.height;
-                    })}>
-                        {({ measureRef }) =>
-                            <div ref={measureRef} id="mainContent-div">
-                                {this.mainContent}
-                                <PreviewCursor />
-                            </div>
-                        }
-                    </Measure>
-                    <ContextMenu />
-                    {this.nodesMenu}
-                    {this.miscButtons}
-                    {workspaceMenu}
-                    <InkingControl />
-                </div>
-                {this.activeTextBox}
-            </>
+            <div id="main-div">
+                <DocumentDecorations />
+                {this.mainContent}
+                <PreviewCursor />
+                <ContextMenu />
+                {this.nodesMenu}
+                {this.miscButtons}
+                {this.workspaceMenu}
+                <InkingControl />
+                <MainOverlayTextBox />
+            </div>
         );
     }
 
     // --------------- Northstar hooks ------------- /
+    private _northstarSchemas: Document[] = [];
 
-    @action AddToNorthstarCatalog(ctlog: Catalog) {
-        CurrentUserUtils.NorthstarDBCatalog = CurrentUserUtils.NorthstarDBCatalog ? CurrentUserUtils.NorthstarDBCatalog : ctlog;
+    @action SetNorthstarCatalog(ctlog: Catalog) {
+        CurrentUserUtils.NorthstarDBCatalog = ctlog;
         if (ctlog && ctlog.schemas) {
             ctlog.schemas.map(schema => {
-                let promises: Promise<void>[] = [];
                 let schemaDocuments: Document[] = [];
-                CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
-                    let prom = Server.GetField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
+                let attributesToBecomeDocs = CurrentUserUtils.GetAllNorthstarColumnAttributes(schema);
+                Promise.all(attributesToBecomeDocs.reduce((promises, attr) => {
+                    promises.push(Server.GetField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
                         if (field instanceof Document) {
                             schemaDocuments.push(field);
                         } else {
@@ -430,32 +322,17 @@ export class Main extends React.Component {
                                 new AttributeTransformationModel(atmod, AggregateFunction.Count));
                             schemaDocuments.push(Documents.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }, undefined, attr.displayName! + ".alias"));
                         }
-                    }));
-                    promises.push(prom);
-                });
-                Promise.all(promises).finally(() => {
-                    let schemaDoc = Documents.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! });
-                    this._northstarSchemas.push(schemaDoc);
-                });
+                    })));
+                    return promises;
+                }, [] as Promise<void>[])).finally(() =>
+                    this._northstarSchemas.push(Documents.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! })));
             });
         }
     }
     async initializeNorthstar(): Promise<void> {
-        let envPath = "/assets/env.json";
-        const response = await fetch(envPath, {
-            redirect: "follow",
-            method: "GET",
-            credentials: "include"
-        });
-        const env = await response.json();
-        Settings.Instance.Update(env);
-        let cat = Gateway.Instance.ClearCatalog();
-        cat.then(async () => {
-            this.AddToNorthstarCatalog(await Gateway.Instance.GetCatalog());
-            // if (!CurrentUserUtils.GetNorthstarSchema("Book1"))
-            //     this.AddToNorthstarCatalog(await Gateway.Instance.GetSchema("http://www.cs.brown.edu/~bcz/Book1.csv", "Book1"));
-        });
-
+        const getEnvironment = await fetch("/assets/env.json", { redirect: "follow", method: "GET", credentials: "include" });
+        NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json());
+        Gateway.Instance.ClearCatalog().then(async () => this.SetNorthstarCatalog(await Gateway.Instance.GetCatalog()));
     }
 }
 
diff --git a/src/client/views/MainOverlayTextBox.scss b/src/client/views/MainOverlayTextBox.scss
new file mode 100644
index 000000000..697d68c8c
--- /dev/null
+++ b/src/client/views/MainOverlayTextBox.scss
@@ -0,0 +1,19 @@
+@import "globalCssVariables";
+.mainOverlayTextBox-textInput {
+    background-color: rgba(248, 6, 6, 0.001);
+    width: 200px;
+    height: 200px;
+    position:absolute;
+    overflow: visible;
+    top: 0;
+    left: 0;
+    z-index: $mainTextInput-zindex;
+    .formattedTextBox-cont {
+        background-color: rgba(248, 6, 6, 0.001);
+        width: 100%;
+        height: 100%;
+        position:absolute;
+        top: 0;
+        left: 0;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
new file mode 100644
index 000000000..df1addbc7
--- /dev/null
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -0,0 +1,110 @@
+import { action, observable, trace } from 'mobx';
+import { observer } from 'mobx-react';
+import "normalize.css";
+import * as React from 'react';
+import { Document } from '../../fields/Document';
+import { Key } from '../../fields/Key';
+import { KeyStore } from '../../fields/KeyStore';
+import { emptyDocFunction, emptyFunction, returnTrue } from '../../Utils';
+import '../northstar/model/ModelExtensions';
+import '../northstar/utils/Extensions';
+import { DragManager } from '../util/DragManager';
+import { Transform } from '../util/Transform';
+import "./MainOverlayTextBox.scss";
+import { FormattedTextBox } from './nodes/FormattedTextBox';
+
+interface MainOverlayTextBoxProps {
+}
+
+@observer
+export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps> {
+    public static Instance: MainOverlayTextBox;
+    @observable public TextDoc?: Document = undefined;
+    public TextScroll: number = 0;
+    private _textRect: any;
+    private _textXf: Transform = Transform.Identity();
+    private _textFieldKey: Key = KeyStore.Data;
+    private _textColor: string | null = null;
+    private _textTargetDiv: HTMLDivElement | undefined;
+    private _textProxyDiv: React.RefObject<HTMLDivElement>;
+
+    constructor(props: MainOverlayTextBoxProps) {
+        super(props);
+        this._textProxyDiv = React.createRef();
+        MainOverlayTextBox.Instance = this;
+    }
+
+    @action
+    SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: Transform) {
+        if (this._textTargetDiv) {
+            this._textTargetDiv.style.color = this._textColor;
+        }
+
+        this.TextDoc = undefined;
+        this.TextDoc = textDoc;
+        this._textFieldKey = textFieldKey!;
+        this._textXf = tx ? tx : Transform.Identity();
+        this._textTargetDiv = div;
+        if (div) {
+            this._textColor = div.style.color;
+            div.style.color = "transparent";
+            this._textRect = div.getBoundingClientRect();
+            this.TextScroll = div.scrollTop;
+        }
+    }
+
+    @action
+    textScroll = (e: React.UIEvent) => {
+        if (this._textProxyDiv.current && this._textTargetDiv) {
+            this._textTargetDiv.scrollTop = this.TextScroll = this._textProxyDiv.current.children[0].scrollTop;
+        }
+    }
+
+    textBoxDown = (e: React.PointerEvent) => {
+        if (e.button !== 0 || e.metaKey || e.altKey) {
+            document.addEventListener("pointermove", this.textBoxMove);
+            document.addEventListener('pointerup', this.textBoxUp);
+        }
+    }
+    textBoxMove = (e: PointerEvent) => {
+        if (e.movementX > 1 || e.movementY > 1) {
+            document.removeEventListener("pointermove", this.textBoxMove);
+            document.removeEventListener('pointerup', this.textBoxUp);
+            let dragData = new DragManager.DocumentDragData([this.TextDoc!]);
+            const [left, top] = this._textXf
+                .inverse()
+                .transformPoint(0, 0);
+            dragData.xOffset = e.clientX - left;
+            dragData.yOffset = e.clientY - top;
+            DragManager.StartDocumentDrag([this._textTargetDiv!], dragData, e.clientX, e.clientY, {
+                handlers: {
+                    dragComplete: action(emptyFunction),
+                },
+                hideSource: false
+            });
+        }
+    }
+    textBoxUp = (e: PointerEvent) => {
+        document.removeEventListener("pointermove", this.textBoxMove);
+        document.removeEventListener('pointerup', this.textBoxUp);
+    }
+
+    render() {
+        if (this.TextDoc) {
+            let x: number = this._textRect.x;
+            let y: number = this._textRect.y;
+            let w: number = this._textRect.width;
+            let h: number = this._textRect.height;
+            let t = this._textXf.transformPoint(0, 0);
+            let s = this._textXf.transformPoint(1, 0);
+            s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
+            return <div className="mainOverlayTextBox-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
+                <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
+                    <FormattedTextBox fieldKey={this._textFieldKey!} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
+                        selectOnLoad={true} ContainingCollectionView={undefined} onActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
+                </div>
+            </ div>;
+        }
+        else return (null);
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 6c382a353..cb4e8fb2e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -24,6 +24,7 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import v5 = require("uuid/v5");
+import { MainOverlayTextBox } from "../../MainOverlayTextBox";
 
 @observer
 export class CollectionFreeFormView extends CollectionSubView {
@@ -205,7 +206,7 @@ export class CollectionFreeFormView extends CollectionSubView {
 
     @action
     private SetPan(panX: number, panY: number) {
-        Main.Instance.SetTextDoc();
+        MainOverlayTextBox.Instance.SetTextDoc();
         var x1 = this.getLocalTransform().inverse().Scale;
         const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX));
         const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY));
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 2e6272836..87c1bcb1e 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -16,6 +16,7 @@ import "./FormattedTextBox.scss";
 import React = require("react");
 import { TextField } from "../../../fields/TextField";
 import { KeyStore } from "../../../fields/KeyStore";
+import { MainOverlayTextBox } from "../MainOverlayTextBox";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -92,7 +93,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         };
 
         if (this.props.isOverlay) {
-            this._inputReactionDisposer = reaction(() => Main.Instance._textDoc && Main.Instance._textDoc.Id,
+            this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc.Id,
                 () => {
                     if (this._editorView) {
                         this._editorView.destroy();
@@ -103,7 +104,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
             );
         } else {
             this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
-                () => this.props.isSelected() && Main.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform()));
+                () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform()));
         }
 
         this._reactionDisposer = reaction(
@@ -184,10 +185,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
 
     onFocused = (e: React.FocusEvent): void => {
         if (!this.props.isOverlay) {
-            Main.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform());
+            MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform());
         } else {
             if (this._ref.current) {
-                this._ref.current.scrollTop = Main.Instance._textScroll;
+                this._ref.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
             }
         }
     }
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 19431bbe3..16a909eb8 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -49,7 +49,7 @@ export namespace KeyStore {
     export const CopyDraggedItems = new Key("CopyDraggedItems");
 
     export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight,
-        Width, Height, ZIndex, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
+        Width, Height, ZIndex, Zoom, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
         LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs,
         LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection,
         Archives, Workspaces, Minimized, CopyDraggedItems
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 13eddafbf..34454eda0 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -1,15 +1,14 @@
-import { DashUserModel } from "./user_model";
+import { computed, observable, action } from "mobx";
 import * as rp from 'request-promise';
-import { RouteStore } from "../../RouteStore";
-import { ServerUtils } from "../../ServerUtil";
+import { Documents } from "../../../client/documents/Documents";
+import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea";
+import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil";
 import { Server } from "../../../client/Server";
 import { Document } from "../../../fields/Document";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
-import { Documents } from "../../../client/documents/Documents";
-import { Schema, Attribute, AttributeGroup, Catalog } from "../../../client/northstar/model/idea/idea";
-import { observable, computed, action } from "mobx";
-import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil";
+import { RouteStore } from "../../RouteStore";
+import { ServerUtils } from "../../ServerUtil";
 
 export class CurrentUserUtils {
     private static curr_email: string;
@@ -17,65 +16,22 @@ export class CurrentUserUtils {
     private static user_document: Document;
     //TODO tfs: these should be temporary...
     private static mainDocId: string | undefined;
-    @observable private static catalog?: Catalog;
-
-    public static get email(): string {
-        return this.curr_email;
-    }
-
-    public static get id(): string {
-        return this.curr_id;
-    }
-
-    public static get UserDocument(): Document {
-        return this.user_document;
-    }
 
-    public static get MainDocId(): string | undefined {
-        return this.mainDocId;
-    }
-
-    public static set MainDocId(id: string | undefined) {
-        this.mainDocId = id;
-    }
-
-    @computed public static get NorthstarDBCatalog(): Catalog | undefined {
-        return this.catalog;
-    }
-    public static set NorthstarDBCatalog(ctlog: Catalog | undefined) {
-        this.catalog = ctlog;
-    }
-    public static GetNorthstarSchema(name: string): Schema | undefined {
-        return !this.catalog || !this.catalog.schemas ? undefined :
-            ArrayUtil.FirstOrDefault<Schema>(this.catalog.schemas, (s: Schema) => s.displayName === name);
-    }
-    public static GetAllNorthstarColumnAttributes(schema: Schema) {
-        if (!schema || !schema.rootAttributeGroup) {
-            return [];
-        }
-        const recurs = (attrs: Attribute[], g: AttributeGroup) => {
-            if (g.attributes) {
-                attrs.push.apply(attrs, g.attributes);
-                if (g.attributeGroups) {
-                    g.attributeGroups.forEach(ng => recurs(attrs, ng));
-                }
-            }
-        };
-        const allAttributes: Attribute[] = new Array<Attribute>();
-        recurs(allAttributes, schema.rootAttributeGroup);
-        return allAttributes;
-    }
+    public static get email() { return this.curr_email; }
+    public static get id() { return this.curr_id; }
+    public static get UserDocument() { return this.user_document; }
+    public static get MainDocId() { return this.mainDocId; }
+    public static set MainDocId(id: string | undefined) { this.mainDocId = id; }
 
     private static createUserDocument(id: string): Document {
         let doc = new Document(id);
-
         doc.Set(KeyStore.Workspaces, new ListField<Document>());
         doc.Set(KeyStore.OptionalRightCollection, Documents.SchemaDocument([], { title: "Pending documents" }));
         return doc;
     }
 
     public static loadCurrentUser(): Promise<any> {
-        let userPromise = rp.get(ServerUtils.prepend(RouteStore.getCurrUser)).then((response) => {
+        let userPromise = rp.get(ServerUtils.prepend(RouteStore.getCurrUser)).then(response => {
             if (response) {
                 let obj = JSON.parse(response);
                 CurrentUserUtils.curr_id = obj.id as string;
@@ -86,17 +42,34 @@ export class CurrentUserUtils {
         });
         let userDocPromise = rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(id => {
             if (id) {
-                return Server.GetField(id).then(field => {
-                    if (field instanceof Document) {
-                        this.user_document = field;
-                    } else {
-                        this.user_document = this.createUserDocument(id);
-                    }
-                });
+                return Server.GetField(id).then(field =>
+                    this.user_document = field instanceof Document ? field : this.createUserDocument(id));
             } else {
                 throw new Error("There should be a user id! Why does Dash think there isn't one?");
             }
         });
         return Promise.all([userPromise, userDocPromise]);
     }
+
+    /* Northstar catalog ... really just for testing so this should eventually go away */
+    @observable private static _northstarCatalog?: Catalog;
+    @computed public static get NorthstarDBCatalog() { return this._northstarCatalog; }
+    public static set NorthstarDBCatalog(ctlog: Catalog | undefined) { this._northstarCatalog = ctlog; }
+
+    public static GetNorthstarSchema(name: string): Schema | undefined {
+        return !this._northstarCatalog || !this._northstarCatalog.schemas ? undefined :
+            ArrayUtil.FirstOrDefault<Schema>(this._northstarCatalog.schemas, (s: Schema) => s.displayName === name);
+    }
+    public static GetAllNorthstarColumnAttributes(schema: Schema) {
+        const recurs = (attrs: Attribute[], g?: AttributeGroup) => {
+            if (g && g.attributes) {
+                attrs.push.apply(attrs, g.attributes);
+                if (g.attributeGroups) {
+                    g.attributeGroups.forEach(ng => recurs(attrs, ng));
+                }
+            }
+            return attrs;
+        };
+        return recurs([] as Attribute[], schema ? schema.rootAttributeGroup : undefined);
+    }
 }
\ No newline at end of file
diff --git a/src/server/authentication/models/user_model.ts b/src/server/authentication/models/user_model.ts
index 1c6926517..d5c84c311 100644
--- a/src/server/authentication/models/user_model.ts
+++ b/src/server/authentication/models/user_model.ts
@@ -18,8 +18,8 @@ mongoose.connection.on('disconnected', function () {
 export type DashUserModel = mongoose.Document & {
     email: string,
     password: string,
-    passwordResetToken: string | undefined,
-    passwordResetExpires: Date | undefined,
+    passwordResetToken?: string,
+    passwordResetExpires?: Date,
 
     userDocumentId: string;
 
@@ -67,11 +67,17 @@ const userSchema = new mongoose.Schema({
  */
 userSchema.pre("save", function save(next) {
     const user = this as DashUserModel;
-    if (!user.isModified("password")) { return next(); }
+    if (!user.isModified("password")) {
+        return next();
+    }
     bcrypt.genSalt(10, (err, salt) => {
-        if (err) { return next(err); }
+        if (err) {
+            return next(err);
+        }
         bcrypt.hash(user.password, salt, () => void {}, (err: mongoose.Error, hash) => {
-            if (err) { return next(err); }
+            if (err) {
+                return next(err);
+            }
             user.password = hash;
             next();
         });
@@ -79,9 +85,8 @@ userSchema.pre("save", function save(next) {
 });
 
 const comparePassword: comparePasswordFunction = function (this: DashUserModel, candidatePassword, cb) {
-    bcrypt.compare(candidatePassword, this.password, (err: mongoose.Error, isMatch: boolean) => {
-        cb(err, isMatch);
-    });
+    bcrypt.compare(candidatePassword, this.password, (err: mongoose.Error, isMatch: boolean) =>
+        cb(err, isMatch));
 };
 
 userSchema.methods.comparePassword = comparePassword;
-- 
cgit v1.2.3-70-g09d2

