From 59cc888c8bf0559c50e12fd2774ea5ac4ebb3059 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Tue, 26 Feb 2019 16:33:53 -0500
Subject: basic implementation of prototype/delegate stuff

---
 src/client/views/nodes/FormattedTextBox.tsx | 4 +++-
 1 file changed, 3 insertions(+), 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 c0969a8c3..57ac880df 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -48,6 +48,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             const { doc, fieldKey } = this.props;
+            // doc.SetOnPrototype(fieldKey, new RichTextField(JSON.stringify(state.toJSON())))
             doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
         }
     }
@@ -103,7 +104,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
     @action
     onChange(e: React.ChangeEvent<HTMLInputElement>) {
         const { fieldKey, doc } = this.props;
-        doc.SetData(fieldKey, e.target.value, RichTextField);
+        doc.SetOnPrototype(fieldKey, new RichTextField(e.target.value))
+        // doc.SetData(fieldKey, e.target.value, RichTextField);
     }
     onPointerDown = (e: React.PointerEvent): void => {
         let me = this;
-- 
cgit v1.2.3-70-g09d2


From c469ece08b8df888395b6c1ab8205d3a027853fa Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Thu, 7 Mar 2019 22:18:47 -0500
Subject: changing branches

---
 .vscode/settings.json                           |  2 +
 src/client/documents/Documents.ts               | 87 +++++++++++--------------
 src/client/views/collections/CollectionView.tsx |  9 ++-
 src/client/views/nodes/FormattedTextBox.tsx     |  4 +-
 src/client/views/nodes/ImageBox.tsx             |  1 +
 src/fields/Document.ts                          |  4 +-
 6 files changed, 54 insertions(+), 53 deletions(-)

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

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 623dae755..7bc0a30f9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -9,4 +9,6 @@
     "editor.formatOnSave": true,
     "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
     "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true,
+    "python.linting.pylintEnabled": true,
+    "python.linting.enabled": true,
 }
\ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4c5f26fbd..9f739a48c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -11,6 +11,7 @@ import { CollectionView, CollectionViewType } from "../views/collections/Collect
 import { FieldView } from "../views/nodes/FieldView";
 import { HtmlField } from "../../fields/HtmlField";
 import { WebView } from "../views/nodes/WebView";
+import { Utils } from "../../Utils";
 
 export interface DocumentOptions {
     x?: number;
@@ -24,10 +25,10 @@ export interface DocumentOptions {
 
 export namespace Documents {
     export function initProtos(callback: () => void) {
-        Server.GetFields([collectionProtoId, textProtoId, imageProtoId], (fields) => {
-            collectionProto = fields[collectionProtoId] as Document;
-            imageProto = fields[imageProtoId] as Document;
-            textProto = fields[textProtoId] as Document;
+        Server.GetFields([], (fields) => {
+            // collectionProto = fields[collectionProtoId] as Document;
+            // imageProto = fields[imageProtoId] as Document;
+            // textProto = fields[textProtoId] as Document;
             callback()
         });
     }
@@ -59,18 +60,14 @@ export namespace Documents {
         doc.SetData(KeyStore.PanY, 0, NumberField);
     }
 
-    let textProto: Document;
-    const textProtoId = "textProto";
     function GetTextPrototype(): Document {
-        if (!textProto) {
-            textProto = new Document(textProtoId);
-            textProto.Set(KeyStore.X, new NumberField(0));
-            textProto.Set(KeyStore.Y, new NumberField(0));
-            textProto.Set(KeyStore.Width, new NumberField(300));
-            textProto.Set(KeyStore.Height, new NumberField(150));
-            textProto.Set(KeyStore.Layout, new TextField(FormattedTextBox.LayoutString()));
-            textProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
-        }
+        let textProto = new Document();
+        textProto.Set(KeyStore.X, new NumberField(0));
+        textProto.Set(KeyStore.Y, new NumberField(0));
+        textProto.Set(KeyStore.Width, new NumberField(300));
+        textProto.Set(KeyStore.Height, new NumberField(150));
+        textProto.Set(KeyStore.Layout, new TextField(FormattedTextBox.LayoutString()));
+        textProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
         return textProto;
     }
 
@@ -103,27 +100,23 @@ export namespace Documents {
         return doc;
     }
 
-    let imageProto: Document;
-    const imageProtoId = "imageProto";
+    // let imageProto: Document;
+    // const imageProtoId = "imageProto";
     function GetImagePrototype(): Document {
-        if (!imageProto) {
-            imageProto = new Document(imageProtoId);
-            imageProto.Set(KeyStore.Title, new TextField("IMAGE PROTO"));
-            imageProto.Set(KeyStore.X, new NumberField(0));
-            imageProto.Set(KeyStore.Y, new NumberField(0));
-            imageProto.Set(KeyStore.NativeWidth, new NumberField(300));
-            imageProto.Set(KeyStore.NativeHeight, new NumberField(300));
-            imageProto.Set(KeyStore.Width, new NumberField(300));
-            imageProto.Set(KeyStore.Height, new NumberField(300));
-            imageProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey")));
-            imageProto.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)
-            imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString()));
-            // imageProto.SetField(KeyStore.Layout, new TextField('<div style={"background-image: " + {Data}} />'));
-            imageProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations]));
-            return imageProto;
-        }
+        let imageProto = new Document();
+        imageProto.Set(KeyStore.Title, new TextField("IMAGE PROTO"));
+        imageProto.Set(KeyStore.X, new NumberField(0));
+        imageProto.Set(KeyStore.Y, new NumberField(0));
+        imageProto.Set(KeyStore.NativeWidth, new NumberField(300));
+        imageProto.Set(KeyStore.NativeHeight, new NumberField(300));
+        imageProto.Set(KeyStore.Width, new NumberField(300));
+        imageProto.Set(KeyStore.Height, new NumberField(300));
+        imageProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey")));
+        imageProto.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)
+        imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString()));
+        // imageProto.SetField(KeyStore.Layout, new TextField('<div style={"background-image: " + {Data}} />'));
+        imageProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations]));
         return imageProto;
-
     }
 
     // example of custom display string for an image that shows a caption.
@@ -146,28 +139,26 @@ export namespace Documents {
     export function ImageDocument(url: string, options: DocumentOptions = {}): Document {
         let doc = GetImagePrototype().MakeDelegate();
         setupOptions(doc, options);
-        doc.Set(KeyStore.Data, new ImageField(new URL(url)));
-        doc.Set(KeyStore.Caption, new TextField("my caption..."));
+        doc.SetOnPrototype(KeyStore.Data, new ImageField(new URL(url)));
+        doc.SetOnPrototype(KeyStore.Caption, new TextField("my caption..."));
         doc.Set(KeyStore.BackgroundLayout, new TextField(EmbeddedCaption()));
         doc.Set(KeyStore.OverlayLayout, new TextField(FixedCaption()));
         doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption]));
 
         let annotation = Documents.TextDocument({ title: "hello" });
