From 27b514747188f12e0b0eeeb124576c556316923d Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Mon, 22 Apr 2019 22:57:18 -0400
Subject: Changes

---
 src/client/views/nodes/FormattedTextBox.tsx | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

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

diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 639dae30a..cb082dc69 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -4,11 +4,6 @@ import { history } from "prosemirror-history";
 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 { TextField } from "../../../fields/TextField";
-import { Document } from "../../../fields/Document";
 import buildKeymap from "../../util/ProsemirrorKeymap";
 import { inpRules } from "../../util/RichTextRules";
 import { schema } from "../../util/RichTextSchema";
@@ -20,6 +15,9 @@ import { FieldView, FieldViewProps } from "./FieldView";
 import "./FormattedTextBox.scss";
 import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
+import { DocComponent } from "../DocComponent";
+import { createSchema, makeInterface } from "../../../new_fields/Schema";
+import { Opt, Doc } from "../../../new_fields/Doc";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -44,7 +42,14 @@ export interface FormattedTextBoxOverlay {
     isOverlay?: boolean;
 }
 
-export class FormattedTextBox extends React.Component<(FieldViewProps & FormattedTextBoxOverlay)> {
+const richTextSchema = createSchema({
+    documentText: "string"
+});
+
+type RichTextDocument = makeInterface<[typeof richTextSchema]>;
+const RichTextDocument = makeInterface(richTextSchema);
+
+export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTextBoxOverlay), RichTextDocument>(RichTextDocument) {
     public static LayoutString(fieldStr: string = "DataKey") {
         return FieldView.LayoutString(FormattedTextBox, fieldStr);
     }
@@ -59,7 +64,6 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         super(props);
 
         this._ref = React.createRef();
-        this.onChange = this.onChange.bind(this);
     }
 
     _applyingChange: boolean = false;
@@ -74,7 +78,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
                 JSON.stringify(state.toJSON()),
                 RichTextField
             );
-            this.props.Document.SetDataOnPrototype(KeyStore.DocumentText, state.doc.textBetween(0, state.doc.content.size, "\n\n"), TextField);
+            Doc.SetOnPrototype(this.props.Document, "documentText", state.doc.textBetween(0, state.doc.content.size, "\n\n"));
             this._applyingChange = false;
             // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
         }
@@ -166,12 +170,6 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
         }
     }
 
