From 3808258fe452be2f71354989c0281dc4549f408b Mon Sep 17 00:00:00 2001
From: laurawilsonri <laura_wilson@brown.edu>
Date: Tue, 16 Apr 2019 18:23:49 -0400
Subject:  font dropdowns update now, ui change and bug fix

---
 src/client/util/TooltipTextMenu.tsx | 75 ++++++++++++++++++++++---------------
 1 file changed, 45 insertions(+), 30 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index a92cbd263..4f0eb7d63 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -34,6 +34,9 @@ export class TooltipTextMenu {
     private fontSizeToNum: Map<MarkType, number>;
     private fontStylesToName: Map<MarkType, string>;
     private fontSizeIndicator: HTMLSpanElement = document.createElement("span");
+    //dropdown doms
+    private fontSizeDom: Node;
+    private fontStyleDom: Node;
 
     constructor(view: EditorView, editorProps: FieldViewProps) {
         this.view = view;
@@ -76,7 +79,7 @@ export class TooltipTextMenu {
         this.fontStylesToName.set(schema.marks.timesNewRoman, "Times New Roman");
         this.fontStylesToName.set(schema.marks.arial, "Arial");
         this.fontStylesToName.set(schema.marks.georgia, "Georgia");
-        this.fontStylesToName.set(schema.marks.comicSans, "Comic Sans");
+        this.fontStylesToName.set(schema.marks.comicSans, "Comic Sans MS");
         this.fontStylesToName.set(schema.marks.tahoma, "Tahoma");
         this.fontStylesToName.set(schema.marks.impact, "Impact");
         this.fontStylesToName.set(schema.marks.crimson, "Crimson Text");
@@ -93,23 +96,15 @@ export class TooltipTextMenu {
         this.fontSizeToNum.set(schema.marks.p72, 72);
         this.fontSizes = Array.from(this.fontSizeToNum.keys());
 
-        this.addFontDropdowns();
+        //this.addFontDropdowns();
 
         this.update(view, undefined);
     }
 
-    //adds font size and font style dropdowns
-    addFontDropdowns() {
+    //label of dropdown will change to given label
+    updateFontSizeDropdown(label: string) {
         //filtering function - might be unecessary
         let cut = (arr: MenuItem[]) => arr.filter(x => x);
-        //font STYLES
-        let fontBtns: MenuItem[] = [];
-        this.fontStylesToName.forEach((name, mark) => {
-            fontBtns.push(this.dropdownBtn(name, "font-family: " + name + ", sans-serif; width: 120px;", mark, this.view, this.changeToMarkInGroup, this.fontStyles));
-        });
-
-        //font size indicator
-        this.fontSizeIndicator = this.icon("12", "font-size-indicator");
 
         //font SIZES
         let fontSizeBtns: MenuItem[] = [];
@@ -117,14 +112,32 @@ export class TooltipTextMenu {
             fontSizeBtns.push(this.dropdownBtn(String(number), "width: 50px;", mark, this.view, this.changeToMarkInGroup, this.fontSizes));
         });
 
-        //dropdown to hold font btns
-        let dd_fontStyle = new Dropdown(cut(fontBtns), { label: "Font Style", css: "color:white;" }) as MenuItem;
-        let dd_fontSize = new Dropdown(cut(fontSizeBtns), { label: "Font Size", css: "color:white; margin-left: -6px;" }) as MenuItem;
-        this.tooltip.appendChild(dd_fontStyle.render(this.view).dom);
-        this.tooltip.appendChild(this.fontSizeIndicator);
-        this.tooltip.appendChild(dd_fontSize.render(this.view).dom);
-        dd_fontStyle.render(this.view).dom.nodeValue = "TEST";
-        console.log(dd_fontStyle.render(this.view).dom.nodeValue);
+        if (this.fontSizeDom) { this.tooltip.removeChild(this.fontSizeDom); }
+        this.fontSizeDom = (new Dropdown(cut(fontSizeBtns), {
+            label: label,
+            css: "color:white; min-width: 60px; padding-left: 5px; margin-right: 0;"
+        }) as MenuItem).render(this.view).dom;
+        this.tooltip.appendChild(this.fontSizeDom);
+    }
+
+    //label of dropdown will change to given label
+    updateFontStyleDropdown(label: string) {
+        //filtering function - might be unecessary
+        let cut = (arr: MenuItem[]) => arr.filter(x => x);
+
+        //font STYLES
+        let fontBtns: MenuItem[] = [];
+        this.fontStylesToName.forEach((name, mark) => {
+            fontBtns.push(this.dropdownBtn(name, "font-family: " + name + ", sans-serif; width: 125px;", mark, this.view, this.changeToMarkInGroup, this.fontStyles));
+        });
+
+        if (this.fontStyleDom) { this.tooltip.removeChild(this.fontStyleDom); }
+        this.fontStyleDom = (new Dropdown(cut(fontBtns), {
+            label: label,
+            css: "color:white; width: 125px; margin-left: -3px; padding-left: 2px;"
+        }) as MenuItem).render(this.view).dom;
+
+        this.tooltip.appendChild(this.fontStyleDom);
     }
 
     //for a specific grouping of marks (passed in), remove all and apply the passed-in one to the selected text
@@ -246,30 +259,32 @@ export class TooltipTextMenu {
         let width = Math.abs(start.left - end.left) / 2 * this.editorProps.ScreenToLocalTransform().Scale;
         let mid = Math.min(start.left, end.left) + width;
 
-        this.tooltip.style.width = 220 + "px";
+        this.tooltip.style.width = 225 + "px";
         this.tooltip.style.bottom = (box.bottom - start.top) * this.editorProps.ScreenToLocalTransform().Scale + "px";
 
+        //UPDATE FONT STYLE DROPDOWN
         let activeStyles = this.activeMarksOnSelection(this.fontStyles);
         if (activeStyles.length === 1) {
             // if we want to update something somewhere with active font name
             let fontName = this.fontStylesToName.get(activeStyles[0]);
+            if (fontName) { this.updateFontStyleDropdown(fontName); }
         } else if (activeStyles.length === 0) {
             //crimson on default
+            this.updateFontStyleDropdown("Crimson Text");
+        } else {
+            this.updateFontStyleDropdown("Various");
         }
 
-        //update font size indicator
+        //UPDATE FONT SIZE DROPDOWN
         let activeSizes = this.activeMarksOnSelection(this.fontSizes);
         if (activeSizes.length === 1) { //if there's only one active font size
             let size = this.fontSizeToNum.get(activeSizes[0]);
-            if (size) {
-                this.fontSizeIndicator.innerHTML = String(size);
-            }
-            //should be 14 on default
+            if (size) { this.updateFontSizeDropdown(String(size) + " pt"); }
         } else if (activeSizes.length === 0) {
-            this.fontSizeIndicator.innerHTML = "14";
-            //multiple font sizes selected
-        } else {
-            this.fontSizeIndicator.innerHTML = "";
+            //should be 14 on default  
+            this.updateFontSizeDropdown("14 pt");
+        } else { //multiple font sizes selected
+            this.updateFontSizeDropdown("Various");
         }
     }
 
-- 
cgit v1.2.3-70-g09d2


From b9b7409af655a0b936ec884de62b8a243be1011b Mon Sep 17 00:00:00 2001
From: laurawilsonri <laura_wilson@brown.edu>
Date: Mon, 22 Apr 2019 22:13:10 -0400
Subject: added a dropdown for bullet types

---
 src/client/util/TooltipTextMenu.tsx | 79 ++++++++++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 9 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 4f0eb7d63..95e7ba2bf 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -11,7 +11,8 @@ import React = require("react");
 import "./TooltipTextMenu.scss";
 const { toggleMark, setBlockType, wrapIn } = require("prosemirror-commands");
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { wrapInList, bulletList, liftListItem, listItem } from 'prosemirror-schema-list';
+import { wrapInList, bulletList, liftListItem, listItem, } from 'prosemirror-schema-list';
+import { liftTarget } from 'prosemirror-transform';
 import {
     faListUl,
 } from '@fortawesome/free-solid-svg-icons';
@@ -29,14 +30,17 @@ export class TooltipTextMenu {
     private view: EditorView;
     private fontStyles: MarkType[];
     private fontSizes: MarkType[];
+    private listTypes: NodeType[];
     private editorProps: FieldViewProps;
     private state: EditorState;
     private fontSizeToNum: Map<MarkType, number>;
     private fontStylesToName: Map<MarkType, string>;
+    private listTypeToIcon: Map<NodeType, string>;
     private fontSizeIndicator: HTMLSpanElement = document.createElement("span");
     //dropdown doms
     private fontSizeDom: Node;
     private fontStyleDom: Node;
+    private listTypeBtnDom: Node;
 
     constructor(view: EditorView, editorProps: FieldViewProps) {
         this.view = view;
@@ -58,8 +62,9 @@ export class TooltipTextMenu {
             { command: toggleMark(schema.marks.strikethrough), dom: this.icon("S", "strikethrough") },
             { command: toggleMark(schema.marks.superscript), dom: this.icon("s", "superscript") },
             { command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") },
-            { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
-            { command: lift, dom: this.icon("<", "lift") },
+            // { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
+            // { command: wrapInList(schema.nodes.ordered_list), dom: this.icon("1)", "bullets") },
+            // { command: lift, dom: this.icon("<", "lift") },
         ];
         //add menu items
         items.forEach(({ dom, command }) => {
@@ -96,7 +101,11 @@ export class TooltipTextMenu {
         this.fontSizeToNum.set(schema.marks.p72, 72);
         this.fontSizes = Array.from(this.fontSizeToNum.keys());
 
-        //this.addFontDropdowns();
+        //list types
+        this.listTypeToIcon = new Map();
+        this.listTypeToIcon.set(schema.nodes.bullet_list, ":");
+        this.listTypeToIcon.set(schema.nodes.ordered_list, "1)");
+        this.listTypes = Array.from(this.listTypeToIcon.keys());
 
         this.update(view, undefined);
     }
@@ -109,7 +118,7 @@ export class TooltipTextMenu {
         //font SIZES
         let fontSizeBtns: MenuItem[] = [];
         this.fontSizeToNum.forEach((number, mark) => {
-            fontSizeBtns.push(this.dropdownBtn(String(number), "width: 50px;", mark, this.view, this.changeToMarkInGroup, this.fontSizes));
+            fontSizeBtns.push(this.dropdownMarkBtn(String(number), "width: 50px;", mark, this.view, this.changeToMarkInGroup, this.fontSizes));
         });
 
         if (this.fontSizeDom) { this.tooltip.removeChild(this.fontSizeDom); }
@@ -128,7 +137,7 @@ export class TooltipTextMenu {
         //font STYLES
         let fontBtns: MenuItem[] = [];
         this.fontStylesToName.forEach((name, mark) => {
-            fontBtns.push(this.dropdownBtn(name, "font-family: " + name + ", sans-serif; width: 125px;", mark, this.view, this.changeToMarkInGroup, this.fontStyles));
+            fontBtns.push(this.dropdownMarkBtn(name, "font-family: " + name + ", sans-serif; width: 125px;", mark, this.view, this.changeToMarkInGroup, this.fontStyles));
         });
 
         if (this.fontStyleDom) { this.tooltip.removeChild(this.fontStyleDom); }
@@ -140,6 +149,29 @@ export class TooltipTextMenu {
         this.tooltip.appendChild(this.fontStyleDom);
     }
 
+    //will display a remove-list-type button if selection is in list, otherwise will show list type dropdown
+    updateListItemDropdown(label: string, listTypeBtn: Node) {
+        //remove old btn
+        if (listTypeBtn) { this.tooltip.removeChild(listTypeBtn); }
+
+        //Make a dropdown of all list types
+        let toAdd: MenuItem[] = [];
+        this.listTypeToIcon.forEach((icon, type) => {
+            toAdd.push(this.dropdownNodeBtn(icon, "width: 40px;", type, this.view, this.listTypes, this.changeToNodeType));
+        });
+        //option to remove the list formatting
+        toAdd.push(this.dropdownNodeBtn("X", "width: 40px;", undefined, this.view, this.listTypes, this.changeToNodeType));
+
+        listTypeBtn = (new Dropdown(toAdd, {
+            label: label,
+            css: "color:white; width: 40px;"
+        }) as MenuItem).render(this.view).dom;
+
+        //add this new button and return it
+        this.tooltip.appendChild(listTypeBtn);
+        return listTypeBtn;
+    }
+
     //for a specific grouping of marks (passed in), remove all and apply the passed-in one to the selected text
     changeToMarkInGroup(markType: MarkType, view: EditorView, fontMarks: MarkType[]) {
         let { empty, $cursor, ranges } = view.state.selection as TextSelection;
@@ -171,9 +203,18 @@ export class TooltipTextMenu {
         return toggleMark(markType)(view.state, view.dispatch, view);
     }
 
-    //makes a button for the drop down
+    //remove all node typeand apply the passed-in one to the selected text
+    changeToNodeType(nodeType: NodeType | undefined, view: EditorView, allNodes: NodeType[]) {
+        //remove old
+        liftListItem(schema.nodes.list_item)(view.state, view.dispatch);
+        if (nodeType) { //add new
+            wrapInList(nodeType)(view.state, view.dispatch);
+        }
+    }
+
+    //makes a button for the drop down FOR MARKS
     //css is the style you want applied to the button
-    dropdownBtn(label: string, css: string, markType: MarkType, view: EditorView, changeToMarkInGroup: (markType: MarkType<any>, view: EditorView, groupMarks: MarkType[]) => any, groupMarks: MarkType[]) {
+    dropdownMarkBtn(label: string, css: string, markType: MarkType, view: EditorView, changeToMarkInGroup: (markType: MarkType<any>, view: EditorView, groupMarks: MarkType[]) => any, groupMarks: MarkType[]) {
         return new MenuItem({
             title: "",
             label: label,
@@ -186,6 +227,23 @@ export class TooltipTextMenu {
             }
         });
     }
+
+    //makes a button for the drop down FOR NODE TYPES
+    //css is the style you want applied to the button
+    dropdownNodeBtn(label: string, css: string, nodeType: NodeType | undefined, view: EditorView, groupNodes: NodeType[], changeToNodeInGroup: (nodeType: NodeType<any> | undefined, view: EditorView, groupNodes: NodeType[]) => any) {
+        return new MenuItem({
+            title: "",
+            label: label,
+            execEvent: "",
+            class: "menuicon",
+            css: css,
+            enable(state) { return true; },
+            run() {
+                changeToNodeInGroup(nodeType, view, groupNodes);
+            }
+        });
+    }
+
     // Helper function to create menu icons
     icon(text: string, name: string) {
         let span = document.createElement("span");
@@ -262,6 +320,9 @@ export class TooltipTextMenu {
         this.tooltip.style.width = 225 + "px";
         this.tooltip.style.bottom = (box.bottom - start.top) * this.editorProps.ScreenToLocalTransform().Scale + "px";
 
+        //UPDATE LIST ITEM DROPDOWN
+        this.listTypeBtnDom = this.updateListItemDropdown(":", this.listTypeBtnDom);
+
         //UPDATE FONT STYLE DROPDOWN
         let activeStyles = this.activeMarksOnSelection(this.fontStyles);
         if (activeStyles.length === 1) {
@@ -288,7 +349,7 @@ export class TooltipTextMenu {
         }
     }
 
-    //finds all active marks on selection
+    //finds all active marks on selection in given group
     activeMarksOnSelection(markGroup: MarkType[]) {
         //current selection
         let { empty, $cursor, ranges } = this.view.state.selection as TextSelection;
-- 
cgit v1.2.3-70-g09d2


From 513e9042ea815e964462e824d85fbd229381250f Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 27 Apr 2019 01:19:52 -0400
Subject: A bunch more stuff

---
 src/client/DocServer.ts                            |   6 +-
 .../northstar/core/brusher/IBaseBrushable.ts       |   4 +-
 src/client/northstar/core/filter/FilterModel.ts    |  17 ++-
 .../northstar/core/filter/IBaseFilterConsumer.ts   |   4 +-
 src/client/northstar/dash-fields/HistogramField.ts |   3 +-
 src/client/util/TooltipTextMenu.tsx                |   4 +-
 src/client/views/InkingStroke.tsx                  |   2 +-
 src/client/views/Main.tsx                          | 152 ++++++++++-----------
 .../views/collections/CollectionDockingView.tsx    |   8 +-
 src/client/views/collections/CollectionPDFView.tsx |  10 +-
 .../views/collections/CollectionSchemaView.tsx     |   4 +-
 .../views/collections/CollectionVideoView.tsx      |   9 +-
 .../CollectionFreeFormLinkView.tsx                 |  20 +--
 .../CollectionFreeFormLinksView.tsx                |  63 +++++----
 .../CollectionFreeFormRemoteCursors.tsx            |   1 -
 src/client/views/nodes/IconBox.tsx                 |  12 +-
 16 files changed, 165 insertions(+), 154 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index 02fd28a86..3f17baec6 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -1,5 +1,5 @@
 import * as OpenSocket from 'socket.io-client';
-import { MessageStore, Types } from "./../server/Message";
+import { MessageStore, Types, Message } from "./../server/Message";
 import { Opt, FieldWaiting, RefField, HandleUpdate } from '../new_fields/Doc';
 import { Utils } from '../Utils';
 import { SerializationHelper } from './util/SerializationHelper';
@@ -13,6 +13,10 @@ export namespace DocServer {
         return window.location.origin + extension;
     }
 
+    export function DeleteDatabase() {
+        Utils.Emit(_socket, MessageStore.DeleteAll, {});
+    }
+
     export async function GetRefField(id: string): Promise<Opt<RefField>> {
         let cached = _cache[id];
         if (cached === undefined) {
diff --git a/src/client/northstar/core/brusher/IBaseBrushable.ts b/src/client/northstar/core/brusher/IBaseBrushable.ts
index c46db4d22..87f4ba413 100644
--- a/src/client/northstar/core/brusher/IBaseBrushable.ts
+++ b/src/client/northstar/core/brusher/IBaseBrushable.ts
@@ -1,9 +1,9 @@
 import { PIXIPoint } from '../../utils/MathUtil';
 import { IEquatable } from '../../utils/IEquatable';
-import { Document } from '../../../../fields/Document';
+import { Doc } from '../../../../new_fields/Doc';
 
 export interface IBaseBrushable<T> extends IEquatable {
-    BrusherModels: Array<Document>;
+    BrusherModels: Array<Doc>;
     BrushColors: Array<number>;
     Position: PIXIPoint;
     Size: PIXIPoint;
diff --git a/src/client/northstar/core/filter/FilterModel.ts b/src/client/northstar/core/filter/FilterModel.ts
index e2ba3f652..6ab96b33d 100644
--- a/src/client/northstar/core/filter/FilterModel.ts
+++ b/src/client/northstar/core/filter/FilterModel.ts
@@ -2,10 +2,9 @@ import { ValueComparison } from "./ValueComparision";
 import { Utils } from "../../utils/Utils";
 import { IBaseFilterProvider } from "./IBaseFilterProvider";
 import { FilterOperand } from "./FilterOperand";
-import { KeyStore } from "../../../../fields/KeyStore";
-import { FieldWaiting } from "../../../../fields/Field";
-import { Document } from "../../../../fields/Document";
 import { HistogramField } from "../../dash-fields/HistogramField";
+import { Cast, FieldValue } from "../../../../new_fields/Types";
+import { Doc } from "../../../../new_fields/Doc";
 
 export class FilterModel {
     public ValueComparisons: ValueComparison[];
@@ -52,12 +51,12 @@ export class FilterModel {
             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) {
-                    let filterHistogram = filterDoc.GetT(KeyStore.Data, HistogramField);
-                    if (filterHistogram && filterHistogram !== FieldWaiting) {
-                        if (!visitedFilterProviders.has(filterHistogram.Data)) {
-                            let child = FilterModel.GetFilterModelsRecursive(filterHistogram.Data, visitedFilterProviders, filterModels, false);
+                let filterDoc = FieldValue(Cast(linkVm.linkedFrom, Doc));
+                if (filterDoc) {
+                    let filterHistogram = Cast(filterDoc.data, HistogramField);
+                    if (filterHistogram) {
+                        if (!visitedFilterProviders.has(filterHistogram.HistoOp)) {
+                            let child = FilterModel.GetFilterModelsRecursive(filterHistogram.HistoOp, visitedFilterProviders, filterModels, false);
                             if (child !== "") {
                                 // if (linkVm.IsInverted) {
                                 //     child = "! " + child;
diff --git a/src/client/northstar/core/filter/IBaseFilterConsumer.ts b/src/client/northstar/core/filter/IBaseFilterConsumer.ts
index 59d7adf4c..e7549d113 100644
--- a/src/client/northstar/core/filter/IBaseFilterConsumer.ts
+++ b/src/client/northstar/core/filter/IBaseFilterConsumer.ts
@@ -1,10 +1,10 @@
 import { FilterOperand } from '../filter/FilterOperand';
 import { IEquatable } from '../../utils/IEquatable';
-import { Document } from "../../../../fields/Document";
+import { Doc } from '../../../../new_fields/Doc';
 
 export interface IBaseFilterConsumer extends IEquatable {
     FilterOperand: FilterOperand;
-    Links: Document[];
+    Links: Doc[];
 }
 
 export function instanceOfIBaseFilterConsumer(object: any): object is IBaseFilterConsumer {
diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts
index baeaca1dd..118f4cf7f 100644
--- a/src/client/northstar/dash-fields/HistogramField.ts
+++ b/src/client/northstar/dash-fields/HistogramField.ts
@@ -7,8 +7,9 @@ import { ObjectField } from "../../../new_fields/Doc";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { OmitKeys } from "../../../Utils";
 import { Deserializable } from "../../util/SerializationHelper";
+
 function serialize(field: HistogramField) {
-    return OmitKeys(field.HistoOp, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit
+    return OmitKeys(field.HistoOp, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit;
 }
 
 function deserialize(jp: any) {
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 4f0eb7d63..1b6647003 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -35,8 +35,8 @@ export class TooltipTextMenu {
     private fontStylesToName: Map<MarkType, string>;
     private fontSizeIndicator: HTMLSpanElement = document.createElement("span");
     //dropdown doms
-    private fontSizeDom: Node;
-    private fontStyleDom: Node;
+    private fontSizeDom?: Node;
+    private fontStyleDom?: Node;
 
     constructor(view: EditorView, editorProps: FieldViewProps) {
         this.view = view;
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 0f05da22c..616299146 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -1,8 +1,8 @@
 import { observer } from "mobx-react";
 import { observable } from "mobx";
 import { InkingControl } from "./InkingControl";
-import { InkTool } from "../../fields/InkField";
 import React = require("react");
+import { InkTool } from "../../new_fields/InkField";
 
 
 interface StrokeProps {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index c6b3f06d8..1e3d4e259 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -8,17 +8,12 @@ import * as React from 'react';
 import * as ReactDOM from 'react-dom';
 import Measure from 'react-measure';
 import * as request from 'request';
-import { Document } from '../../fields/Document';
-import { Field, FieldWaiting, Opt, FIELD_WAITING } from '../../fields/Field';
-import { KeyStore } from '../../fields/KeyStore';
-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 { RouteStore } from '../../server/RouteStore';
-import { ServerUtils } from '../../server/ServerUtil';
-import { emptyDocFunction, emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils';
-import { Documents } from '../documents/Documents';
+import { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils';
+import { Docs } from '../documents/Documents';
 import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
 import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
 import { Gateway, NorthstarSettings } from '../northstar/manager/Gateway';
@@ -26,7 +21,6 @@ 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 { Transform } from '../util/Transform';
 import { UndoManager } from '../util/UndoManager';
@@ -39,6 +33,10 @@ import { MainOverlayTextBox } from './MainOverlayTextBox';
 import { DocumentView } from './nodes/DocumentView';
 import { PreviewCursor } from './PreviewCursor';
 import { SelectionManager } from '../util/SelectionManager';
+import { FieldResult, Field, Doc, Id, Opt } from '../../new_fields/Doc';
+import { Cast, FieldValue, StrCast } from '../../new_fields/Types';
+import { DocServer } from '../DocServer';
+import { listSpec } from '../../new_fields/Schema';
 
 
 @observer
@@ -48,11 +46,13 @@ export class Main extends React.Component {
     @observable public pwidth: number = 0;
     @observable public pheight: number = 0;
 
-    @computed private get mainContainer(): Document | undefined | FIELD_WAITING {
-        return CurrentUserUtils.UserDocument.GetT(KeyStore.ActiveWorkspace, Document);
+    @computed private get mainContainer(): Opt<Doc> {
+        return FieldValue(Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc));
     }
-    private set mainContainer(doc: Document | undefined | FIELD_WAITING) {
-        doc && CurrentUserUtils.UserDocument.Set(KeyStore.ActiveWorkspace, doc);
+    private set mainContainer(doc: Opt<Doc>) {
+        if (doc) {
+            CurrentUserUtils.UserDocument.activeWorkspace = doc;
+        }
     }
 
     constructor(props: Readonly<{}>) {
@@ -100,8 +100,8 @@ export class Main extends React.Component {
         if (window.location.pathname !== RouteStore.home) {
             let pathname = window.location.pathname.split("/");
             CurrentUserUtils.MainDocId = pathname[pathname.length - 1];
-            Server.GetField(CurrentUserUtils.MainDocId, action((field: Opt<Field>) => {
-                if (field instanceof Document) {
+            DocServer.GetRefField(CurrentUserUtils.MainDocId).then(action((field: Opt<Field>) => {
+                if (field instanceof Doc) {
                     this.openWorkspace(field, true);
                 }
             }));
@@ -113,9 +113,9 @@ export class Main extends React.Component {
         window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler
         window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler
         window.addEventListener("keydown", (e) => {
-            if (e.key == "Escape") {
+            if (e.key === "Escape") {
                 DragManager.AbortDrag();
-                SelectionManager.DeselectAll()
+                SelectionManager.DeselectAll();
             }
         }, false); // drag event handler
         // click interactions for the context menu
@@ -126,54 +126,55 @@ export class Main extends React.Component {
         }), true);
     }
 
-    initAuthenticationRouters = () => {
+    initAuthenticationRouters = async () => {
         // Load the user's active workspace, or create a new one if initial session after signup
         if (!CurrentUserUtils.MainDocId) {
-            CurrentUserUtils.UserDocument.GetTAsync(KeyStore.ActiveWorkspace, Document).then(doc => {
-                if (doc) {
-                    CurrentUserUtils.MainDocId = doc.Id;
-                    this.openWorkspace(doc);
-                } else {
-                    this.createNewWorkspace();
-                }
-            });
+            const doc = await Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc);
+            if (doc) {
+                CurrentUserUtils.MainDocId = doc[Id];
+                this.openWorkspace(doc);
+            } else {
+                this.createNewWorkspace();
+            }
         } else {
-            Server.GetField(CurrentUserUtils.MainDocId).then(field =>
-                field instanceof Document ? this.openWorkspace(field) :
+            DocServer.GetRefField(CurrentUserUtils.MainDocId).then(field =>
+                field instanceof Doc ? this.openWorkspace(field) :
                     this.createNewWorkspace(CurrentUserUtils.MainDocId));
         }
     }
 
     @action
-    createNewWorkspace = (id?: string): void => {
-        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)] }] };
-                let mainDoc = Documents.DockDocument(JSON.stringify(dockingLayout), { title: `Main Container ${list.Data.length + 1}` }, id);
-                list.Data.push(mainDoc);
-                CurrentUserUtils.MainDocId = mainDoc.Id;
-                // 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" });
-                    mainDoc.Set(KeyStore.OptionalRightCollection, pendingDocument);
-                }, 0);
-            }
-        }));
+    createNewWorkspace = async (id?: string) => {
+        const list = Cast(CurrentUserUtils.UserDocument.workspaces, listSpec(Doc));
+        if (list) {
+            let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
+            var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc)] }] };
+            let mainDoc = Docs.DockDocument(JSON.stringify(dockingLayout), { title: `Main Container ${list.length + 1}` }, id);
+            list.push(mainDoc);
+            CurrentUserUtils.MainDocId = mainDoc[Id];
+            // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
+            setTimeout(() => {
+                this.openWorkspace(mainDoc);
+                let pendingDocument = Docs.SchemaDocument([], { title: "New Mobile Uploads" });
+                mainDoc.optionalRightCollection = pendingDocument;
+            }, 0);
+        }
     }
 
     @action
-    openWorkspace = (doc: Document, fromHistory = false): void => {
+    openWorkspace = async (doc: Doc, fromHistory = false) => {
         this.mainContainer = doc;
-        fromHistory || window.history.pushState(null, doc.Title, "/doc/" + doc.Id);
-        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(() =>
-                col && col.GetTAsync<ListField<Document>>(KeyStore.Data, ListField, (f: Opt<ListField<Document>>) =>
-                    f && f.Data.length > 0 && CollectionDockingView.Instance.AddRightSplit(col))
-                , 100)
-        );
+        fromHistory || window.history.pushState(null, StrCast(doc.title), "/doc/" + doc.Id);
+        const col = await Cast(CurrentUserUtils.UserDocument.optionalRightCollection, Doc);
+        // 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(async () => {
+            if (col) {
+                const l = Cast(col.data, listSpec(Doc));
+                if (l && l.length > 0) {
+                    CollectionDockingView.Instance.AddRightSplit(col);
+                }
+            }
+        }, 100);
     }
 
     @computed
@@ -196,7 +197,7 @@ export class Main extends React.Component {
                             PanelHeight={pheightFunc}
                             isTopMost={true}
                             selectOnLoad={false}
-                            focus={emptyDocFunction}
+                            focus={emptyFunction}
                             parentActive={returnTrue}
                             whenActiveChanged={emptyFunction}
                             ContainingCollectionView={undefined} />}
@@ -214,17 +215,17 @@ export class Main extends React.Component {
         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 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 }));
-        let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, title: "video node" }));
-        let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" }));
-        let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 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 addTextNode = action(() => Docs.TextDocument({ width: 200, height: 200, title: "a text note" }));
+        let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
+        let addSchemaNode = action(() => Docs.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" }));
+        let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", copyDraggedItems: true }));
+        let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" }));
+        let addPDFNode = action(() => Docs.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" }));
+        let addImageNode = action(() => Docs.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
+        let addWebNode = action(() => Docs.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
+        let addAudioNode = action(() => Docs.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" }));
 
-        let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Document][] = [
+        let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Doc][] = [
             [React.createRef<HTMLDivElement>(), "font", "Add Textbox", addTextNode],
             [React.createRef<HTMLDivElement>(), "image", "Add Image", addImageNode],
             [React.createRef<HTMLDivElement>(), "file-pdf", "Add PDF", addPDFNode],
@@ -260,9 +261,8 @@ export class Main extends React.Component {
         let logoutRef = React.createRef<HTMLDivElement>();
         let toggleWorkspaces = () => runInAction(() => this._workspacesShown = !this._workspacesShown);
 
-        let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}));
         return [
-            <button className="clear-db-button" key="clear-db" onClick={clearDatabase}>Clear Database</button>,
+            <button className="clear-db-button" key="clear-db" onClick={DocServer.DeleteDatabase}>Clear Database</button>,
             <div id="toolbar" key="toolbar">
                 <button className="toolbar-button round-button" title="Undo" onClick={() => UndoManager.Undo()}><FontAwesomeIcon icon="undo-alt" size="sm" /></button>
                 <button className="toolbar-button round-button" title="Redo" onClick={() => UndoManager.Redo()}><FontAwesomeIcon icon="redo-alt" size="sm" /></button>
@@ -271,7 +271,7 @@ export class Main extends React.Component {
             <div className="main-buttonDiv" key="workspaces" style={{ top: '34px', left: '2px', position: 'absolute' }} ref={workspacesRef}>
                 <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>
+                <button onClick={() => request.get(DocServer.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
         ];
     }
 
@@ -279,10 +279,10 @@ export class Main extends React.Component {
     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 || this.mainContainer === FieldWaiting) ? (null) :
+        let workspaces = Cast(CurrentUserUtils.UserDocument.workspaces, listSpec(Doc));
+        return (!workspaces || !this.mainContainer) ? (null) :
             <WorkspacesMenu active={this.mainContainer} open={this.openWorkspace}
-                new={this.createNewWorkspace} allWorkspaces={workspaces.Data}
+                new={this.createNewWorkspace} allWorkspaces={workspaces}
                 isShown={areWorkspacesShown} toggle={toggleWorkspaces} />;
     }
 
@@ -303,17 +303,17 @@ export class Main extends React.Component {
     }
 
     // --------------- Northstar hooks ------------- /
-    private _northstarSchemas: Document[] = [];
+    private _northstarSchemas: Doc[] = [];
 
     @action SetNorthstarCatalog(ctlog: Catalog) {
         CurrentUserUtils.NorthstarDBCatalog = ctlog;
         if (ctlog && ctlog.schemas) {
             ctlog.schemas.map(schema => {
-                let schemaDocuments: Document[] = [];
+                let schemaDocuments: Doc[] = [];
                 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) {
+                    promises.push(DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
+                        if (field instanceof Doc) {
                             schemaDocuments.push(field);
                         } else {
                             var atmod = new ColumnAttributeModel(attr);
@@ -321,12 +321,12 @@ export class Main extends React.Component {
                                 new AttributeTransformationModel(atmod, AggregateFunction.None),
                                 new AttributeTransformationModel(atmod, AggregateFunction.Count),
                                 new AttributeTransformationModel(atmod, AggregateFunction.Count));
-                            schemaDocuments.push(Documents.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }, undefined, attr.displayName! + ".alias"));
+                            schemaDocuments.push(Docs.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }));
                         }
                     })));
                     return promises;
                 }, [] as Promise<void>[])).finally(() =>
-                    this._northstarSchemas.push(Documents.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! })));
+                    this._northstarSchemas.push(Docs.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! })));
             });
         }
     }
@@ -338,7 +338,7 @@ export class Main extends React.Component {
 }
 
 (async () => {
-    await Documents.initProtos();
+    await Docs.initProtos();
     await CurrentUserUtils.loadCurrentUser();
     ReactDOM.render(<Main />, document.getElementById('root'));
 })();
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 69401ceeb..2ff409b9b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -6,13 +6,11 @@ import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
 import { Utils, returnTrue, emptyFunction, returnOne, returnZero } from "../../../Utils";
-import { Server } from "../../Server";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { DocumentView } from "../nodes/DocumentView";
 import "./CollectionDockingView.scss";
 import React = require("react");
 import { SubCollectionViewProps } from "./CollectionSubView";
-import { ServerUtils } from "../../../server/ServerUtil";
 import { DragManager, DragLinksAsDocuments } from "../../util/DragManager";
 import { Transform } from '../../util/Transform';
 import { Doc, Id, Opt, Field, FieldId } from "../../../new_fields/Doc";
@@ -206,7 +204,7 @@ 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>) =>
+            DocServer.GetRefField(docid).then(action(async (sourceDoc: Opt<Field>) =>
                 (sourceDoc instanceof Doc) && DragLinksAsDocuments(tab, x, y, sourceDoc)));
         } else
             if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) {
@@ -216,7 +214,7 @@ 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((f: Opt<Field>) => {
+                DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
                     if (f instanceof Doc) {
                         DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), x, y,
                             {
@@ -301,7 +299,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         stack.header.controlsContainer.find('.lm_popout') //get the close icon
             .off('click') //unbind the current click handler
             .click(action(function () {
-                var url = ServerUtils.prepend("/doc/" + stack.contentItems[0].tab.contentItem.config.props.documentId);
+                var url = DocServer.prepend("/doc/" + stack.contentItems[0].tab.contentItem.config.props.documentId);
                 let win = window.open(url, stack.contentItems[0].tab.title, "width=300,height=400");
             }));
     }
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 229bc4059..e73b7b4a6 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -1,6 +1,5 @@
 import { action } from "mobx";
 import { observer } from "mobx-react";
-import { KeyStore } from "../../../fields/KeyStore";
 import { ContextMenu } from "../ContextMenu";
 import "./CollectionPDFView.scss";
 import React = require("react");
@@ -8,6 +7,7 @@ import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormV
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView";
 import { emptyFunction } from "../../../Utils";
+import { NumCast } from "../../../new_fields/Types";
 
 
 @observer
@@ -17,10 +17,10 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
         return FieldView.LayoutString(CollectionPDFView, fieldKey);
     }
 
-    private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); }
-    private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); }
-    @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : -1;
-    @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : -1;
+    private get curPage() { return NumCast(this.props.Document.curPage, -1); }
+    private get numPages() { return NumCast(this.props.Document.numPages); }
+    @action onPageBack = () => this.curPage > 1 ? (this.props.Document.curPage = this.curPage - 1) : -1;
+    @action onPageForward = () => this.curPage < this.numPages ? (this.props.Document.curPage = this.curPage + 1) : -1;
 
     private get uIButtons() {
         let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 2e1175f28..874170f3d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -5,7 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, untracked } from "mobx";
 import { observer } from "mobx-react";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
-import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'
+import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss';
 import "react-table/react-table.css";
 import { emptyFunction, returnFalse, returnZero } from "../../../Utils";
 import { SetupDrag } from "../../util/DragManager";
@@ -283,7 +283,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         //  then by the time the options button is clicked, all of the fields should be in place.  If a new field is added while this menu
         //  is displayed (unlikely) it won't show up until something else changes.
         //TODO Types
-        untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
+        untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false))));
 
         this.columns.forEach(key => keys[key] = true);
         return Array.from(Object.keys(keys)).map(item =>
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 779dc8fc3..d314e3fc0 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -1,6 +1,5 @@
 import { action, observable, trace } from "mobx";
 import { observer } from "mobx-react";
-import { KeyStore } from "../../../fields/KeyStore";
 import { ContextMenu } from "../ContextMenu";
 import { CollectionViewType, CollectionBaseView, CollectionRenderProps } from "./CollectionBaseView";
 import React = require("react");
@@ -8,6 +7,7 @@ import "./CollectionVideoView.scss";
 import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { emptyFunction } from "../../../Utils";
+import { NumCast } from "../../../new_fields/Types";
 
 
 @observer
@@ -44,8 +44,9 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
         if (ele) {
             this._player = ele.getElementsByTagName("video")[0];
             console.log(this._player);
-            if (this.props.Document.GetNumber(KeyStore.CurPage, -1) >= 0) {
-                this._currentTimecode = this.props.Document.GetNumber(KeyStore.CurPage, -1);
+            const curPage = NumCast(this.props.Document.curPage, -1);
+            if (curPage >= 0) {
+                this._currentTimecode = curPage;
             }
         }
     }
@@ -69,7 +70,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 (this._player as any).AHackBecauseSomethingResetsTheVideoToZero = -1;
             } else {
                 this._currentTimecode = this._player.currentTime;
-                this.props.Document.SetNumber(KeyStore.CurPage, Math.round(this._currentTimecode));
+                this.props.Document.curPage = Math.round(this._currentTimecode);
             }
         }
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 20c5a84bf..d4987fc18 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -1,15 +1,15 @@
 import { observer } from "mobx-react";
-import { Document } from "../../../../fields/Document";
-import { KeyStore } from "../../../../fields/KeyStore";
 import { Utils } from "../../../../Utils";
 import "./CollectionFreeFormLinkView.scss";
 import React = require("react");
 import v5 = require("uuid/v5");
+import { StrCast, NumCast, BoolCast } from "../../../../new_fields/Types";
+import { Doc } from "../../../../new_fields/Doc";
 
 export interface CollectionFreeFormLinkViewProps {
-    A: Document;
-    B: Document;
-    LinkDocs: Document[];
+    A: Doc;
+    B: Doc;
+    LinkDocs: Doc[];
 }
 
 @observer
@@ -17,16 +17,16 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
 
     onPointerDown = (e: React.PointerEvent) => {
         this.props.LinkDocs.map(l =>
-            console.log("Link:" + l.Title));
+            console.log("Link:" + StrCast(l.title)));
     }
     render() {
         let l = this.props.LinkDocs;
         let a = this.props.A;
         let b = this.props.B;
-        let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Width() / 2);
-        let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Height() / 2);
-        let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Width() / 2);
-        let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Height() / 2);
+        let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / 2);
+        let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / 2);
+        let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / 2);
+        let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / 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.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index ebdb0c75c..ce9995630 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,8 +1,5 @@
 import { computed, IReactionDisposer, reaction } from "mobx";
 import { observer } from "mobx-react";