-        doc.Set(KeyStore.Annotations, new ListField([annotation]));
+        doc.SetOnPrototype(KeyStore.Annotations, new ListField([annotation]));
         return doc;
     }
 
-    let collectionProto: Document;
+    // let collectionProto: Document;
     const collectionProtoId = "collectionProto";
     function GetCollectionPrototype(): Document {
-        if (!collectionProto) {
-            collectionProto = new Document(collectionProtoId);
-            collectionProto.Set(KeyStore.Scale, new NumberField(1));
-            collectionProto.Set(KeyStore.PanX, new NumberField(0));
-            collectionProto.Set(KeyStore.PanY, new NumberField(0));
-            collectionProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("DataKey")));
-            collectionProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
-        }
+        let collectionProto = new Document();
+        collectionProto.Set(KeyStore.Scale, new NumberField(1));
+        collectionProto.Set(KeyStore.PanX, new NumberField(0));
+        collectionProto.Set(KeyStore.PanY, new NumberField(0));
+        collectionProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("DataKey")));
+        collectionProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
         return collectionProto;
     }
 
@@ -175,9 +166,9 @@ export namespace Documents {
         let doc = GetCollectionPrototype().MakeDelegate(id);
         setupOptions(doc, options);
         if (typeof data === "string") {
-            doc.SetText(KeyStore.Data, data);
+            doc.SetOnPrototype(KeyStore.Data, new TextField(data));
         } else {
-            doc.SetData(KeyStore.Data, data, ListField);
+            doc.SetOnPrototype(KeyStore.Data, new ListField(data));
         }
         doc.SetNumber(KeyStore.ViewType, viewType);
         return doc;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 90080ab43..18e290477 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -11,6 +11,7 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import { CollectionDockingView } from "./CollectionDockingView";
 import { CollectionSchemaView } from "./CollectionSchemaView";
 import { CollectionViewProps } from "./CollectionViewBase";
+import { Field } from "../../../fields/Field";
 
 
 
@@ -40,8 +41,12 @@ export class CollectionView extends React.Component<CollectionViewProps> {
     @action
     addDocument = (doc: Document): void => {
         //TODO This won't create the field if it doesn't already exist
-        const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>())
-        value.push(doc);
+        let value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array<Document>())
+        value.push(doc)
+        // this.props.Document.GetAsync(this.props.fieldKey, (f: Field) => {
+        //     (f as ListField<Document>).Data.push(doc);
+        //     this.props.Document.SetOnPrototype(KeyStore.Data, (f as ListField<Document>))
+        // })
     }
 
     @action
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 57ac880df..727645934 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -48,8 +48,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             const { doc, fieldKey } = this.props;
-            // doc.SetOnPrototype(fieldKey, new RichTextField(JSON.stringify(state.toJSON())))
-            doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+            doc.SetOnPrototype(fieldKey, new RichTextField(JSON.stringify(state.toJSON())))
+            // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
         }
     }
 
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index b5ce8b28c..f3c1d3f4e 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -81,6 +81,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
 
     render() {
         let field = this.props.doc.Get(this.props.fieldKey);
+        console.log(field)
         let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
             field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif";
         let nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 1);
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 39648a950..1b27c4a13 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -212,7 +212,9 @@ export class Document extends Field {
 
     CreateAlias(id?: string): Document {
         let alias = new Document(id)
-        alias.Set(KeyStore.Prototype, this)
+        this.GetAsync(KeyStore.Prototype, (f: Field) => {
+            alias.Set(KeyStore.Prototype, f)
+        })
 
         return alias
     }
-- 
cgit v1.2.3-70-g09d2


From 43c96800f0a651247fdcaf2c77c710a30cb3f79d Mon Sep 17 00:00:00 2001
From: Jude <julie_wang1@brown.edu>
Date: Sun, 10 Mar 2019 13:06:04 -0400
Subject: changed default sizing

---
 src/client/documents/Documents.ts                  |  8 +++---
 src/client/views/Main.tsx                          | 14 ++++-----
 src/client/views/_global_variables.scss            |  2 +-
 .../views/collections/CollectionFreeFormView.scss  |  2 +-
 .../views/collections/CollectionSchemaView.scss    |  2 ++
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../views/collections/CollectionTreeView.scss      | 33 ++++++++++++----------
 src/client/views/nodes/FormattedTextBox.tsx        |  2 +-
 src/client/views/nodes/ImageBox.scss               | 29 +++++++++----------
 9 files changed, 49 insertions(+), 45 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index fc210e9a2..30a292502 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -113,7 +113,7 @@ export namespace Documents {
     function GetCollectionPrototype(): Document {
         return collProto ? collProto :
             collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"),
-                { panx: 0, pany: 0, scale: 1, layoutKeys: [KeyStore.Data] });
+                { panx: 0, pany: 0, scale: 1, width: 500, height: 500, layoutKeys: [KeyStore.Data] });
     }
 
     function GetKVPPrototype(): Document {
@@ -125,9 +125,9 @@ export namespace Documents {
     export function ImageDocument(url: string, options: DocumentOptions = {}) {
         let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
             new URL(url), ImageField);
-        doc.SetText(KeyStore.Caption, "my caption...");
-        doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption());
-        doc.SetText(KeyStore.OverlayLayout, FixedCaption());
+        // doc.SetText(KeyStore.Caption, "my caption...");
+        // doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption());
+        // doc.SetText(KeyStore.OverlayLayout, FixedCaption());
         return doc;
     }
     export function TextDocument(options: DocumentOptions = {}) {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 1caaa1cba..79c5cb5aa 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -76,12 +76,12 @@ Documents.initProtos(mainDocId, (res?: Document) => {
     let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf"
     let weburl = "https://cs.brown.edu/courses/cs166/";
     let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {}))
-    let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" }))
-    let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
-    let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" }));
-    let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" }));
+    let addTextNode = action(() => Documents.TextDocument({ width: 230, height: 130, title: "a text note" }))
+    let addColNode = action(() => Documents.FreeformDocument([], { width: 300, height: 300, title: "a freeform collection" }));
+    let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 450, height: 200, title: "a schema collection" }));
+    let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 300, height: 400, title: "a pdf" }));
     let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" }));