-    @action
-    onChange(e: React.ChangeEvent<HTMLInputElement>) {
-        const { fieldKey, Document } = this.props;
-        Document.SetOnPrototype(fieldKey, new RichTextField(e.target.value));
-        // doc.SetData(fieldKey, e.target.value, RichTextField);
-    }
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             console.log("first");
@@ -252,7 +250,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
     }
 
     onKeyPress(e: React.KeyboardEvent) {
-        if (e.key == "Escape") {
+        if (e.key === "Escape") {
             SelectionManager.DeselectAll();
         }
         e.stopPropagation();
-- 
cgit v1.2.3-70-g09d2


From 7a820b3b175ea52712927e75ce16e32f0ed3a131 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 27 Apr 2019 19:51:58 -0400
Subject: Compiling

---
 src/client/util/DragManager.ts                     |  8 +++----
 src/client/views/MainOverlayTextBox.tsx            | 17 +++++++-------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx        | 17 ++++++--------
 src/fields/RichTextField.ts                        | 26 ----------------------
 src/new_fields/RichTextField.ts                    | 12 ++++++++++
 src/new_fields/Types.ts                            | 14 ++++++------
 7 files changed, 39 insertions(+), 57 deletions(-)
 delete mode 100644 src/fields/RichTextField.ts
 create mode 100644 src/new_fields/RichTextField.ts

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 0174b2f54..e65f2b9ed 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -158,13 +158,13 @@ export namespace DragManager {
     }
 
     export class LinkDragData {
-        constructor(linkSourceDoc: Document, blacklist: Document[] = []) {
+        constructor(linkSourceDoc: Doc, blacklist: Doc[] = []) {
             this.linkSourceDocument = linkSourceDoc;
             this.blacklist = blacklist;
         }
-        droppedDocuments: Document[] = [];
-        linkSourceDocument: Document;
-        blacklist: Document[];
+        droppedDocuments: Doc[] = [];
+        linkSourceDocument: Doc;
+        blacklist: Doc[];
         [id: string]: any;
     }
 
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index be8d67925..a7ced36bf 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -2,16 +2,15 @@ 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, returnZero } from '../../Utils';
+import { emptyFunction, returnTrue, returnZero } 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';
+import { Doc } from '../../new_fields/Doc';
+import { NumCast } from '../../new_fields/Types';
 
 interface MainOverlayTextBoxProps {
 }
@@ -19,11 +18,11 @@ interface MainOverlayTextBoxProps {
 @observer
 export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps> {
     public static Instance: MainOverlayTextBox;
-    @observable public TextDoc?: Document = undefined;
+    @observable public TextDoc?: Doc = undefined;
     public TextScroll: number = 0;
     @observable _textRect: any;
     @observable _textXf: () => Transform = () => Transform.Identity();
-    private _textFieldKey: Key = KeyStore.Data;
+    private _textFieldKey: string = "data";
     private _textColor: string | null = null;
     private _textTargetDiv: HTMLDivElement | undefined;
     private _textProxyDiv: React.RefObject<HTMLDivElement>;
@@ -35,7 +34,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
     }
 
     @action
-    SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: () => Transform) {
+    SetTextDoc(textDoc?: Doc, textFieldKey?: string, div?: HTMLDivElement, tx?: () => Transform) {
         if (this._textTargetDiv) {
             this._textTargetDiv.style.color = this._textColor;
         }
@@ -94,10 +93,10 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
             let s = 1 / this._textXf().Scale;
             return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${pt[0]}px, ${pt[1]}px) scale(${s},${s})`, width: "auto", height: "auto" }} >
                 <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll}
-                    style={{ width: `${this.TextDoc.Width()}px`, height: `${this.TextDoc.Height()}px` }}>
+                    style={{ width: `${NumCast(this.TextDoc.width)}px`, height: `${NumCast(this.TextDoc.height)}px` }}>
                     <FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
                         selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
-                        ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyDocFunction} />
+                        ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} />
                 </div>
             </ div>;
         }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 80900c450..047fbad18 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -97,7 +97,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     if (!NumCast(d.height)) {
                         let nw = NumCast(d.nativeWidth);
                         let nh = NumCast(d.nativeHeight);
-                        d.height = nw && nh ? nh / nw * d.Width() : 300;
+                        d.height = nw && nh ? nh / nw * NumCast(d.Width) : 300;
                     }
                     this.bringToFront(d);
                 });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index c65b1ac89..7a85c9dd3 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -20,7 +20,8 @@ import { createSchema, makeInterface } from "../../../new_fields/Schema";
 import { Opt, Doc } from "../../../new_fields/Doc";
 import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
-import { StrCast } from "../../../new_fields/Types";
+import { StrCast, Cast } from "../../../new_fields/Types";
+import { RichTextField } from "../../../new_fields/RichTextField";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -77,11 +78,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             this._applyingChange = true;
-            this.props.Document.SetDataOnPrototype(
-                this.props.fieldKey,
-                JSON.stringify(state.toJSON()),
-                RichTextField
-            );
+            Doc.SetOnPrototype(this.props.Document, this.props.fieldKey, new RichTextField(JSON.stringify(state.toJSON())));
             Doc.SetOnPrototype(this.props.Document, "documentText", state.doc.textBetween(0, state.doc.content.size, "\n\n"));
             this._applyingChange = false;
             // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
@@ -127,8 +124,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
 
         this._reactionDisposer = reaction(
             () => {
-                const field = this.props.Document ? this.props.Document.GetT(this.props.fieldKey, RichTextField) : undefined;
-                return field && field !== FieldWaiting ? field.Data : undefined;
+                const field = this.props.Document ? Cast(this.props.Document[this.props.fieldKey], RichTextField) : undefined;
+                return field ? field.Data : undefined;
             },
             field => field && this._editorView && !this._applyingChange &&
                 this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field)))
@@ -136,8 +133,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         this.setupEditor(config, this.props.Document);
     }
 
-    private setupEditor(config: any, doc?: Document) {
-        let field = doc ? doc.GetT(this.props.fieldKey, RichTextField) : undefined;
+    private setupEditor(config: any, doc?: Doc) {
+        let field = doc ? Cast(doc[this.props.fieldKey], RichTextField) : undefined;
         if (this._ref.current) {
             this._editorView = new EditorView(this._ref.current, {
                 state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config),
diff --git a/src/fields/RichTextField.ts b/src/fields/RichTextField.ts
deleted file mode 100644
index f53f48ca6..000000000
--- a/src/fields/RichTextField.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { BasicField } from "./BasicField";
-import { Types } from "../server/Message";
-import { FieldId } from "./Field";
-
-export class RichTextField extends BasicField<string> {
-    constructor(data: string = "", id?: FieldId, save: boolean = true) {
-        super(data, save, id);
-    }
-
-    ToScriptString(): string {
-        return `new RichTextField(${this.Data})`;
-    }
-
-    Copy() {
-        return new RichTextField(this.Data);
-    }
-
-    ToJson() {
-        return {
-            type: Types.RichText,
-            data: this.Data,
-            id: this.Id
-        };
-    }
-
-}
\ No newline at end of file
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
new file mode 100644
index 000000000..156e4efd9
--- /dev/null
+++ b/src/new_fields/RichTextField.ts
@@ -0,0 +1,12 @@
+import { ObjectField } from "./Doc";
+import { serializable } from "serializr";
+
+export class RichTextField extends ObjectField {
+    @serializable(true)
+    readonly Data: string;
+
+    constructor(data: string) {
+        super();
+        this.Data = data;
+    }
+}
\ No newline at end of file
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 4808d6e46..7fa18673f 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -38,10 +38,10 @@ export interface Interface {
 }
 
 export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T): FieldResult<ToType<T>>;
-export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal: WithoutList<ToType<T>>): WithoutList<ToType<T>>;
-export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal?: ToType<T>): FieldResult<ToType<T>> | undefined {
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal: WithoutList<ToType<T>> | null): WithoutList<ToType<T>>;
+export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: FieldResult, ctor: T, defaultVal?: ToType<T> | null): FieldResult<ToType<T>> | undefined {
     if (field instanceof Promise) {
-        return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) as any : defaultVal;
+        return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) as any : defaultVal === null ? undefined : defaultVal;
     }
     if (field !== undefined && !(field instanceof Promise)) {
         if (typeof ctor === "string") {
@@ -56,18 +56,18 @@ export function Cast<T extends ToConstructor<Field> | ListSpec<Field>>(field: Fi
             return field as ToType<T>;
         }
     }
-    return defaultVal;
+    return defaultVal === null ? undefined : defaultVal;
 }
 
-export function NumCast(field: FieldResult, defaultVal: Opt<number> = 0) {
+export function NumCast(field: FieldResult, defaultVal: number | null = 0) {
     return Cast(field, "number", defaultVal);
 }
 
-export function StrCast(field: FieldResult, defaultVal: Opt<string> = "") {
+export function StrCast(field: FieldResult, defaultVal: string | null = "") {
     return Cast(field, "string", defaultVal);
 }
 
-export function BoolCast(field: FieldResult, defaultVal: Opt<boolean> = undefined) {
+export function BoolCast(field: FieldResult, defaultVal: boolean | null = null) {
     return Cast(field, "boolean", defaultVal);
 }
 
-- 
cgit v1.2.3-70-g09d2


From 506af03831bf3cc002f93ad8708eafb909c0a194 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 27 Apr 2019 22:27:26 -0400
Subject: Various fixes

---
 src/client/DocServer.ts                            | 24 ++++++++++++++++++----
 src/client/documents/Documents.ts                  |  2 +-
 src/client/northstar/dash-nodes/HistogramBox.tsx   |  2 +-
 src/client/views/collections/CollectionPDFView.tsx |  2 +-
 src/client/views/collections/CollectionSubView.tsx |  1 +
 .../views/collections/CollectionVideoView.tsx      |  2 +-
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/FieldView.tsx               |  4 ++--
 src/client/views/nodes/FormattedTextBox.tsx        |  2 +-
 src/client/views/nodes/KeyValueBox.tsx             |  2 +-
 src/new_fields/util.ts                             |  5 +++--
 src/server/database.ts                             | 21 +++++++++++++------
 src/server/index.ts                                | 10 +++++----
 14 files changed, 55 insertions(+), 26 deletions(-)

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

diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index c7cbfce37..07997f072 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -55,12 +55,28 @@ export namespace DocServer {
                 map[id] = cached;
             }
         }
-        const prom = Utils.EmitCallback(_socket, MessageStore.GetFields, requestedIds);
-        requestedIds.map((id, index) => _cache[id] = prom.then((fields: RefField[]) => fields[index]));
+        const prom = Utils.EmitCallback(_socket, MessageStore.GetRefFields, requestedIds).then(fields => {
+            for (const key in fields) {
+                const field = fields[key];
+                if (field) {
+                    fields[key] = SerializationHelper.Deserialize(field);
+                }
+            }
+            return fields;
+        });
+        requestedIds.forEach((id, index) => _cache[id] = prom.then((fields: RefField[]) => fields[index]));
         const fields = await prom;
-        requestedIds.map((id, index) => map[id] = fields[index]);
+        requestedIds.forEach((id, index) => {
+            const field = fields[index];
+            if (field) {
+                _cache[id] = field;
+            } else {
+                delete _cache[id];
+            }
+            map[id] = field;
+        });
         const otherFields = await Promise.all(promises);
-        waitingIds.map((id, index) => map[id] = otherFields[index]);
+        waitingIds.forEach((id, index) => map[id] = otherFields[index]);
         return map;
     }
 
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index c30fb21d5..2a9687bda 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -138,7 +138,7 @@ export namespace Docs {
         return webProto;
     }
     function CreateCollectionPrototype(): Doc {
-        let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"),
+        let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("data"),
             { panX: 0, panY: 0, scale: 1, width: 500, height: 500 });
         return collProto;
     }
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index a9c68ccba..19d108676 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -26,7 +26,7 @@ import { Id } from "../../../new_fields/RefField";
 
 @observer
 export class HistogramBox extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(HistogramBox, fieldStr); }
+    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(HistogramBox, fieldStr); }
     private _dropXRef = React.createRef<HTMLDivElement>();
     private _dropYRef = React.createRef<HTMLDivElement>();
     private _dropXDisposer?: DragManager.DragDropDisposer;
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index e73b7b4a6..99438b4e8 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -13,7 +13,7 @@ import { NumCast } from "../../../new_fields/Types";
 @observer
 export class CollectionPDFView extends React.Component<FieldViewProps> {
 
-    public static LayoutString(fieldKey: string = "DataKey") {
+    public static LayoutString(fieldKey: string = "data") {
         return FieldView.LayoutString(CollectionPDFView, fieldKey);
     }
 
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 4d090b680..2c2d74302 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -53,6 +53,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
 
         @action
         protected async setCursorPosition(position: [number, number]) {
+            return;
             let ind;
             let doc = this.props.Document;
             let id = CurrentUserUtils.id;
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index d314e3fc0..d45be228a 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -18,7 +18,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
     @observable _currentTimecode: number = 0;
     @observable _isPlaying: boolean = false;
 
-    public static LayoutString(fieldKey: string = "DataKey") {
+    public static LayoutString(fieldKey: string = "data") {
         return FieldView.LayoutString(CollectionVideoView, fieldKey);
     }
     private get uIButtons() {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e7bf1e121..b72065bca 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -13,7 +13,7 @@ import { trace } from 'mobx';
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(CollectionView, fieldStr); }
+    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(CollectionView, fieldStr); }
 
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 18107e98a..dfacca204 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -314,7 +314,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
-                        <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />
+                        {/* <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" /> */}
                     </CollectionFreeFormViewPannableContents>
                     <CollectionFreeFormOverlayView {...this.getDocumentViewProps(this.props.Document)} />
                 </MarqueeView>
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index dc36c5914..df76f7cea 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -45,8 +45,8 @@ export interface FieldViewProps {
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: { name: string }, fieldStr: string = "DataKey") {
-        return `<${fieldType.name} {...props} fieldKey={${fieldStr}} />`;
+    public static LayoutString(fieldType: { name: string }, fieldStr: string = "data") {
+        return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"} />`;
     }
 
     @computed
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 7a85c9dd3..96512718f 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -55,7 +55,7 @@ const RichTextDocument = makeInterface(richTextSchema);
 
 @observer
 export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTextBoxOverlay), RichTextDocument>(RichTextDocument) {
-    public static LayoutString(fieldStr: string = "DataKey") {
+    public static LayoutString(fieldStr: string = "data") {
         return FieldView.LayoutString(FormattedTextBox, fieldStr);
     }
     private _ref: React.RefObject<HTMLDivElement>;
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index ae39ebe2d..876a3c173 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -14,7 +14,7 @@ import { Doc, IsField } from "../../../new_fields/Doc";
 export class KeyValueBox extends React.Component<FieldViewProps> {
     private _mainCont = React.createRef<HTMLDivElement>();
 
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr); }
+    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(KeyValueBox, fieldStr); }
     @observable private _keyInput: string = "";
     @observable private _valueInput: string = "";
     @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); }
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 011e8c8d9..b2299f34a 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -5,8 +5,9 @@ import { ProxyField } from "./Proxy";
 import { FieldValue } from "./Types";
 import { RefField, Id } from "./RefField";
 import { ObjectField, Parent, OnUpdate } from "./ObjectField";