-import { Document } from "../../../../fields/Document";
-import { KeyStore } from "../../../../fields/KeyStore";
-import { ListField } from "../../../../fields/ListField";
 import { Utils } from "../../../../Utils";
 import { DocumentManager } from "../../../util/DocumentManager";
 import { DocumentView } from "../../nodes/DocumentView";
@@ -10,54 +7,66 @@ import { CollectionViewProps } from "../CollectionSubView";
 import "./CollectionFreeFormLinksView.scss";
 import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView";
 import React = require("react");
+import { Doc, Id } from "../../../../new_fields/Doc";
+import { Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types";
+import { listSpec } from "../../../../new_fields/Schema";
+import { List } from "../../../../new_fields/List";
 
 @observer
 export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> {
 
     _brushReactionDisposer?: IReactionDisposer;
     componentDidMount() {
-        this._brushReactionDisposer = reaction(() => this.props.Document.GetList(this.props.fieldKey, [] as Document[]).map(doc => doc.GetNumber(KeyStore.X, 0)),
+        this._brushReactionDisposer = reaction(() => Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).map(doc => NumCast(doc.x)),
             () => {
-                let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc.GetText(KeyStore.BackgroundLayout, "").indexOf("istogram") !== -1);
+                let views = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(doc => StrCast(doc.backgroundLayout, "").indexOf("istogram") !== -1);
                 for (let i = 0; i < views.length; i++) {
                     for (let j = 0; j < views.length; j++) {
                         let srcDoc = views[j];
                         let dstDoc = views[i];
-                        let x1 = srcDoc.GetNumber(KeyStore.X, 0);
-                        let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
-                        let x2 = dstDoc.GetNumber(KeyStore.X, 0);
-                        let x2w = dstDoc.GetNumber(KeyStore.Width, -1);
+                        let x1 = NumCast(srcDoc.x);
+                        let x1w = NumCast(srcDoc.width, -1);
+                        let x2 = NumCast(dstDoc.x);
+                        let x2w = NumCast(dstDoc.width, -1);
                         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[]) : [];
+                        let findBrush = (field: List<Doc>) => field.findIndex(brush => {
+                            let bdocs = brush ? Cast(brush.brushingDocs, listSpec(Doc), []) : [];
                             return (bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false);
                         });
-                        let brushAction = (field: ListField<Document>) => {
+                        let brushAction = (field: List<Doc>) => {
                             let found = findBrush(field);
                             if (found !== -1) {
                                 console.log("REMOVE BRUSH " + srcTarg.Title + " " + dstTarg.Title);
-                                field.Data.splice(found, 1);
+                                field.splice(found, 1);
                             }
                         };
                         if (Math.abs(x1 + x1w - x2) < 20) {
-                            let linkDoc: Document = new Document();
-                            linkDoc.SetText(KeyStore.Title, "Histogram Brush");
-                            linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
-                            linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
+                            let linkDoc: Doc = new Doc();
+                            linkDoc.title = "Histogram Brush";
+                            linkDoc.linkDescription = "Brush between " + StrCast(srcTarg.title) + " and " + StrCast(dstTarg.Title);
+                            linkDoc.brushingDocs = new List([dstTarg, srcTarg]);
 
-                            brushAction = (field: ListField<Document>) => {
+                            brushAction = (field: List<Doc>) => {
                                 if (findBrush(field) === -1) {
                                     console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
-                                    (findBrush(field) === -1) && field.Data.push(linkDoc);
+                                    (findBrush(field) === -1) && field.push(linkDoc);
                                 }
                             };
                         }
-                        dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
-                        srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction);
+                        let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc));
+                        if (dstBrushDocs === undefined) {
+                            dstTarg.brushingDocs = dstBrushDocs = new List();
+                        }
+                        let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc));
+                        if (srcBrushDocs === undefined) {
+                            srcTarg.brushingDocs = srcBrushDocs = new List();
+                        }
+                        brushAction(dstBrushDocs);
+                        brushAction(srcBrushDocs);
 
                     }
                 }