-    let addWebNode = action(() => Documents.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
+    let addWebNode = action(() => Documents.WebDocument(weburl, { width: 300, height: 400, title: "a sample web page" }));
 
 
     let addClick = (creator: () => Document) => action(() =>
@@ -100,7 +100,7 @@ Documents.initProtos(mainDocId, (res?: Document) => {
 
     ReactDOM.render((
         <div style={{ position: "absolute", width: "100%", height: "100%" }}>
-            <div id="dash-title">— DASH —</div>
+            {/* <div id="dash-title">— DASH —</div> */}
 
             <DocumentView Document={mainContainer}
                 AddDocument={undefined} RemoveDocument={undefined} ScreenToLocalTransform={() => Transform.Identity}
@@ -153,7 +153,7 @@ Documents.initProtos(mainDocId, (res?: Document) => {
 
             </div>
 
-            <InkingControl />
+            {/* <InkingControl /> */}
         </div >),
         document.getElementById('root'));
 })
diff --git a/src/client/views/_global_variables.scss b/src/client/views/_global_variables.scss
index 333fb3122..1c06ab44a 100644
--- a/src/client/views/_global_variables.scss
+++ b/src/client/views/_global_variables.scss
@@ -1,4 +1,4 @@
-@import url("https://fonts.googleapis.com/css?family=Roboto+Slab:300,700|Crimson+Text:400,400i,700");
+@import url("https://fonts.googleapis.com/css?family=Roboto+Slab:,700|Crimson+Text:400,400i,700");
 
 // colors
 $light-color: #fcfbf7;
diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss
index 90caa0d14..7250c9241 100644
--- a/src/client/views/collections/CollectionFreeFormView.scss
+++ b/src/client/views/collections/CollectionFreeFormView.scss
@@ -41,7 +41,7 @@
     background: $light-color-secondary;
   }
 
-  border: 0px solid $intermediate-color;
+  border: 0px solid transparent;
   border-radius: $border-radius;
   box-sizing: border-box;
   position: absolute;
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index cb0040657..b66fc7981 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -7,6 +7,8 @@
   position: absolute;
   width: 100%;
   height: 100%;
+  overflow: hidden;
+
   .collectionSchemaView-previewRegion {
     position: relative;
     background: $light-color;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 19ed97391..deb307fb3 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -31,7 +31,7 @@ export class CollectionSchemaView extends CollectionViewBase {
     @observable _panelWidth = 0;
     @observable _panelHeight = 0;
     @observable _selectedIndex = 0;
-    @observable _splitPercentage: number = 50;
+    @observable _splitPercentage: number = 100;
 
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index f8d580a7b..4b28ded45 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -1,37 +1,40 @@
+@import "../global_variables";
+
 #body {
-    padding: 20px;
-    background: #bbbbbb;
+  padding: 20px;
+  background: $light-color-secondary;
 }
 
 ul {
-    list-style: none;
+  list-style: none;
 }
 
 li {
-    margin: 5px 0;
+  margin: 5px 0;
 }
 
 .no-indent {
-    padding-left: 0;
+  padding-left: 0;
 }
 
 .bullet {
-    width: 1.5em;
-    display: inline-block;
+  width: 1.5em;
+  display: inline-block;
 }
 
 .collectionTreeView-dropTarget {
-    border-style: solid;
-    box-sizing: border-box;
-    height: 100%;
+  border: 0px solid $intermediate-color;
+  border-radius: $border-radius;
+  box-sizing: border-box;
+  height: 100%;
 }
 
 .docContainer {
-    display: inline-table;
+  display: inline-table;
 }
 
 .delete-button {
-    color: #999999;
-    float: right;
-    margin-left: 1em;
-}
\ No newline at end of file
+  color: $intermediate-color;
+  float: right;
+  margin-left: 1em;
+}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index a6cee9957..a375cfc48 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -31,7 +31,7 @@ import { ContextMenu } from "../../views/ContextMenu";
 //    and 'doc' property to the document that is being rendered
 //
 //  When rendered() by React, this extracts the TextController from the Document stored at the 
-//  specified Key and assigns it to an HTML input node.  When changes are made tot his node, 
+//  specified Key and assigns it to an HTML input node.  When changes are made to this node, 
 //  this will edit the document and assign the new value to that field.
 //]
 export class FormattedTextBox extends React.Component<FieldViewProps> {
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index ea459b911..2cb460eea 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -1,22 +1,21 @@
-
 .imageBox-cont {
-    padding: 0vw;
-    position: relative;
-    text-align: center;
-    width: 100%;
-    height: auto;
-    max-width: 100%;
-    max-height: 100%
+  padding: 0vw;
+  position: relative;
+  text-align: center;
+  width: 100%;
+  height: auto;
+  max-width: 100%;
+  max-height: 100%;
 }
 
 .imageBox-cont img {
-    object-fit: contain;
-    height: 100%;
+  object-fit: contain;
+  height: 100%;
 }
 
 .imageBox-button {
-    padding : 0vw;
-    border: none;
-    width : 100%;
-    height: 100%;
-}
\ No newline at end of file
+  padding: 0vw;
+  border: none;
+  width: 100%;
+  height: 100%;
+}
-- 
cgit v1.2.3-70-g09d2


From 0b9dab6403ed3e073f499cd38d3cb4aa434d7c95 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 10 Mar 2019 20:30:44 -0400
Subject: fixed  issue with typing into an existing note in an embedded
 collection

---
 src/client/views/nodes/FormattedTextBox.tsx | 4 ++++
 1 file changed, 4 insertions(+)

(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 a6cee9957..f5063f9b1 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -151,8 +151,12 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         })
     }
 
+    onKeyPress(e: React.KeyboardEvent) {
+        e.stopPropagation();
+    }
     render() {
         return (<div className="formattedTextBox-cont"
+            onKeyPress={this.onKeyPress}
             onPointerDown={this.onPointerDown}
             onContextMenu={this.specificContextMenu}
             onWheel={this.onPointerWheel}
-- 
cgit v1.2.3-70-g09d2


From 845a7989a6ff66b1c922d1f7f69c7560b6783dd8 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 10 Mar 2019 22:20:31 -0400
Subject: fixed type of FormattedTextBox to RichTextField

---
 src/client/documents/Documents.ts           | 11 ++++++-----
 src/client/views/nodes/FormattedTextBox.tsx |  2 +-
 2 files changed, 7 insertions(+), 6 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a91834cca..b78762018 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -22,6 +22,7 @@ import { AudioBox } from "../views/nodes/AudioBox";
 import { PDFField } from "../../fields/PDFField";
 import { PDFBox } from "../views/nodes/PDFBox";
 import { CollectionPDFView } from "../views/collections/CollectionPDFView";
+import { RichTextField } from "../../fields/RichTextField";
 
 export interface DocumentOptions {
     x?: number;
@@ -45,8 +46,8 @@ export namespace Documents {
     let webProto: Document;
     let collProto: Document;
     let kvpProto: Document;
-    let videoProto: Document; 
-    let audioProto: Document; 
+    let videoProto: Document;
+    let audioProto: Document;
     let pdfProto: Document;
     const textProtoId = "textProto";
     const pdfProtoId = "pdfProto";
@@ -150,7 +151,7 @@ export namespace Documents {
         doc.SetText(KeyStore.OverlayLayout, FixedCaption());
         return doc;
     }
-    export function VideoDocument(url: string, options: DocumentOptions = {}){
+    export function VideoDocument(url: string, options: DocumentOptions = {}) {
         let doc = SetInstanceOptions(GetVideoPrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
             new URL(url), VideoField);
         doc.SetText(KeyStore.Caption, "my caption...");
@@ -158,7 +159,7 @@ export namespace Documents {
         doc.SetText(KeyStore.OverlayLayout, FixedCaption());
         return doc;
     }
-    export function AudioDocument(url: string, options: DocumentOptions = {}){
+    export function AudioDocument(url: string, options: DocumentOptions = {}) {
         let doc = SetInstanceOptions(GetAudioPrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
             new URL(url), AudioField);
         doc.SetText(KeyStore.Caption, "my caption...");
@@ -167,7 +168,7 @@ export namespace Documents {
         return doc;
     }
     export function TextDocument(options: DocumentOptions = {}) {
-        return SetInstanceOptions(GetTextPrototype(), options, "", TextField);
+        return SetInstanceOptions(GetTextPrototype(), options, "", RichTextField);
     }
     export function PdfDocument(url: string, options: DocumentOptions = {}) {
         return SetInstanceOptions(GetPdfPrototype(), options, new URL(url), PDFField);
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index f5063f9b1..ad7ddf37a 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -69,7 +69,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         };
 
         let field = this.props.doc.GetT(this.props.fieldKey, RichTextField);
-        if (field && field != FieldWaiting) {
+        if (field && field != FieldWaiting && field.Data) {
             state = EditorState.fromJSON(config, JSON.parse(field.Data));
         } else {
             state = EditorState.create(config);
-- 
cgit v1.2.3-70-g09d2


From bff0093163bdc05fb661eb744c2333069544dc89 Mon Sep 17 00:00:00 2001
From: laurawilsonri <laura_wilson@brown.edu>
Date: Mon, 11 Mar 2019 18:48:58 -0400
Subject: added a method to check if block has a syle ie bullets

---
 src/client/util/RichTextSchema.tsx          | 44 +++++++++++++++++++++++++----
 src/client/util/TooltipTextMenu.tsx         |  3 +-
 src/client/views/nodes/FormattedTextBox.tsx |  2 ++
 3 files changed, 41 insertions(+), 8 deletions(-)

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

diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index abf448c9f..341d5a443 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -1,12 +1,31 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Schema, NodeSpec, MarkSpec, DOMOutputSpecArray } from "prosemirror-model"
+import { Schema, NodeSpec, MarkSpec, DOMOutputSpecArray, NodeType } from "prosemirror-model"
 import { joinUp, lift, setBlockType, toggleMark, wrapIn } from 'prosemirror-commands'
 import { redo, undo } from 'prosemirror-history'
-import { orderedList, bulletList, listItem } from 'prosemirror-schema-list'
+import { orderedList, bulletList, listItem, } from 'prosemirror-schema-list'
+import { EditorState, Transaction, NodeSelection, } from "prosemirror-state";
+import { EditorView, } from "prosemirror-view";
 
 const pDOM: DOMOutputSpecArray = ["p", 0], blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"],
   preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]
 
+//adapted this method - use it to check if block has a tag (ie bulleting)
+const blockActive = (type: NodeType<Schema<string, string>>, attrs = {}) => (state: EditorState) => {
+
+  if (state.selection instanceof NodeSelection) {
+    const sel: NodeSelection = state.selection;
+    let $from = sel.$from;
+    let to = sel.to;
+    let node = sel.node;
+
+    if (node) {
+      return node.hasMarkup(type, attrs);
+    }
+
+    return to <= $from.end() && $from.parent.hasMarkup(type, attrs);
+  }
+};
+
 // :: Object
 // [Specs](#model.NodeSpec) for the nodes defined in this schema.
 export const nodes: { [index: string]: NodeSpec } = {
@@ -113,11 +132,24 @@ export const nodes: { [index: string]: NodeSpec } = {
     content: 'list_item+',
     group: 'block'
   },
+  //bullet_list: {
+  //  ...bulletList,
+  //  content: 'list_item+',
+  //  group: 'block',
+  //parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
+  //toDOM() { return ulDOM }
+  //},
   bullet_list: {
-    content: 'list_item+',
-    group: 'block',
-    parseDOM: [{ tag: "ul" }, { style: "list-style-type=disc;" }],
-    toDOM() { return ulDOM }
+    title: "Wrap in bullet list",
+    content: icons.bullet_list,
+    active: blockActive(state.config.schema.nodes.bullet_list),
+    enable: state => wrapInList(state.config.schema.nodes.bullet_list),
+    run: state => wrapInList(state.config.schema.nodes.bullet_list),
+    active: blockActive(schema.nodes.bullet_list),
+    enable: wrapInList(schema.nodes.bullet_list),
+    run: wrapInList(schema.nodes.bullet_list),
+    select: state => true,
+    menu: props => <Button key={uuid()} {...props} />
   },
   list_item: {
     ...listItem,
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 3b87fe9de..90b10a3ce 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -2,7 +2,6 @@ import { action, IReactionDisposer, reaction } from "mobx";
 import { baseKeymap } from "prosemirror-commands";
 import { history, redo, undo } from "prosemirror-history";
 import { keymap } from "prosemirror-keymap";
-const { exampleSetup } = require("prosemirror-example-setup")
 import { EditorState, Transaction, } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { schema } from "./RichTextSchema";
@@ -39,7 +38,7 @@ export class TooltipTextMenu {
       { command: toggleMark(schema.marks.strikethrough), dom: this.icon("S", "strikethrough") },
       { command: toggleMark(schema.marks.superscript), dom: this.icon("s", "superscript") },
       { command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") },
-      { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") }
+      { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
     ]
     items.forEach(({ dom }) => this.tooltip.appendChild(dom));
 
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index a6cee9957..d3184612c 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -14,6 +14,8 @@ import { Plugin } from 'prosemirror-state'
 import { Decoration, DecorationSet } from 'prosemirror-view'
 import { TooltipTextMenu } from "../../util/TooltipTextMenu"
 import { ContextMenu } from "../../views/ContextMenu";
+const { buildMenuItems } = require("prosemirror-example-setup");
+const { menuBar } = require("prosemirror-menu");
 
 
 
-- 
cgit v1.2.3-70-g09d2


From eb1c48dc6ff1403372f820d07b46c08f58cc7306 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 11 Mar 2019 20:46:22 -0400
Subject: added modifier options for macbook

---
 src/client/util/DragManager.ts                          | 2 +-
 src/client/views/collections/CollectionFreeFormView.tsx | 2 +-
 src/client/views/nodes/DocumentView.tsx                 | 2 +-
 src/client/views/nodes/FormattedTextBox.tsx             | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4a61220a5..9bd7d5c24 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -158,7 +158,7 @@ export namespace DragManager {
             e.preventDefault();
             x += e.movementX;
             y += e.movementY;
-            if (e.shiftKey) {
+            if (e.shiftKey && (e.button == 2 || e.altKey)) {
                 abortDrag();
                 CollectionDockingView.Instance.StartOtherDrag(doc, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 });
             }
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index b5dc5ab18..74d37ccec 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -77,7 +77,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
 
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        if (((e.button === 2 && this.props.active()) || !e.defaultPrevented) && !e.shiftKey &&
+        if (((e.button === 2 && this.props.active()) || !e.defaultPrevented) &&
             (!this.isAnnotationOverlay || this.zoomScaling != 1 || e.button == 0)) {
             document.removeEventListener("pointermove", this.onPointerMove);
             document.addEventListener("pointermove", this.onPointerMove);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index dc793c16d..da40f0dc1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -182,7 +182,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
             document.removeEventListener("pointermove", this.onPointerMove)
             document.removeEventListener("pointerup", this.onPointerUp);
-            if (!this.topMost || e.buttons == 2) {
+            if (!this.topMost || e.buttons == 2 || e.altKey) {
                 this.startDragging(e.x, e.y);
             }
         }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index ad7ddf37a..5c7aaf9fe 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -113,7 +113,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         this.props.doc.SetData(this.props.fieldKey, e.target.value, RichTextField);
     }
     onPointerDown = (e: React.PointerEvent): void => {
-        if (e.buttons === 1 && this.props.isSelected()) {
+        if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
             e.stopPropagation();
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 50477f0a9b0b371b4f381b6cef14030a9d7de21e Mon Sep 17 00:00:00 2001
From: laurawilsonri <laura_wilson@brown.edu>
Date: Tue, 12 Mar 2019 16:14:13 -0400
Subject: added some helpful comments

---
 package-lock.json                           |  9 ++++++
 package.json                                |  1 +
 src/client/util/RichTextRules.ts            | 43 ++++++++++++++++++++++++++
 src/client/util/RichTextSchema.tsx          | 47 +++++++++--------------------
 src/client/util/TooltipTextMenu.tsx         | 24 ++++++++++++---
 src/client/views/nodes/FormattedTextBox.tsx |  2 ++
 6 files changed, 88 insertions(+), 38 deletions(-)
 create mode 100644 src/client/util/RichTextRules.ts

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

diff --git a/package-lock.json b/package-lock.json
index 9343a2e88..e780b247f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -320,6 +320,15 @@
         "@types/prosemirror-state": "*"
       }
     },
+    "@types/prosemirror-inputrules": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/@types/prosemirror-inputrules/-/prosemirror-inputrules-1.0.2.tgz",
+      "integrity": "sha512-bKFneQUPnkZmzCJ1uoitpKH6PFW0hc4q55NsC7mFUCvX0eZl0GRKxyfV47jkJbsbyUQoO/QFv0WwLDz2bo15sA==",
+      "requires": {
+        "@types/prosemirror-model": "*",
+        "@types/prosemirror-state": "*"
+      }
+    },
     "@types/prosemirror-keymap": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.1.tgz",
diff --git a/package.json b/package.json
index a89d82645..841796bb4 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
     "@types/passport-local": "^1.0.33",
     "@types/prosemirror-commands": "^1.0.1",
     "@types/prosemirror-history": "^1.0.1",
+    "@types/prosemirror-inputrules": "^1.0.2",
     "@types/prosemirror-keymap": "^1.0.1",
     "@types/prosemirror-model": "^1.7.0",
     "@types/prosemirror-schema-basic": "^1.0.1",
diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts
new file mode 100644
index 000000000..3b8396510
--- /dev/null
+++ b/src/client/util/RichTextRules.ts
@@ -0,0 +1,43 @@
+import {
+    inputRules,
+    wrappingInputRule,
+    textblockTypeInputRule,
+    smartQuotes,
+    emDash,
+    ellipsis
+} from "prosemirror-inputrules";
+import { Schema, NodeSpec, MarkSpec, DOMOutputSpecArray, NodeType } from "prosemirror-model";
+
+import { schema } from "./RichTextSchema";
+
+export const inpRules = {
+    rules: [
+        ...smartQuotes,
+        ellipsis,
+        emDash,
+
+        // > blockquote
+        wrappingInputRule(/^\s*>\s$/, schema.nodes.blockquote),
+
+        // 1. ordered list
+        wrappingInputRule(
+            /^(\d+)\.\s$/,
+            schema.nodes.ordered_list,
+            match => ({ order: +match[1] }),
+            (match, node) => node.childCount + node.attrs.order === +match[1]
+        ),
+
+        // * bullet list
+        wrappingInputRule(/^\s*([-+*])\s$/, schema.nodes.bullet_list),
+
+        // ``` code block
+        textblockTypeInputRule(/^```$/, schema.nodes.code_block),
+
+        // # heading
+        textblockTypeInputRule(
+            new RegExp("^(#{1,6})\\s$"),
+            schema.nodes.heading,
+            match => ({ level: match[1].length })
+        )
+    ]
+};
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 341d5a443..2a3c1da6e 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -9,22 +9,6 @@ import { EditorView, } from "prosemirror-view";
 const pDOM: DOMOutputSpecArray = ["p", 0], blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"],
   preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]
 
-//adapted this method - use it to check if block has a tag (ie bulleting)
-const blockActive = (type: NodeType<Schema<string, string>>, attrs = {}) => (state: EditorState) => {
-
-  if (state.selection instanceof NodeSelection) {
-    const sel: NodeSelection = state.selection;
-    let $from = sel.$from;
-    let to = sel.to;
-    let node = sel.node;
-
-    if (node) {
-      return node.hasMarkup(type, attrs);
-    }
-
-    return to <= $from.end() && $from.parent.hasMarkup(type, attrs);
-  }
-};
 
 // :: Object
 // [Specs](#model.NodeSpec) for the nodes defined in this schema.
@@ -132,25 +116,22 @@ export const nodes: { [index: string]: NodeSpec } = {
     content: 'list_item+',
     group: 'block'
   },
-  //bullet_list: {
-  //  ...bulletList,
-  //  content: 'list_item+',
-  //  group: 'block',
-  //parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
-  //toDOM() { return ulDOM }
-  //},
+  //this doesn't currently work for some reason
   bullet_list: {
-    title: "Wrap in bullet list",
-    content: icons.bullet_list,
-    active: blockActive(state.config.schema.nodes.bullet_list),
-    enable: state => wrapInList(state.config.schema.nodes.bullet_list),
-    run: state => wrapInList(state.config.schema.nodes.bullet_list),
-    active: blockActive(schema.nodes.bullet_list),
-    enable: wrapInList(schema.nodes.bullet_list),
-    run: wrapInList(schema.nodes.bullet_list),
-    select: state => true,
-    menu: props => <Button key={uuid()} {...props} />
+    ...bulletList,
+    content: 'list_item+',
+    group: 'block',
+    // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
+    // toDOM() { return ulDOM }
   },
+  //bullet_list: {
+  //  content: 'list_item+',
+  // group: 'block',
+  //active: blockActive(schema.nodes.bullet_list),
+  //enable: wrapInList(schema.nodes.bullet_list),
+  //run: wrapInList(schema.nodes.bullet_list),
+  //select: state => true,
+  // },
   list_item: {
     ...listItem,
     content: 'paragraph block*'
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 90b10a3ce..d771ed13f 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -2,9 +2,10 @@ import { action, IReactionDisposer, reaction } from "mobx";
 import { baseKeymap } from "prosemirror-commands";
 import { history, redo, undo } from "prosemirror-history";
 import { keymap } from "prosemirror-keymap";
-import { EditorState, Transaction, } from "prosemirror-state";
+import { EditorState, Transaction, NodeSelection } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { schema } from "./RichTextSchema";
+import { Schema, NodeType } from "prosemirror-model"
 import React = require("react")
 import "./TooltipTextMenu.scss";
 const { toggleMark, setBlockType, wrapIn } = require("prosemirror-commands");
@@ -15,7 +16,7 @@ import {
 } from '@fortawesome/free-solid-svg-icons';
 
 
-
+//appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
 
   private tooltip: HTMLElement;
@@ -38,6 +39,7 @@ export class TooltipTextMenu {
       { command: toggleMark(schema.marks.strikethrough), dom: this.icon("S", "strikethrough") },
       { command: toggleMark(schema.marks.superscript), dom: this.icon("s", "superscript") },
       { command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") },
+      //this doesn't work currently - look into notion of active block
       { command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
     ]
     items.forEach(({ dom }) => this.tooltip.appendChild(dom));
@@ -65,10 +67,22 @@ export class TooltipTextMenu {
     return span;
   }
 
-  blockActive(view: EditorView) {
-    const { $from, to } = view.state.selection
+  //adapted this method - use it to check if block has a tag (ie bulleting)
+  blockActive(type: NodeType<Schema<string, string>>, state: EditorState) {
+    let attrs = {};
+
+    if (state.selection instanceof NodeSelection) {
+      const sel: NodeSelection = state.selection;
+      let $from = sel.$from;
+      let to = sel.to;
+      let node = sel.node;
 
-    return to <= $from.end() && $from.parent.hasMarkup(schema.nodes.bulletList);
+      if (node) {
+        return node.hasMarkup(type, attrs);
+      }
+
+      return to <= $from.end() && $from.parent.hasMarkup(type, attrs);
+    }
   }
 
   //this doesn't currently work but hopefully will soon
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d3184612c..7419b3a60 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -14,6 +14,7 @@ import { Plugin } from 'prosemirror-state'
 import { Decoration, DecorationSet } from 'prosemirror-view'
 import { TooltipTextMenu } from "../../util/TooltipTextMenu"
 import { ContextMenu } from "../../views/ContextMenu";
+import { inpRules } from "../../util/RichTextRules";
 const { buildMenuItems } = require("prosemirror-example-setup");
 const { menuBar } = require("prosemirror-menu");
 
@@ -62,6 +63,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
         let state: EditorState;
         const config = {
             schema,
+            inpRules, //these currently don't do anything, but could eventually be helpful
             plugins: [
                 history(),
                 keymap({ "Mod-z": undo, "Mod-y": redo }),
-- 
cgit v1.2.3-70-g09d2


From 9e55d38acc7a6ef1477a81068c5b201f9b13a2e8 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Mon, 18 Mar 2019 16:13:21 -0400
Subject: Got rid of some SetOnPrototype

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

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

diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index ad6bbd476..eb2172d03 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -40,7 +40,7 @@ export class InkingControl extends React.Component {
         if (SelectionManager.SelectedDocuments().length == 1) {
             var sdoc = SelectionManager.SelectedDocuments()[0];
             if (sdoc.props.ContainingCollectionView && sdoc.props.ContainingCollectionView) {
-                sdoc.props.Document.SetOnPrototype(KeyStore.BackgroundColor, new TextField(color.hex));
+                sdoc.props.Document.SetDataOnPrototype(KeyStore.BackgroundColor, color.hex, TextField);
             }
         }
     }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 4bd5726f4..ba9bd9566 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -56,7 +56,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             const { doc, fieldKey } = this.props;
-            doc.SetOnPrototype(fieldKey, new RichTextField(JSON.stringify(state.toJSON())))
+            doc.SetDataOnPrototype(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
             // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 356991c6100a44ef45b4574b43c815383d9be751 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 23 Mar 2019 00:22:52 -0400
Subject: Various fixes for the demo

---
 src/client/documents/Documents.ts                  | 17 ++++++---
 src/client/util/Scripting.ts                       |  8 +++--
 src/client/util/type_decls.d                       |  3 ++
 .../views/collections/CollectionFreeFormView.tsx   |  5 +++
 .../views/collections/CollectionSchemaView.tsx     | 42 ++++++++++++++++++----
 .../views/collections/CollectionViewBase.tsx       | 39 ++++++++++++++------
 src/client/views/nodes/DocumentView.tsx            |  7 ++++
 src/client/views/nodes/FieldView.tsx               | 18 +++++++++-
 src/client/views/nodes/FormattedTextBox.tsx        |  2 ++
 9 files changed, 117 insertions(+), 24 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 96a7332aa..a2444db06 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1,6 +1,6 @@
 import { AudioField } from "../../fields/AudioField";
 import { Document } from "../../fields/Document";
-import { Field } from "../../fields/Field";
+import { Field, FieldWaiting } from "../../fields/Field";
 import { HtmlField } from "../../fields/HtmlField";
 import { ImageField } from "../../fields/ImageField";
 import { InkField, StrokeData } from "../../fields/InkField";
@@ -23,6 +23,7 @@ import { PDFBox } from "../views/nodes/PDFBox";
 import { VideoBox } from "../views/nodes/VideoBox";
 import { WebBox } from "../views/nodes/WebBox";
 import { HistogramBox } from "../views/nodes/HistogramBox";
+import { FieldView } from "../views/nodes/FieldView";
 
 export interface DocumentOptions {
     x?: number;
@@ -112,7 +113,7 @@ export namespace Documents {
     function GetImagePrototype(): Document {
         if (!imageProto) {
             imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"),
-                { x: 0, y: 0, nativeWidth: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] });
+                { x: 0, y: 0, nativeWidth: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
             imageProto.SetText(KeyStore.BackgroundLayout, ImageBox.LayoutString());
         }
         return imageProto;
@@ -155,7 +156,7 @@ export namespace Documents {
     function GetVideoPrototype(): Document {
         if (!videoProto) {
             videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("AnnotationsKey"),
-                { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] });
+                { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] });
             videoProto.SetNumber(KeyStore.CurPage, 0);
             videoProto.SetText(KeyStore.BackgroundLayout, VideoBox.LayoutString());
         }
@@ -218,6 +219,14 @@ export namespace Documents {
         return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options)
     }
 
+    export function CaptionDocument(doc: Document) {
+        const captionDoc = doc.CreateAlias();
+        captionDoc.SetText(KeyStore.OverlayLayout, FixedCaption());
+        captionDoc.SetNumber(KeyStore.Width, doc.GetNumber(KeyStore.Width, 0));
+        captionDoc.SetNumber(KeyStore.Height, doc.GetNumber(KeyStore.Height, 0));
+        return captionDoc;
+    }
+
     // example of custom display string for an image that shows a caption.
     function EmbeddedCaption() {
         return `<div style="height:100%">
@@ -228,7 +237,7 @@ export namespace Documents {
             + FormattedTextBox.LayoutString("CaptionKey") +
             `</div> 
         </div>` };
-    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") +
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 4cf98472f..4e97b9401 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -15,6 +15,8 @@ import { ListField } from "../../fields/ListField";
 
 // @ts-ignore
 import * as typescriptlib from '!!raw-loader!./type_decls.d'
+import { Documents } from "../documents/Documents";
+import { Key } from "../../fields/Key";
 
 
 export interface ExecutableScript {
@@ -28,9 +30,9 @@ function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [
 
     let func: () => Opt<Field>;
     if (compiled && script) {
-        let fieldTypes = [Document, NumberField, TextField, ImageField, RichTextField, ListField];
-        let paramNames = ["KeyStore", ...fieldTypes.map(fn => fn.name)];
-        let params: any[] = [KeyStore, ...fieldTypes]
+        let fieldTypes = [Document, NumberField, TextField, ImageField, RichTextField, ListField, Key];
+        let paramNames = ["KeyStore", "Documents", ...fieldTypes.map(fn => fn.name)];
+        let params: any[] = [KeyStore, Documents, ...fieldTypes]
         for (let prop in scope) {
             if (prop === "this") {
                 continue;
diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d
index dcf79285d..4f69053b1 100644
--- a/src/client/util/type_decls.d
+++ b/src/client/util/type_decls.d
@@ -174,6 +174,7 @@ declare class ListField<T> extends BasicField<T[]>{
     Copy(): Field;
 }
 declare class Key extends Field {
+    constructor(name:string);
     Name: string;
     TrySetValue(value: any): boolean;
     GetValue(): any;
@@ -220,3 +221,5 @@ declare const KeyStore: {
 
 // @ts-ignore
 declare const console: any;
+
+declare const Documents: any;
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index da9f7b392..8f7b4cfe7 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -83,6 +83,10 @@ export class CollectionFreeFormView extends CollectionViewBase {
             const [x, y] = this.getTransform().transformPoint(screenX, screenY);
             de.data.droppedDocument.SetNumber(KeyStore.X, x);
             de.data.droppedDocument.SetNumber(KeyStore.Y, y);
+            if (!de.data.droppedDocument.GetNumber(KeyStore.Width, 0)) {
+                de.data.droppedDocument.SetNumber(KeyStore.Width, 300);
+                de.data.droppedDocument.SetNumber(KeyStore.Height, 300);
+            }
             this.bringToFront(de.data.droppedDocument);
         }
     }
@@ -259,6 +263,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         const lvalue = this.props.Document.GetT<ListField<Document>>(this.props.fieldKey, ListField);
         if (lvalue && lvalue != FieldWaiting) {
             return lvalue.Data.map(doc => {
+                if (!doc) return null;
                 var page = doc.GetNumber(KeyStore.Page, 0);
                 return (page != curPage && page != 0) ? (null) :
                     (<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 8e0a38f05..7dd364449 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,6 +1,6 @@
 import React = require("react")
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCog } from '@fortawesome/free-solid-svg-icons';
+import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
@@ -8,7 +8,7 @@ import Measure from "react-measure";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
 import "react-table/react-table.css";
 import { Document } from "../../../fields/Document";
-import { Field, Opt } from "../../../fields/Field";
+import { Field, Opt, FieldWaiting } from "../../../fields/Field";
 import { Key } from "../../../fields/Key";
 import { KeyStore } from "../../../fields/KeyStore";
 import { ListField } from "../../../fields/ListField";
@@ -24,6 +24,7 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
 import { CollectionView, COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { CollectionViewBase } from "./CollectionViewBase";
+import { TextField } from "../../../fields/TextField";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -104,11 +105,11 @@ export class CollectionSchemaView extends CollectionViewBase {
             return false;
         }
         return (
-            <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "36px" }} key={props.doc.Id} ref={reference}>
+            <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "56px" }} key={props.doc.Id} ref={reference}>
                 <EditableView
                     display={"inline"}
                     contents={contents}
-                    height={36}
+                    height={56}
                     GetValue={() => {
                         let field = props.doc.Get(props.fieldKey);
                         if (field && field instanceof Field) {
@@ -249,23 +250,48 @@ export class CollectionSchemaView extends CollectionViewBase {
         }
     }
 
+    @action
+    addColumn = () => {
+        this.columns.push(new Key(this.newKeyName));
+        this.newKeyName = "";
+    }
+
+    @observable
+    newKeyName: string = "";
+
+    @action
+    newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+        this.newKeyName = e.currentTarget.value;
+    }
+
     @observable _optionsActivated: number = 0;
     @action
     OptionsMenuDown = (e: React.PointerEvent) => {
         this._optionsActivated++;
     }
+
+    @observable previewScript: string = "this";
+    @action
+    onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+        this.previewScript = e.currentTarget.value;
+    }
+
     render() {
         library.add(faCog);
+        library.add(faPlus);
         const columns = this.columns;
         const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
         const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
         //all the keys/columns that will be displayed in the schema
         const allKeys = this.findAllDocumentKeys;
+        let doc: any = selected ? selected.Get(new Key(this.previewScript)) : undefined;
+
+        // let doc = CompileScript(this.previewScript, { this: selected }, true)();
         let content = this._selectedIndex == -1 || !selected ? (null) : (
             <Measure onResize={this.setScaling}>
                 {({ measureRef }) =>
                     <div className="collectionSchemaView-content" ref={measureRef}>
-                        <DocumentView Document={selected}
+                        {doc instanceof Document ? <DocumentView Document={doc}
                             AddDocument={this.props.addDocument} RemoveDocument={this.props.removeDocument}
                             isTopMost={false}
                             SelectOnLoad={false}
@@ -275,7 +301,9 @@ export class CollectionSchemaView extends CollectionViewBase {
                             PanelHeight={this.getPanelHeight}
                             ContainingCollectionView={this.props.CollectionView}
                             focus={this.focusDocument}
-                        />
+                        /> : null}
+                        <input value={this.previewScript} onChange={this.onPreviewScriptChange}
+                            style={{ position: 'absolute', bottom: '0px' }} />
                     </div>
                 }
             </Measure>
@@ -297,6 +325,8 @@ export class CollectionSchemaView extends CollectionViewBase {
                             return (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />)
                         })}
                     </ul>
+                    <input value={this.newKeyName} onChange={this.newKeyChange} />
+                    <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
                 </div>
             </div>
             }>
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index f33007196..7d903899d 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -17,6 +17,7 @@ import { NumberField } from "../../../fields/NumberField";
 import { DocumentManager } from "../../util/DocumentManager";
 import request = require("request");
 import { ServerUtils } from "../../../server/ServerUtil";
+import { Server } from "../../Server";
 
 export interface CollectionViewProps {
     fieldKey: Key;
@@ -59,17 +60,20 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         let email = CurrentUserUtils.email;
         if (id && email) {
             let textInfo: [string, string] = [id, email];
-            doc.GetOrCreateAsync<ListField<CursorEntry>>(KeyStore.Cursors, ListField, field => {
-                let cursors = field.Data;
-                if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.Data[0][0] === id)) > -1) {
-                    cursors[ind].Data[1] = position;
-                } else {
-                    let entry = new TupleField<[string, string], [number, number]>([textInfo, position]);
-                    cursors.push(entry);
+            doc.GetTAsync(KeyStore.Prototype, Document).then(proto => {
+                if (!proto) {
+                    return;
                 }
+                proto.GetOrCreateAsync<ListField<CursorEntry>>(KeyStore.Cursors, ListField, action((field: ListField<CursorEntry>) => {
+                    let cursors = field.Data;
+                    if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.Data[0][0] === id)) > -1) {
+                        cursors[ind].Data[1] = position;
+                    } else {
+                        let entry = new TupleField<[string, string], [number, number]>([textInfo, position]);
+                        cursors.push(entry);
+                    }
+                }))
             })
-
-
         }
     }
 
@@ -111,6 +115,21 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             ctor = Documents.PdfDocument;
         }
         if (type.indexOf("html") !== -1) {
+            if (path.includes('localhost')) {
+                let s = path.split('/');
+                let id = s[s.length - 1];
+                Server.GetField(id).then(field => {
+                    if (field instanceof Document) {
+                        let alias = field.CreateAlias();
+                        alias.SetNumber(KeyStore.X, options.x || 0);
+                        alias.SetNumber(KeyStore.Y, options.y || 0);
+                        alias.SetNumber(KeyStore.Width, options.width || 300);
+                        alias.SetNumber(KeyStore.Height, options.height || options.width || 300);
+                        this.props.addDocument(alias, false);
+                    }
+                })
+                return undefined;
+            }
             ctor = Documents.WebDocument;
             options = { height: options.width, ...options, };
         }
@@ -130,7 +149,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
         e.stopPropagation()
         e.preventDefault()
 
-        if (html && html.indexOf("<img") != 0) {
+        if (html && html.indexOf("<img") != 0 && !html.startsWith("<a")) {
             console.log("not good");
             let htmlDoc = Documents.HtmlDocument(html, { ...options, width: 300, height: 300 });
             htmlDoc.SetText(KeyStore.DocumentText, text);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cfe67c8fe..55aa1ccab 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -18,6 +18,7 @@ import { ContextMenu } from "../ContextMenu";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import React = require("react");
+import { ServerUtils } from "../../../server/ServerUtil";
 
 
 export interface DocumentViewProps {
@@ -283,6 +284,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         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(ServerUtils.prepend("/doc/" + this.props.Document.Id));
+            }
+        });
         ContextMenu.Instance.addItem({
             description: "Copy ID",
             event: () => {
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index f6343c631..4e83ec7b9 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -16,6 +16,9 @@ import { VideoBox } from "./VideoBox";
 import { AudioBox } from "./AudioBox";
 import { AudioField } from "../../../fields/AudioField";
 import { ListField } from "../../../fields/ListField";
+import { DocumentContentsView } from "./DocumentContentsView";
+import { Transform } from "../../util/Transform";
+import { KeyStore } from "../../../fields/KeyStore";
 
 
 //
@@ -65,7 +68,20 @@ export class FieldView extends React.Component<FieldViewProps> {
             return <AudioBox {...this.props} />
         }
         else if (field instanceof Document) {
-            return <div>{field.Title}</div>
+            return (<DocumentContentsView Document={field}
+                AddDocument={undefined}
+                RemoveDocument={undefined}
+                ScreenToLocalTransform={() => Transform.Identity}
+                ContentScaling={() => 1}
+                PanelWidth={() => 100}
+                PanelHeight={() => 100}
+                isTopMost={true}
+                SelectOnLoad={false}
+                focus={() => { }}
+                isSelected={() => false}
+                select={() => false}
+                layoutKey={KeyStore.Layout}
+                ContainingCollectionView={undefined} />)
         }
         else if (field instanceof ListField) {
             return (<div>
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index ba9bd9566..30fa1342e 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -167,6 +167,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             onKeyPress={this.onKeyPress}
             onPointerDown={this.onPointerDown}
             onContextMenu={this.specificContextMenu}
+            // tfs: do we need this event handler
+            onKeyDown={this.onKeyPress}
             onWheel={this.onPointerWheel}
             ref={this._ref} />)
     }
-- 
cgit v1.2.3-70-g09d2


From 970ecdb7158340cec2ea9e9a381d86afa8a59430 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 26 Mar 2019 00:02:30 -0400
Subject: tried to fix keyboard event issue when editing a text note in an
 embedded free form collection.

---
 src/client/views/collections/PreviewCursor.tsx | 9 ++++++---
 src/client/views/nodes/FormattedTextBox.tsx    | 6 ++++--
 2 files changed, 10 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/PreviewCursor.tsx b/src/client/views/collections/PreviewCursor.tsx
index cbf36cf9e..5d621f321 100644
--- a/src/client/views/collections/PreviewCursor.tsx
+++ b/src/client/views/collections/PreviewCursor.tsx
@@ -37,13 +37,13 @@ export class PreviewCursor extends React.Component<PreviewCursorProps>  {
 
     @action
     cleanupInteractions = () => {
-        document.removeEventListener("keypress", this.onKeyPress, true);
+        document.removeEventListener("keypress", this.onKeyPress, false);
     }
 
     @action
     onCursorPlaced = (visible: boolean, downX: number, downY: number): void => {
         if (visible) {
-            document.addEventListener("keypress", this.onKeyPress, true);
+            document.addEventListener("keypress", this.onKeyPress, false);
             this._lastX = downX;
             this._lastY = downY;
         } else
@@ -52,8 +52,11 @@ export class PreviewCursor extends React.Component<PreviewCursorProps>  {
 
     @action
     onKeyPress = (e: KeyboardEvent) => {
+        // Mixing events between React and Native is finicky.  In FormattedTextBox, we set the
+        // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore
+        // the keyPress here.
         //if not these keys, make a textbox if preview cursor is active!
-        if (!e.ctrlKey && !e.altKey && !e.defaultPrevented) {
+        if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
             //make textbox and add it to this collection
             let [x, y] = this.props.getTransform().transformPoint(this._lastX, this._lastY);
             let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "new" });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 30fa1342e..512ad7d70 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -158,17 +158,19 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
             }
         })
     }
-
     onKeyPress(e: React.KeyboardEvent) {
         e.stopPropagation();
+        // stop propagation doesn't seem to stop propagation of native keyboard events.
+        // so we set a flag on the native event that marks that the event's been handled.
+        // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
     }
     render() {
         return (<div className="formattedTextBox-cont"
+            onKeyDown={this.onKeyPress}
             onKeyPress={this.onKeyPress}
             onPointerDown={this.onPointerDown}
             onContextMenu={this.specificContextMenu}
             // tfs: do we need this event handler
-            onKeyDown={this.onKeyPress}
             onWheel={this.onPointerWheel}
             ref={this._ref} />)
     }
-- 
cgit v1.2.3-70-g09d2