+import { action } from "mobx";
 
-export function setter(target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
+export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
     if (SerializationHelper.IsSerializing()) {
         target[prop] = value;
         return true;
@@ -46,7 +47,7 @@ export function setter(target: any, prop: string | symbol | number, value: any,
         undo: () => receiver[prop] = curValue
     });
     return true;
-}
+});
 
 export function getter(target: any, prop: string | symbol | number, receiver: any): any {
     if (typeof prop === "symbol") {
diff --git a/src/server/database.ts b/src/server/database.ts
index 6b3b6797f..4775c0eeb 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -60,19 +60,28 @@ export class Database {
     }
 
     public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = Database.DocumentsCollection) {
-        console.log("getDocument");
-        this.db && this.db.collection(collectionName).findOne({ id: id }, (err, result) =>
-            fn(result ? ({ id: result._id, type: result.type, data: result.data }) : undefined));
+        this.db && this.db.collection(collectionName).findOne({ _id: id }, (err, result) => {
+            if (result) {
+                result.id = result._id;
+                delete result._id;
+                fn(result);
+            } else {
+                fn(undefined);
+            }
+        });
     }
 
     public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = Database.DocumentsCollection) {
-        console.log("getDocuments");
-        this.db && this.db.collection(collectionName).find({ id: { "$in": ids } }).toArray((err, docs) => {
+        this.db && this.db.collection(collectionName).find({ _id: { "$in": ids } }).toArray((err, docs) => {
             if (err) {
                 console.log(err.message);
                 console.log(err.errmsg);
             }
-            fn(docs.map(doc => ({ id: doc._id, type: doc.type, data: doc.data })));
+            fn(docs.map(doc => {
+                doc.id = doc._id;
+                delete doc._id;
+                return doc;
+            }));
         });
     }
 
diff --git a/src/server/index.ts b/src/server/index.ts
index 10158eb96..6801b3132 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -234,16 +234,18 @@ server.on("connection", function (socket: Socket) {
 
     Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField);
     Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff));
-    Utils.AddServerHandler(socket, MessageStore.GetRefField, GetRefField);
-    Utils.AddServerHandler(socket, MessageStore.GetRefFields, GetRefFields);
+    Utils.AddServerHandlerCallback(socket, MessageStore.GetRefField, GetRefField);
+    Utils.AddServerHandlerCallback(socket, MessageStore.GetRefFields, GetRefFields);
 });
 
-function deleteFields() {
-    return Database.Instance.deleteAll();
+async function deleteFields() {
+    await Database.Instance.deleteAll();
+    await Database.Instance.deleteAll('newDocuments');
 }
 
 async function deleteAll() {
     await Database.Instance.deleteAll();
+    await Database.Instance.deleteAll('newDocuments');
     await Database.Instance.deleteAll('sessions');
     await Database.Instance.deleteAll('users');
 }
-- 
cgit v1.2.3-70-g09d2


From a2751d16babb38cde2b86b1cb8fc5d74c15762d7 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sun, 28 Apr 2019 00:23:18 -0400
Subject: Decent amount of stuff is working

---
 src/client/views/Main.tsx                                             | 2 +-
 src/client/views/collections/CollectionBaseView.tsx                   | 2 +-
 src/client/views/collections/CollectionPDFView.tsx                    | 3 ++-
 src/client/views/collections/CollectionVideoView.tsx                  | 3 ++-
 src/client/views/collections/CollectionView.tsx                       | 3 ++-
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx   | 2 +-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx             | 1 +
 src/client/views/nodes/DocumentView.tsx                               | 4 ++--
 src/client/views/nodes/FormattedTextBox.tsx                           | 3 ++-
 src/client/views/nodes/PDFBox.tsx                                     | 2 +-
 src/new_fields/RichTextField.ts                                       | 2 ++
 src/new_fields/Types.ts                                               | 2 +-
 12 files changed, 18 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 4a68d1c68..98c5a5306 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -165,7 +165,7 @@ export class Main extends React.Component {
     @action
     openWorkspace = async (doc: Doc, fromHistory = false) => {
         this.mainContainer = doc;
-        fromHistory || window.history.pushState(null, StrCast(doc.title), "/doc/" + doc.Id);
+        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 () => {
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index b2fba1415..ed761d3f3 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -95,7 +95,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             //TODO This won't create the field if it doesn't already exist
             const value = Cast(props.Document[props.fieldKey], listSpec(Doc));
             if (value !== undefined) {
-                if (allowDuplicates || !value.some(v => v.Id === doc.Id)) {
+                if (allowDuplicates || !value.some(v => v[Id] === doc[Id])) {
                     value.push(doc);
                 }
             } else {
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 99438b4e8..5a1af354a 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -8,6 +8,7 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView";
 import { emptyFunction } from "../../../Utils";
 import { NumCast } from "../../../new_fields/Types";
+import { Id } from "../../../new_fields/RefField";
 
 
 @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
+        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: emptyFunction });
         }
     }
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index d45be228a..7232ecea2 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -8,6 +8,7 @@ import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormV
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { emptyFunction } from "../../../Utils";
 import { NumCast } from "../../../new_fields/Types";
+import { Id } from "../../../new_fields/RefField";
 
 
 @observer
@@ -107,7 +108,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
+        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: emptyFunction });
         }
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index b72065bca..c2049a09a 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -10,6 +10,7 @@ import { CurrentUserUtils } from '../../../server/authentication/models/current_
 import { observer } from 'mobx-react';
 import { undoBatch } from '../../util/UndoManager';
 import { trace } from 'mobx';