@@ -70,9 +79,9 @@ 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()!);
+        let containerDoc = FieldValue(Cast(view.props.Document.annotationOn, Doc));
+        if (containerDoc) {
+            equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.proto!);
         }
         return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document);
     }
@@ -82,12 +91,12 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
         let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => {
             let srcViews = this.documentAnchors(connection.a);
             let targetViews = this.documentAnchors(connection.b);
-            let possiblePairs: { a: Document, b: Document, }[] = [];
+            let possiblePairs: { a: Doc, b: Doc, }[] = [];
             srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document })));
             possiblePairs.map(possiblePair =>
                 drawnPairs.reduce((found, drawnPair) => {
                     let match = (possiblePair.a === drawnPair.a && possiblePair.b === drawnPair.b);
-                    if (match && !drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false)) {
+                    if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) {
                         drawnPair.l.push(connection.l);
                     }
                     return match || found;
@@ -96,7 +105,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                 drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] })
             );
             return drawnPairs;
-        }, [] as { a: Document, b: Document, l: Document[] }[]);
+        }, [] as { a: Doc, b: Doc, l: Doc[] }[]);
         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 cf0a6de00..036745eca 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -1,6 +1,5 @@
 import { computed } from "mobx";
 import { observer } from "mobx-react";