+import { Id } from '../../../new_fields/RefField';
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
@@ -31,7 +32,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
     get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's?
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!this.isAnnotationOverlay && !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 (!this.isAnnotationOverlay && !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.viewType = CollectionViewType.Freeform) });
             ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema) });
             ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree) });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index dfacca204..dcded7648 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -257,7 +257,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             moveDocument: this.props.moveDocument,
             ScreenToLocalTransform: this.getTransform,
             isTopMost: false,
-            selectOnLoad: document.Id === this._selectOnLoaded,
+            selectOnLoad: document[Id] === this._selectOnLoaded,
             PanelWidth: () => Cast(document.width, "number", 0),//TODO Types These are inline functions
             PanelHeight: () => Cast(document.height, "number", 0),
             ContentScaling: returnOne,
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 376af0b36..8766eb7ea 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -20,6 +20,7 @@ const schema = createSchema({
     zIndex: "number"
 });
 
+//TODO Types: The import order is wrong, so positionSchema is undefined
 type FreeformDocument = makeInterface<[typeof schema, typeof positionSchema]>;
 const FreeformDocument = makeInterface(schema, positionSchema);
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c304b6a35..3814eeb9c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -139,7 +139,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     onClick = (e: React.MouseEvent): void => {
-        if (CurrentUserUtils.MainDocId !== this.props.Document.Id &&
+        if (CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
             (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
                 Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
             SelectionManager.SelectDoc(this, e.ctrlKey);
@@ -247,7 +247,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked });
         ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) });
         ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) });
-        ContextMenu.Instance.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document.Id)) });
+        ContextMenu.Instance.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])) });
         ContextMenu.Instance.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]) });
         //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) })
         ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 96512718f..c4c720ca9 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -22,6 +22,7 @@ import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
 import { StrCast, Cast } from "../../../new_fields/Types";
 import { RichTextField } from "../../../new_fields/RichTextField";
+import { Id } from "../../../new_fields/RefField";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -108,7 +109,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         };
 
         if (this.props.isOverlay) {
-            this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc.Id,
+            this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc[Id],
                 () => {
                     if (this._editorView) {
                         this._editorView.destroy();
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 7fbfed1c0..9f0849492 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -447,7 +447,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField);
         let xf = FieldValue(this.Document.nativeHeight, 0) / renderHeight;
         return <div className="pdfBox-contentContainer" key="container" style={{ transform: `scale(${xf}, ${xf})` }}>
-            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`} renderMode={this._renderAsSvg ? "svg" : ""}>
+            <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl!.url.href}`} renderMode={this._renderAsSvg ? "svg" : ""}>
                 <Measure onResize={this.setScaling}>
                     {({ measureRef }) =>
                         <div className="pdfBox-page" ref={measureRef}>
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts
index 0fa3cf73c..f2033d5a7 100644
--- a/src/new_fields/RichTextField.ts
+++ b/src/new_fields/RichTextField.ts
@@ -1,6 +1,8 @@
 import { ObjectField } from "./ObjectField";
 import { serializable } from "serializr";
+import { Deserializable } from "../client/util/SerializationHelper";
 
+@Deserializable("RichTextField")
 export class RichTextField extends ObjectField {
     @serializable(true)
     readonly Data: string;
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 3f8eabd45..e179c2602 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -76,7 +76,7 @@ type WithoutList<T extends Field> = T extends List<infer R> ? R[] : T;
 export function FieldValue<T extends Field, U extends WithoutList<T>>(field: FieldResult<T>, defaultValue: U): WithoutList<T>;
 export function FieldValue<T extends Field>(field: FieldResult<T>): Opt<T>;
 export function FieldValue<T extends Field>(field: FieldResult<T>, defaultValue?: T): Opt<T> {
-    return field instanceof Promise ? defaultValue : field;
+    return (field instanceof Promise || field === undefined) ? defaultValue : field;
 }
 
 export interface PromiseLike<T> {
-- 
cgit v1.2.3-70-g09d2


From 7d4a4b25459b66568880528cd3776b6ff9cbcf9f Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 30 Apr 2019 19:17:20 -0400
Subject: Fixed rich text background

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

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

diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 455672472..9c6f95fc4 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -279,7 +279,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         let color = StrCast(this.props.Document.backgroundColor);
         let interactive = InkingControl.Instance.selectedTool ? "" : "interactive";
         return (
-            <div className={`formattedTextBox-cont${style}`} ref={this._ref}
+            <div className={`formattedTextBox-cont-${style}`} ref={this._ref}
                 style={{
                     pointerEvents: interactive ? "all" : "none",
                     background: color,
-- 
cgit v1.2.3-70-g09d2


From 35105279d9cc55ccf331ec06de78077250b4cb5b Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 30 Apr 2019 19:30:17 -0400
Subject: Fixed various keys that hadn't been properly converted, which fixes
 zooming out on images/videos, etc.

---
 src/client/documents/Documents.ts           | 20 ++++++++++----------
 src/client/views/Templates.tsx              |  8 ++++----
 src/client/views/nodes/FormattedTextBox.tsx |  2 +-
 3 files changed, 15 insertions(+), 15 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 964faa8db..d9ee7a736 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -112,13 +112,13 @@ export namespace Docs {
     }
 
     function CreateImagePrototype(): Doc {
-        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"),
+        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: ImageBox.LayoutString(), curPage: 0 });
         return imageProto;
     }
 
     function CreateHistogramPrototype(): Doc {
-        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("AnnotationsKey"),
+        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("annotations"),
             { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString() });
         return histoProto;
     }
@@ -134,7 +134,7 @@ export namespace Docs {
         return textProto;
     }
     function CreatePdfPrototype(): Doc {
-        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"),
+        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("annotations"),
             { x: 0, y: 0, nativeWidth: 1200, width: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1 });
         return pdfProto;
     }
@@ -155,7 +155,7 @@ export namespace Docs {
         return kvpProto;
     }
     function CreateVideoPrototype(): Doc {
-        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("AnnotationsKey"),
+        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: VideoBox.LayoutString(), curPage: 0 });
         return videoProto;
     }
@@ -267,14 +267,14 @@ export namespace Docs {
             + ImageBox.LayoutString() +
             `</div>
             <div style="position:relative; height:15%; text-align:center; ">`
-            + FormattedTextBox.LayoutString("CaptionKey") +
+            + FormattedTextBox.LayoutString("caption") +
             `</div> 
         </div>`;
     }
-    export function FixedCaption(fieldName: string = "Caption") {
+    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") +
+            + FormattedTextBox.LayoutString(fieldName) +
             `</div> 
         </div>`;
     }
@@ -286,7 +286,7 @@ export namespace Docs {
         {layout}
     </div>
     <div style="height:(100% + 25px); width:100%; position:absolute">
-        <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+        <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
     </div>
 </div>       
         `);
@@ -298,7 +298,7 @@ export namespace Docs {
             {layout}
         </div>
         <div style="height:25px; width:100%; position:absolute">
-            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
         </div>
     </div>       
             `);
@@ -321,7 +321,7 @@ export namespace Docs {
             {layout}
         </div>
         <div style="height:15%; width:100%; position:absolute">
-            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"CaptionKey"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
         </div>
     </div>       
             `);
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index fef69392d..5b7e8da63 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -39,19 +39,19 @@ export namespace Templates {
     // export const BasicLayout = new Template("Basic layout", "{layout}");
 
     export const OuterCaption = new Template("Outer caption", TemplatePosition.OutterBottom,
-        `<div><div style="margin:auto; height:calc(100%); width:100%;">{layout}</div><div style="height:(100% + 50px); width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={CaptionKey} /></div></div>`
+        `<div><div style="margin:auto; height:calc(100%); width:100%;">{layout}</div><div style="height:(100% + 50px); width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={"caption"} /></div></div>`
     );
 
     export const InnerCaption = new Template("Inner caption", TemplatePosition.InnerBottom,
-        `<div><div style="margin:auto; height:calc(100% - 50px); width:100%;">{layout}</div><div style="height:50px; width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={CaptionKey}/></div></div>`
+        `<div><div style="margin:auto; height:calc(100% - 50px); width:100%;">{layout}</div><div style="height:50px; width:100%; position:absolute"><FormattedTextBox {...props} fieldKey={"caption"}/></div></div>`
     );
 
     export const SideCaption = new Template("Side caption", TemplatePosition.OutterRight,
-        `<div><div style="margin:auto; height:100%; width:100%;">{layout}</div><div style="height:100%; width:300px; position:absolute; top: 0; right: -300px;"><FormattedTextBox {...props} fieldKey={CaptionKey}/></div> </div>`
+        `<div><div style="margin:auto; height:100%; width:100%;">{layout}</div><div style="height:100%; width:300px; position:absolute; top: 0; right: -300px;"><FormattedTextBox {...props} fieldKey={"caption"}/></div> </div>`
     );
 
     export const Title = new Template("Title", TemplatePosition.InnerTop,
-        `<div><div style="height:100%; width:100%;position:absolute;">{layout}</div><div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:2px 10px">{Title}</div></div>`
+        `<div><div style="height:100%; width:100%;position:absolute;">{layout}</div><div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; padding:2px 10px">{Document.title}</div></div>`
     );
 
     export const TemplateList: Template[] = [Title, OuterCaption, InnerCaption, SideCaption];
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9c6f95fc4..b95d327d2 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -28,7 +28,7 @@ const { menuBar } = require("prosemirror-menu");
 
 // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
 //
-//  HTML Markup:  <FormattedTextBox Doc={Document's ID} FieldKey={Key's name + "Key"}
+//  HTML Markup:  <FormattedTextBox Doc={Document's ID} FieldKey={Key's name}
 //
 //  In Code, the node's HTML is specified in the document's parameterized structure as:
 //        document.SetField(KeyStore.Layout,  "<FormattedTextBox doc={doc} fieldKey={<KEYNAME>Key} />");
-- 
cgit v1.2.3-70-g09d2


From 3ed9fbefe1428c1493027122791ccbbe1b2fe1d1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 30 Apr 2019 19:48:36 -0400
Subject: fixed link document

---
 src/client/views/nodes/FormattedTextBox.scss | 6 +++---
 src/client/views/nodes/FormattedTextBox.tsx  | 8 ++++----
 src/new_fields/Doc.ts                        | 8 ++++----
 3 files changed, 11 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 727d3c0b2..d43aa4e02 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -30,11 +30,11 @@
     pointer-events: none;
 }
 .formattedTextBox-inner-rounded {
-    height: calc(100% - 40px);
+    height: calc(100% - 25px);
     width: calc(100% - 40px);
     position: absolute;
-    overflow: scroll;
-    top: 20;
+    overflow: auto;
+    top: 15;
     left: 20;
 }
 
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9c6f95fc4..fe9696062 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -144,8 +144,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
 
     private setupEditor(config: any, doc?: Doc) {
         let field = doc ? Cast(doc[this.props.fieldKey], RichTextField) : undefined;
-        if (this._ref.current) {
-            this._editorView = new EditorView(this._ref.current, {
+        if (this._proseRef.current) {
+            this._editorView = new EditorView(this._proseRef.current, {
                 state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config),
                 dispatchTransaction: this.dispatchTransaction
             });
@@ -195,8 +195,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         if (!this.props.isOverlay) {
             MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform);
         } else {
-            if (this._ref.current) {
-                this._ref.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
+            if (this._proseRef.current) {
+                this._proseRef.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
             }
         }
     }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 64cc6d270..c4ad5ae95 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -1,7 +1,6 @@
 import { observable, action } from "mobx";
 import { serializable, primitive, map, alias, list } from "serializr";
 import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper";
-import { Utils } from "../Utils";
 import { DocServer } from "../client/DocServer";
 import { setter, getter, getField, updateFunction, deleteProperty } from "./util";
 import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types";
@@ -10,6 +9,7 @@ import { listSpec } from "./Schema";
 import { List } from "./List";
 import { ObjectField, Parent, OnUpdate } from "./ObjectField";
 import { RefField, FieldId, Id } from "./RefField";
+import { Docs } from "../client/documents/Documents";
 
 export function IsField(field: any): field is Field {
     return (typeof field === "string")
@@ -163,9 +163,9 @@ export namespace Doc {
         return copy;
     }
 
-    export function MakeLink(source: Doc, target: Doc): Doc {
-        return UndoManager.RunInBatch(() => {
-            let linkDoc = new Doc;
+    export function MakeLink(source: Doc, target: Doc) {
+        UndoManager.RunInBatch(() => {
+            let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 });
             linkDoc.title = "New Link";
             linkDoc.linkDescription = "";
             linkDoc.linkTags = "Default";
-- 
cgit v1.2.3-70-g09d2


From 8f9baace2a0fd25e8a1cbdbb153cee1f286ad8e3 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 1 May 2019 09:03:17 -0400
Subject: fixed transition to GoldenLayout with Shift after drag starts

---
 src/client/views/nodes/DocumentView.tsx     | 1 -
 src/client/views/nodes/FormattedTextBox.tsx | 6 ++++++
 2 files changed, 6 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index eab068355..cda9f9473 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -171,7 +171,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             document.addEventListener("pointermove", this.onPointerMove);
             document.removeEventListener("pointerup", this.onPointerUp);
             document.addEventListener("pointerup", this.onPointerUp);
-            e.preventDefault();
         }
     }
     onPointerMove = (e: PointerEvent): void => {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 45e5901eb..12b7b5abf 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -237,6 +237,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     onClick = (e: React.MouseEvent): void => {
         this._proseRef.current!.focus();
     }
+    onMouseDown = (e: React.MouseEvent): void => {
+        if (!this.props.isSelected() && this.props.active()) { // preventing default allows the onClick to be generated instead of being swallowed by the text box itself
+            e.preventDefault(); // bcz: this would normally be in OnPointerDown - however, if done there, no mouse move events will be generated which makes transititioning to GoldenLayout's drag interactions impossible
+        }
+    }
 
     tooltipTextMenuPlugin() {
         let myprops = this.props;
@@ -290,6 +295,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 onClick={this.onClick}
                 onPointerUp={this.onPointerUp}
                 onPointerDown={this.onPointerDown}
+                onMouseDown={this.onMouseDown}
                 onContextMenu={this.specificContextMenu}
                 // tfs: do we need this event handler
                 onWheel={this.onPointerWheel}
-- 
cgit v1.2.3-70-g09d2


From d6ecb1cabeb34b5e55bc107f308f63071e4c40f7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 1 May 2019 11:02:53 -0400
Subject: fixed nested textbox selection

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

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

diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 12b7b5abf..7f269a505 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -238,7 +238,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         this._proseRef.current!.focus();
     }
     onMouseDown = (e: React.MouseEvent): void => {
-        if (!this.props.isSelected() && this.props.active()) { // preventing default allows the onClick to be generated instead of being swallowed by the text box itself
+        if (!this.props.isSelected()) { // preventing default allows the onClick to be generated instead of being swallowed by the text box itself
             e.preventDefault(); // bcz: this would normally be in OnPointerDown - however, if done there, no mouse move events will be generated which makes transititioning to GoldenLayout's drag interactions impossible
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 1ece3904b6b3fbf4ddde29e93e31a30f3898e720 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 2 May 2019 13:20:27 -0400
Subject: cleaned up drag code - userDropAction takes precedence over
 dropAction. default is alias

---
 src/client/documents/Documents.ts                  |  3 ++-
 src/client/util/DragManager.ts                     | 19 ++++++++++------
 src/client/views/DocumentDecorations.tsx           |  1 -
 src/client/views/EditableView.tsx                  |  2 +-
 src/client/views/Main.tsx                          | 14 +++++-------
 src/client/views/collections/CollectionSubView.tsx |  6 ++---
 .../views/collections/CollectionTreeView.scss      |  3 ++-
 .../views/collections/CollectionTreeView.tsx       | 26 +++++++++++-----------
 src/client/views/nodes/DocumentView.tsx            | 12 +++++-----
 src/client/views/nodes/FormattedTextBox.tsx        |  6 +++--
 10 files changed, 49 insertions(+), 43 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2de389a3c..8706359e4 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -32,6 +32,7 @@ import { IconField } from "../../new_fields/IconField";
 import { listSpec } from "../../new_fields/Schema";
 import { DocServer } from "../DocServer";
 import { StrokeData, InkField } from "../../new_fields/InkField";
+import { dropActionType } from "../util/DragManager";
 
 export interface DocumentOptions {
     x?: number;
@@ -51,7 +52,7 @@ export interface DocumentOptions {
     templates?: List<string>;
     viewType?: number;
     backgroundColor?: string;
-    copyDraggedItems?: boolean;
+    dropAction?: dropActionType;
     backgroundLayout?: string;
     curPage?: number;
     documentText?: string;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4acf609f4..a3dbe6e43 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,14 +1,14 @@
 import { action } from "mobx";
 import { emptyFunction } from "../../Utils";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
-import { DocumentDecorations } from "../views/DocumentDecorations";
 import * as globalCssVariables from "../views/globalCssVariables.scss";
 import { MainOverlayTextBox } from "../views/MainOverlayTextBox";
 import { Doc } from "../../new_fields/Doc";
 import { Cast } from "../../new_fields/Types";
 import { listSpec } from "../../new_fields/Schema";
 
-export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Doc, moveFunc?: DragManager.MoveFunction, copyOnDrop: boolean = false) {
+export type dropActionType = "alias" | "copy" | undefined;
+export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Doc, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) {
     let onRowMove = action((e: PointerEvent): void => {
         e.stopPropagation();
         e.preventDefault();
@@ -16,7 +16,7 @@ export function SetupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
         document.removeEventListener("pointermove", onRowMove);
         document.removeEventListener('pointerup', onRowUp);
         var dragData = new DragManager.DocumentDragData([docFunc()]);
-        dragData.copyOnDrop = copyOnDrop;
+        dragData.dropAction = dropAction;
         dragData.moveDocument = moveFunc;
         DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y);
     });
@@ -146,15 +146,20 @@ export namespace DragManager {
         droppedDocuments: Doc[];
         xOffset: number;
         yOffset: number;
-        aliasOnDrop?: boolean;
-        copyOnDrop?: boolean;
+        dropAction: dropActionType;
+        userDropAction: dropActionType;
         moveDocument?: MoveFunction;
         [id: string]: any;
     }
 
     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 ? dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : dragData.copyOnDrop ? dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : dragData.draggedDocuments));
+            (dropData: { [id: string]: any }) =>
+                (dropData.droppedDocuments = dragData.userDropAction == "alias" || (!dragData.userDropAction && dragData.dropAction == "alias") ?
+                    dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) :
+                    dragData.userDropAction == "copy" || (!dragData.userDropAction && dragData.dropAction == "copy") ?
+                        dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) :
+                        dragData.draggedDocuments));
     }
 
     export class LinkDragData {
@@ -252,7 +257,7 @@ export namespace DragManager {
             e.stopPropagation();
             e.preventDefault();
             if (dragData instanceof DocumentDragData) {
-                dragData.aliasOnDrop = e.ctrlKey || e.altKey;
+                dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined;
             }
             if (e.shiftKey) {
                 AbortDrag();
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7dcd71495..d07adcb71 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -144,7 +144,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
         dragData.xOffset = xoff;
         dragData.yOffset = yoff;
-        dragData.aliasOnDrop = false;
         dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument;
         this.Interacting = true;
         this._hidden = true;
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 2f17c6c51..73467eb9d 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -60,7 +60,7 @@ export class EditableView extends React.Component<EditableProps> {
             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}
+                    <span>{this.props.contents}</span>
                 </div>
             );
         }
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index b2ca4a196..a07a2d5b1 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -8,9 +8,7 @@ import * as React from 'react';
 import * as ReactDOM from 'react-dom';
 import Measure from 'react-measure';
 import * as request from 'request';
-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 { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils';
 import { Docs } from '../documents/Documents';
@@ -86,11 +84,11 @@ export class Main extends React.Component {
         this.initEventListeners();
         this.initAuthenticationRouters();
 
-        try {
-            this.initializeNorthstar();
-        } catch (e) {
+        // try {
+        //     this.initializeNorthstar();
+        // } catch (e) {
 
-        }
+        // }
     }
 
     componentDidMount() { window.onpopstate = this.onHistory; }
@@ -219,8 +217,8 @@ export class Main extends React.Component {
         let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, 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([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, copyDraggedItems: true }));
-        // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", copyDraggedItems: true }));
+        let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
+        // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy"  }));
         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" }));
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index bcbde24f0..a59bc196e 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -83,13 +83,13 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
         @action
         protected drop(e: Event, de: DragManager.DropEvent): boolean {
             if (de.data instanceof DragManager.DocumentDragData) {
-                if (de.data.aliasOnDrop || de.data.copyOnDrop) {
+                if (de.data.dropAction || de.data.userDropAction) {
                     ["width", "height", "curPage"].map(key =>
                         de.data.draggedDocuments.map((draggedDocument: Doc, i: number) =>
                             PromiseValue(Cast(draggedDocument[key], "number")).then(f => f && (de.data.droppedDocuments[i][key] = f))));
                 }
                 let added = false;
-                if (de.data.aliasOnDrop || de.data.copyOnDrop) {
+                if (de.data.dropAction || de.data.userDropAction) {
                     added = de.data.droppedDocuments.reduce((added: boolean, d) => {
                         let moved = this.props.addDocument(d);
                         return moved || added;
@@ -129,7 +129,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             }
             if (type.indexOf("excel") !== -1) {
                 ctor = Docs.DBDocument;
-                options.copyDraggedItems = true;
+                options.dropAction = "copy";
             }
             if (type.indexOf("html") !== -1) {
                 if (path.includes('localhost')) {
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index ecb5f78bb..d00785879 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -45,7 +45,8 @@
 
     .docContainer {
         margin-left: 10px;
-        display: inline-table;
+        display: block;
+        width: max-content;
     }
 
     .docContainer:hover {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 0520e0f88..037703c46 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -3,7 +3,7 @@ import { faCaretDown, faCaretRight, faTrashAlt } from '@fortawesome/free-solid-s
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, observable } from "mobx";
 import { observer } from "mobx-react";
-import { DragManager, SetupDrag } from "../../util/DragManager";
+import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager";
 import { EditableView } from "../EditableView";
 import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
@@ -12,8 +12,6 @@ import { Document, listSpec } from '../../../new_fields/Schema';
 import { Cast, StrCast, BoolCast, FieldValue } from '../../../new_fields/Types';
 import { Doc } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/RefField';
-import { Utils } from '../../../Utils';
-import { JSXElement } from 'babel-types';
 import { ContextMenu } from '../ContextMenu';
 import { undoBatch } from '../../util/UndoManager';
 import { Main } from '../Main';
@@ -24,7 +22,7 @@ export interface TreeViewProps {
     document: Doc;
     deleteDoc: (doc: Doc) => void;
     moveDocument: DragManager.MoveFunction;
-    copyOnDrag: boolean;
+    dropAction: "alias" | "copy" | undefined;
 }
 
 export enum BulletType {
@@ -83,7 +81,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.dropAction);
         let editableView = (titleString: string) =>
             (<EditableView
                 display={"inline"}
@@ -91,14 +89,15 @@ class TreeView extends React.Component<TreeViewProps> {
                 height={36}
                 GetValue={() => StrCast(this.props.document.title)}
                 SetValue={(value: string) => {
-                    this.props.document.title = value;
+                    let target = this.props.document.proto ? this.props.document.proto : this.props.document;
+                    target.title = value;
                     return true;
                 }}
             />);
         return (
             <div className="docContainer" ref={reference} onPointerDown={onItemDown}>
                 {editableView(StrCast(this.props.document.title))}
-                <div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>
+                {/* <div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div> */}
             </div >);
     }
 
@@ -117,7 +116,7 @@ class TreeView extends React.Component<TreeViewProps> {
             if (!this._collapsed) {
                 bulletType = BulletType.Collapsible;
                 contentElement = <ul>
-                    {TreeView.GetChildElements(children, this.remove, this.move, this.props.copyOnDrag)}
+                    {TreeView.GetChildElements(children, this.remove, this.move, this.props.dropAction)}
                 </ul >;
             }
             else bulletType = BulletType.Collapsed;
@@ -130,9 +129,9 @@ class TreeView extends React.Component<TreeViewProps> {
             </li>
         </div>;
     }
-    public static GetChildElements(docs: Doc[], remove: ((doc: Doc) => void), move: DragManager.MoveFunction, copyOnDrag: boolean) {
+    public static GetChildElements(docs: Doc[], remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) {
         return docs.filter(child => !child.excludeFromLibrary).map(child =>
-            <TreeView document={child} key={child[Id]} deleteDoc={remove} moveDocument={move} copyOnDrag={copyOnDrag} />);
+            <TreeView document={child} key={child[Id]} deleteDoc={remove} moveDocument={move} dropAction={dropAction} />);
     }
 }
 
@@ -154,13 +153,13 @@ export class CollectionTreeView extends CollectionSubView(Document) {
     }
     render() {
         const children = this.children;
-        let copyOnDrag = BoolCast(this.props.Document.copyDraggedItems, false);
+        let dropAction = StrCast(this.props.Document.dropAction, "alias") as dropActionType;
         if (!children) {
             return (null);
         }
         let testForLibrary = children && children.length === 1 && children[0] === CurrentUserUtils.UserDocument;
         var subchildren = testForLibrary ? Cast(children[0].data, listSpec(Doc), children) : children;
-        let childElements = TreeView.GetChildElements(subchildren, this.remove, this.props.moveDocument, copyOnDrag);
+        let childElements = TreeView.GetChildElements(subchildren, this.remove, this.props.moveDocument, dropAction);
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
@@ -175,7 +174,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                         height={72}
                         GetValue={() => StrCast(this.props.Document.title)}
                         SetValue={(value: string) => {
-                            this.props.Document.title = value;
+                            let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+                            target.title = value;
                             return true;
                         }} />
                 </div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 86d34725d..b151657e1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
 import { emptyFunction, Utils } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
-import { DragManager } from "../../util/DragManager";
+import { DragManager, dropActionType } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
@@ -129,12 +129,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.stopPropagation();
     }
 
-    startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
+    startDragging(x: number, y: number, dropAction: dropActionType) {
         if (this._mainCont.current) {
             const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0);
             let dragData = new DragManager.DocumentDragData([this.props.Document]);
             const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
-            dragData.aliasOnDrop = dropAliasOfDraggedDoc;
+            dragData.dropAction = dropAction;
             dragData.xOffset = xoff;
             dragData.yOffset = yoff;
             dragData.moveDocument = this.props.moveDocument;
@@ -142,7 +142,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 handlers: {
                     dragComplete: action(emptyFunction)
                 },
-                hideSource: !dropAliasOfDraggedDoc
+                hideSource: !dropAction
             });
         }
     }
@@ -162,7 +162,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
         if (e.shiftKey && e.buttons === 1) {
             if (this.props.isTopMost) {
-                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
+                this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey ? "alias" : undefined);
             } else {
                 CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
             }
@@ -180,7 +180,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 document.removeEventListener("pointermove", this.onPointerMove);
                 document.removeEventListener("pointerup", this.onPointerUp);
                 if (!e.altKey && !this.topMost && (!CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 1) || (CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 2)) {
-                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey);
+                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined);
                 }
             }
             e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 7f269a505..1d362bdaa 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -89,7 +89,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             if (title && title.startsWith("-") && this._editorView) {
                 let str = this._editorView.state.doc.textContent;
                 let titlestr = str.substr(0, Math.min(40, str.length));
-                this.props.Document.title = "-" + titlestr + (str.length > 40 ? "..." : "");
+                let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+                target.title = "-" + titlestr + (str.length > 40 ? "..." : "");
             };
         }
     }
@@ -275,7 +276,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         if (StrCast(this.props.Document.title).startsWith("-") && this._editorView) {
             let str = this._editorView.state.doc.textContent;
             let titlestr = str.substr(0, Math.min(40, str.length));
-            this.props.Document.title = "-" + titlestr + (str.length > 40 ? "..." : "");
+            let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+            target.title = "-" + titlestr + (str.length > 40 ? "..." : "");
         }
     }
     render() {
-- 
cgit v1.2.3-70-g09d2


From 9b33ac1cb790e88558edb3e4626f5a7b759ea3db Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 3 May 2019 14:46:31 -0400
Subject: added make button option.  summarize to text notes that can be frozen
 to resize.

---
 src/client/views/DocumentDecorations.tsx             |  1 +
 .../collections/collectionFreeForm/MarqueeView.tsx   | 20 +++++++++++++++-----
 .../views/nodes/CollectionFreeFormDocumentView.tsx   | 16 +++++++++-------
 src/client/views/nodes/DocumentView.tsx              | 10 +++++++++-
 src/client/views/nodes/FormattedTextBox.tsx          | 20 ++++++++++++++------
 5 files changed, 48 insertions(+), 19 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 2299f4c32..693d6ec55 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -255,6 +255,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     @action createIcon = (selected: DocumentView[], layoutString: string): Doc => {
         let doc = selected[0].props.Document;
         let iconDoc = Docs.IconDocument(layoutString);
+        iconDoc.isButton = true;
         iconDoc.title = selected.length > 1 ? "ICONset" : "ICON" + StrCast(doc.title);
         iconDoc.labelField = this._fieldKey;
         iconDoc[this._fieldKey] = selected.length > 1 ? "collection" : undefined;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 82027a6f2..8c81f6990 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -154,7 +154,8 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             e.stopPropagation();
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
-                this.props.removeDocument(d);
+                if (e.key !== "r")
+                    this.props.removeDocument(d);
                 d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
                 d.y = NumCast(d.y) - bounds.top - bounds.height / 2;
                 d.page = -1;
@@ -180,12 +181,21 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             // SelectionManager.DeselectAll();
             if (e.key === "r") {
                 let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
-                summary.doc1 = selected[0];
-                if (selected.length > 1)
-                    summary.doc2 = selected[1];
-                summary.templates = new List<string>([Templates.Summary.Layout]);
+                summary.maximizedDocs = new List<Doc>(selected);
+                // summary.doc1 = selected[0];
+                // if (selected.length > 1)
+                //     summary.doc2 = selected[1];
+                // summary.templates = new List<string>([Templates.Summary.Layout]);
                 this.props.addLiveTextDocument(summary);
                 e.preventDefault();
+                let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top);
+                selected.map(maximizedDoc => {
+                    let maxx = NumCast(maximizedDoc.x, undefined);
+                    let maxy = NumCast(maximizedDoc.y, undefined);
+                    let maxw = NumCast(maximizedDoc.width, undefined);
+                    let maxh = NumCast(maximizedDoc.height, undefined);
+                    maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0])
+                });
             }
             else {
                 this.props.addDocument(newCollection, false);
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 741af82fd..2ba0458f5 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -138,8 +138,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     if (isMinimized === undefined) {
                         isMinimized = BoolCast(maximizedDoc.isMinimized, false);
                     }
-                    let minx = NumCast(minimizedTarget.x, undefined);
-                    let miny = NumCast(minimizedTarget.y, undefined);
+                    let minx = NumCast(minimizedTarget.x, undefined) + NumCast(minimizedTarget.width, undefined) / 2;
+                    let miny = NumCast(minimizedTarget.y, undefined) + NumCast(minimizedTarget.height, undefined) / 2;
                     let maxx = NumCast(maximizedDoc.x, undefined);
                     let maxy = NumCast(maximizedDoc.y, undefined);
                     let maxw = NumCast(maximizedDoc.width, undefined);
@@ -164,11 +164,13 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         let ctrlKey = e.ctrlKey;
         if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
             Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
-            let maximizedDocs = await Cast(this.props.Document.maximizedDocs, listSpec(Doc));
-            if (maximizedDocs) {   // bcz: need a better way to associate behaviors with click events on widget-documents
-                if (ctrlKey)
-                    this.props.addDocument && maximizedDocs.filter(d => d instanceof Doc).map(maxDoc => this.props.addDocument!(maxDoc, false));
-                this.toggleIcon();
+            if (await BoolCast(this.props.Document.isButton, false)) {
+                let maximizedDocs = await Cast(this.props.Document.maximizedDocs, listSpec(Doc));
+                if (maximizedDocs) {   // bcz: need a better way to associate behaviors with click events on widget-documents
+                    if (ctrlKey)
+                        this.props.addDocument && maximizedDocs.filter(d => d instanceof Doc).map(maxDoc => this.props.addDocument!(maxDoc, false));
+                    this.toggleIcon();
+                }
             }
         }
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 892850a69..c08e322c0 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -16,7 +16,7 @@ import { Template, Templates } from "./../Templates";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
-import { Opt, Doc } from "../../../new_fields/Doc";
+import { Opt, Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
 import { DocComponent } from "../DocComponent";
 import { createSchema, makeInterface } from "../../../new_fields/Schema";
 import { FieldValue, StrCast, BoolCast } from "../../../new_fields/Types";
@@ -200,6 +200,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         let kvp = Docs.KVPDocument(this.props.Document, { width: 300, height: 300 });
         CollectionDockingView.Instance.AddRightSplit(kvp);
     }
+    makeButton = (e: React.MouseEvent): void => {
+        this.props.Document.isButton = !BoolCast(this.props.Document.isButton, false);
+        if (this.props.Document.isButton && !this.props.Document.nativeWidth) {
+            this.props.Document.nativeWidth = this.props.Document[WidthSym]();
+            this.props.Document.nativeHeight = this.props.Document[HeightSym]();
+        }
+    }
     fullScreenClicked = (e: React.MouseEvent): void => {
         const doc = Doc.MakeDelegate(FieldValue(this.Document.proto));
         if (doc) {
@@ -263,6 +270,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.preventDefault();
 
         ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked });
+        ContextMenu.Instance.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeButton });
         ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked });
         ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) });
         ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 1d362bdaa..eeb60cb3d 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -17,10 +17,10 @@ import React = require("react");
 import { SelectionManager } from "../../util/SelectionManager";
 import { DocComponent } from "../DocComponent";
 import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { Opt, Doc } from "../../../new_fields/Doc";