-import { KeyStore } from "../../../../fields/KeyStore";
 import { CollectionViewProps, CursorEntry } from "../CollectionSubView";
 import "./CollectionFreeFormView.scss";
 import React = require("react");
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
index 9c90c0a0e..f7cceb3d4 100644
--- a/src/client/views/nodes/IconBox.tsx
+++ b/src/client/views/nodes/IconBox.tsx
@@ -4,12 +4,12 @@ import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } fr
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed } from "mobx";
 import { observer } from "mobx-react";
-import { Document } from '../../../fields/Document';
-import { IconField } from "../../../fields/IconFIeld";
-import { KeyStore } from "../../../fields/KeyStore";
 import { SelectionManager } from "../../util/SelectionManager";
 import { FieldView, FieldViewProps } from './FieldView';
 import "./IconBox.scss";
+import { Cast } from "../../../new_fields/Types";
+import { Doc } from "../../../new_fields/Doc";
+import { IconField } from "../../../new_fields/IconField";
 
 
 library.add(faCaretUp);
@@ -22,8 +22,8 @@ library.add(faFilm);
 export class IconBox extends React.Component<FieldViewProps> {
     public static LayoutString() { return FieldView.LayoutString(IconBox); }
 
-    @computed get maximized() { return this.props.Document.GetT(KeyStore.MaximizedDoc, Document); }
-    @computed get layout(): string { return this.props.Document.GetData(this.props.fieldKey, IconField, "<p>Error loading layout data</p>" as string); }
+    @computed get maximized() { return Cast(this.props.Document.maximizedDoc, Doc); }
+    @computed get layout(): string { const field = Cast(this.props.Document[this.props.fieldKey], IconField); return field ? field.layout : "<p>Error loading layout data</p>"; }
     @computed get minimizedIcon() { return IconBox.DocumentIcon(this.layout); }
 
     public static DocumentIcon(layout: string) {
@@ -33,7 +33,7 @@ export class IconBox extends React.Component<FieldViewProps> {
                     layout.indexOf("Video") !== -1 ? faFilm :
                         layout.indexOf("Collection") !== -1 ? faObjectGroup :
                             faCaretUp;
-        return <FontAwesomeIcon icon={button} className="documentView-minimizedIcon" />
+        return <FontAwesomeIcon icon={button} className="documentView-minimizedIcon" />;
     }
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From a5ab5caa244da261814bc10f0ae88b302da93951 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 28 Apr 2019 22:00:32 -0400
Subject: fixed webbox interactions.  got rid of pdf annotation.  fixed
 formatted text menu appearing

---
 src/client/util/TooltipTextMenu.tsx         |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx | 20 ++++++++++++--------
 src/client/views/nodes/PDFBox.tsx           |  4 ++--
 src/client/views/nodes/WebBox.scss          | 17 +++++++++++++++--
 src/client/views/nodes/WebBox.tsx           |  6 ++++--
 5 files changed, 34 insertions(+), 15 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 4f0eb7d63..38267f4f9 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -24,7 +24,7 @@ const SVG = "http://www.w3.org/2000/svg";
 //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
 
-    private tooltip: HTMLElement;
+    public tooltip: HTMLElement;
     private num_icons = 0;
     private view: EditorView;
     private fontStyles: MarkType[];
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d8cd28b6c..fc8d757f6 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,4 +1,4 @@
-import { action, IReactionDisposer, reaction, trace, computed } from "mobx";
+import { action, IReactionDisposer, reaction, trace, computed, _allowStateChangesInsideComputed } from "mobx";
 import { baseKeymap } from "prosemirror-commands";
 import { history } from "prosemirror-history";
 import { keymap } from "prosemirror-keymap";
@@ -22,8 +22,6 @@ import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
-const { buildMenuItems } = require("prosemirror-example-setup");
-const { menuBar } = require("prosemirror-menu");
 
 // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
 //
@@ -67,9 +65,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
 
     _applyingChange: boolean = false;
 
+    _lastState: any = undefined;
     dispatchTransaction = (tx: Transaction) => {
         if (this._editorView) {
-            const state = this._editorView.state.apply(tx);
+            const state = this._lastState = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             this._applyingChange = true;
             this.props.Document.SetDataOnPrototype(
@@ -88,10 +87,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
             schema,
             inpRules, //these currently don't do anything, but could eventually be helpful
             plugins: this.props.isOverlay ? [
+                this.tooltipTextMenuPlugin(),
                 history(),
                 keymap(buildKeymap(schema)),
                 keymap(baseKeymap),
-                this.tooltipTextMenuPlugin(),
                 // this.tooltipLinkingMenuPlugin(),
                 new Plugin({
                     props: {
@@ -169,8 +168,10 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
     }
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
+        if (e.button === 0 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             e.stopPropagation();
+            if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip)
+                this._toolTipTextMenu.tooltip.style.opacity = "0";
         }
         if (e.button === 2 || (e.button === 0 && e.ctrlKey)) {
             this._gotDown = true;
@@ -178,7 +179,8 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         }
     }
     onPointerUp = (e: React.PointerEvent): void => {
-        console.log("pointer up");
+        if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip)
+            this._toolTipTextMenu.tooltip.style.opacity = "1";
         if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
             e.stopPropagation();
         }
@@ -235,13 +237,15 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
 
     tooltipTextMenuPlugin() {
         let myprops = this.props;
+        let self = this;
         return new Plugin({
             view(_editorView) {
-                return new TooltipTextMenu(_editorView, myprops);
+                return self._toolTipTextMenu = new TooltipTextMenu(_editorView, myprops);
             }
         });
     }
 
+    _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
     tooltipLinkingMenuPlugin() {
         let myprops = this.props;
         return new Plugin({
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3d13c6f23..226dfba11 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -115,7 +115,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
                                 child.id = "highlighted";
                                 //@ts-ignore
                                 obj.spans.push(child);
-                                child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
+                                // child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
                             }
                         });
                     }
@@ -138,7 +138,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
                     child.id = "highlighted";
                     //@ts-ignore
                     temp.spans.push(child);
-                    child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
+                    // child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
                 }
             });
 
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index 2ad1129a4..eb09b0693 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -1,12 +1,19 @@
 
-.webBox-cont {
+.webBox-cont, .webBox-cont-interactive{
     padding: 0vw;
     position: absolute;
     top: 0;
     left:0;
     width: 100%;
     height: 100%;
-    overflow: scroll;
+    overflow: auto;
+    pointer-events: none ;
+}
+.webBox-cont-interactive {
+    pointer-events: all;
+    span {
+        user-select: text !important;
+    }
 }
 
 #webBox-htmlSpan {
@@ -15,6 +22,12 @@
     left:0;
 }
 
+.webBox-overlay {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+}
+
 .webBox-button {
     padding : 0vw;
     border: none;
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index f7f5e31e6..a7c6fda8b 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -7,6 +7,7 @@ import { observer } from "mobx-react";
 import { computed, reaction, IReactionDisposer } from 'mobx';
 import { KeyStore } from '../../../fields/KeyStore';
 import { DocumentDecorations } from "../DocumentDecorations";
+import { InkingControl } from "../InkingControl";
 
 @observer
 export class WebBox extends React.Component<FieldViewProps> {
@@ -45,12 +46,13 @@ export class WebBox extends React.Component<FieldViewProps> {
 
         let frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
 
+        let classname = "webBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !DocumentDecorations.Instance.Interacting ? "-interactive" : "");
         return (
             <>
-                <div className="webBox-cont"  >
+                <div className={classname}  >
                     {content}
                 </div>
-                {!frozen ? (null) : <div onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer} style={{ width: "100%", height: "100%", position: "absolute" }} />}
+                {!frozen ? (null) : <div className="webBox-overlay" onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer} />}
             </>);
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2