+import { Opt, Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
 import { observer } from "mobx-react";
 import { InkingControl } from "../InkingControl";
-import { StrCast, Cast, NumCast } from "../../../new_fields/Types";
+import { StrCast, Cast, NumCast, BoolCast } from "../../../new_fields/Types";
 import { RichTextField } from "../../../new_fields/RichTextField";
 import { Id } from "../../../new_fields/RefField";
 const { buildMenuItems } = require("prosemirror-example-setup");
@@ -128,7 +128,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             );
         } else {
             this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
-                () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
+                () => this.props.isSelected() && !BoolCast(this.props.Document.isButton, false) && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
         }
 
 
@@ -203,15 +203,23 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     }
 
     //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE
-    textCapability = (e: React.MouseEvent): void => { };
+    textCapability = (e: React.MouseEvent): void => {
+        if (NumCast(this.props.Document.nativeWidth)) {
+            this.props.Document.nativeWidth = undefined;
+            this.props.Document.nativeHeight = undefined;
 
+        } else {
+            this.props.Document.nativeWidth = this.props.Document[WidthSym]();
+            this.props.Document.nativeHeight = this.props.Document[HeightSym]();
+        }
+    }
     specificContextMenu = (e: React.MouseEvent): void => {
         if (!this._gotDown) {
             e.preventDefault();
             return;
         }
         ContextMenu.Instance.addItem({
-            description: "Text Capability",
+            description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze",
             event: this.textCapability
         });
 
@@ -302,7 +310,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 // tfs: do we need this event handler
                 onWheel={this.onPointerWheel}
             >
-                <div className={`formattedTextBox-inner${rounded}`} ref={this._proseRef} />
+                <div className={`formattedTextBox-inner${rounded}`} style={{ pointerEvents: this.props.Document.isButton ? "none" : "all" }} ref={this._proseRef} />
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2

