From a37faf30652c6c593923198ad34e54377e670caf Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 5 Jun 2019 08:09:10 -0400
Subject: fixed full screen text bug.  cleaned up imports

---
 src/client/views/collections/CollectionBaseView.tsx | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 734669893..9350dc974 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -1,14 +1,14 @@
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { ContextMenu } from '../ContextMenu';
-import { FieldViewProps } from '../nodes/FieldView';
-import { Cast, FieldValue, PromiseValue, NumCast } from '../../../new_fields/Types';
-import { Doc, FieldResult, Opt, DocListCast } from '../../../new_fields/Doc';
-import { listSpec } from '../../../new_fields/Schema';
+import { Doc, DocListCast, Opt } from '../../../new_fields/Doc';
+import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
+import { listSpec } from '../../../new_fields/Schema';
+import { Cast, FieldValue, NumCast, PromiseValue } from '../../../new_fields/Types';
 import { SelectionManager } from '../../util/SelectionManager';
-import { Id } from '../../../new_fields/FieldSymbols';
+import { ContextMenu } from '../ContextMenu';
+import { FieldViewProps } from '../nodes/FieldView';
 
 export enum CollectionViewType {
     Invalid,
-- 
cgit v1.2.3-70-g09d2


From 1087133d71ef2ac7df6976c61685167ed0fe71d9 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 5 Jun 2019 14:09:40 -0400
Subject: cleaned up selections somewhat so that PDFs don't flicker when
 manipulating annotations.

---
 src/client/util/SelectionManager.ts                | 24 +++++++++-------------
 src/client/views/DocumentDecorations.tsx           |  1 -
 .../views/collections/CollectionBaseView.tsx       |  2 +-
 src/client/views/collections/CollectionPDFView.tsx |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  1 -
 .../collections/collectionFreeForm/MarqueeView.tsx |  1 -
 src/client/views/nodes/PDFBox.tsx                  | 16 +++++++--------
 7 files changed, 20 insertions(+), 27 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 8c92c2023..5311841e1 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -21,6 +21,13 @@ export namespace SelectionManager {
                 doc.props.whenActiveChanged(true);
             }
         }
+        @action
+        DeSelectDoc(doc: DocumentView): void {
+            if (manager.SelectedDocuments.indexOf(doc) !== -1) {
+                manager.SelectedDocuments.splice(manager.SelectedDocuments.indexOf(doc), 1);
+                doc.props.whenActiveChanged(false);
+            }
+        }
 
         @action
         DeselectAll(): void {
@@ -28,16 +35,6 @@ export namespace SelectionManager {
             manager.SelectedDocuments = [];
             FormattedTextBox.InputBoxOverlay = undefined;
         }
-        @action
-        ReselectAll() {
-            let sdocs = manager.SelectedDocuments.map(d => d);
-            manager.SelectedDocuments = [];
-            return sdocs;
-        }
-        @action
-        ReselectAll2(sdocs: DocumentView[]) {
-            sdocs.map(s => SelectionManager.SelectDoc(s, true));
-        }
     }
 
     const manager = new Manager();
@@ -49,6 +46,9 @@ export namespace SelectionManager {
     export function IsSelected(doc: DocumentView): boolean {
         return manager.SelectedDocuments.indexOf(doc) !== -1;
     }
+    export function DeSelectDoc(doc: DocumentView): void {
+        manager.DeSelectDoc(doc);
+    }
 
     export function DeselectAll(except?: Doc): void {
         let found: DocumentView | undefined = undefined;
@@ -62,10 +62,6 @@ export namespace SelectionManager {
         if (found) manager.SelectDoc(found, false);
     }
 
-    export function ReselectAll() {
-        let sdocs = manager.ReselectAll();
-        setTimeout(() => manager.ReselectAll2(sdocs), 0);
-    }
     export function SelectedDocuments(): Array<DocumentView> {
         return manager.SelectedDocuments;
     }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 37895516a..cdd537760 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -463,7 +463,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         e.stopPropagation();
         this._resizing = "";
         this.Interacting = false;
-        SelectionManager.ReselectAll();
         if (e.button === 0) {
             e.preventDefault();
             this._isPointerDown = false;
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 9350dc974..cb92464e5 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -158,7 +158,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     @action.bound
     moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean {
-        if (this.props.Document === targetCollection) {
+        if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
             return true;
         }
         if (this.removeDocument(doc)) {
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 5e51437a4..25c1535b3 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -70,7 +70,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
         return (
             <>
                 <CollectionFreeFormView {...props} CollectionView={this} />
-                {this.props.isSelected() ? this.uIButtons : (null)}
+                {this.props.active() ? this.uIButtons : (null)}
             </>
         );
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 634b4dfa0..582f93c2e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -104,7 +104,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     }
                     this.bringToFront(d);
                 });
-                SelectionManager.ReselectAll();
             }
             return true;
         }
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 9ec941eff..81ca4c29a 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -325,7 +325,6 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             }
             else {
                 this.props.addDocument(newCollection, false);
-                SelectionManager.DeselectAll();
                 this.props.selectDocuments([newCollection]);
             }
             this.cleanupInteractions(false);
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index aa29a7170..855c744e6 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -68,20 +68,21 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
 
     @observable private _currAnno: any = [];
     @observable private _interactive: boolean = false;
-    @observable private _loaded: boolean = false;
 
     @computed private get curPage() { return NumCast(this.Document.curPage, 1); }
     @computed private get thumbnailPage() { return NumCast(this.props.Document.thumbnailPage, -1); }
 
     componentDidMount() {
-        let wasSelected = this.props.isSelected();
+        let wasSelected = this.props.active();
         this._reactionDisposer = reaction(
-            () => [this.props.isSelected(), this.curPage],
+            () => [this.props.active(), this.curPage],
             () => {
-                if (this.curPage > 0 && !this.props.isTopMost && this.curPage !== this.thumbnailPage && wasSelected && !this.props.isSelected()) {
-                    this.saveThumbnail();
-                }
-                wasSelected = this._interactive = this.props.isSelected();
+                setTimeout(action(() => {  // this forces the active() check to happen after all changes in a transaction have occurred.
+                    if (this.curPage > 0 && !this.props.isTopMost && this.curPage !== this.thumbnailPage && wasSelected && !this.props.active()) {
+                        this.saveThumbnail();
+                    }
+                    wasSelected = this._interactive = this.props.active();
+                }), 0);
             },
             { fireImmediately: true });
 
@@ -276,7 +277,6 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
         if (this._perPageInfo.length === 0) { //Makes sure it only runs once
             this._perPageInfo = [...Array(page._transport.numPages)];
         }
-        this._loaded = true;
     }
 
     @action
-- 
cgit v1.2.3-70-g09d2


From ac63044fad5968cca83108f6dd3015ef657840bd Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 7 Jun 2019 10:21:55 -0400
Subject: fixed some pinterest layout issues.

---
 .../views/collections/CollectionBaseView.scss      | 11 ++++++++
 .../views/collections/CollectionBaseView.tsx       |  4 +--
 .../views/collections/CollectionStackingView.scss  | 20 ++++---------
 .../views/collections/CollectionStackingView.tsx   | 33 +++++++++++-----------
 src/client/views/nodes/DocumentView.tsx            |  3 +-
 5 files changed, 36 insertions(+), 35 deletions(-)
 create mode 100644 src/client/views/collections/CollectionBaseView.scss

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/collections/CollectionBaseView.scss b/src/client/views/collections/CollectionBaseView.scss
new file mode 100644
index 000000000..1f5acb96a
--- /dev/null
+++ b/src/client/views/collections/CollectionBaseView.scss
@@ -0,0 +1,11 @@
+@import "../globalCssVariables";
+#collectionBaseView {
+    border-width: 0;
+    box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
+    border-color: $light-color-secondary;
+    border-style: solid;
+    border-radius: 0 0 $border-radius $border-radius;
+    box-sizing: border-box;
+    border-radius: inherit;
+    pointer-events: all;
+}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index cb92464e5..ddec587a9 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -9,6 +9,7 @@ import { Cast, FieldValue, NumCast, PromiseValue } from '../../../new_fields/Typ
 import { SelectionManager } from '../../util/SelectionManager';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
+import './CollectionBaseView.scss';
 
 export enum CollectionViewType {
     Invalid,
@@ -178,8 +179,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         };
         const viewtype = this.collectionViewType;
         return (
-            <div className={this.props.className || "collectionView-cont"}
-                style={{ borderRadius: "inherit", pointerEvents: "all" }}
+            <div id="collectionBaseView" className={this.props.className || "collectionView-cont"}
                 onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
                 {viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
             </div>
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 4d84aaaa9..af194aec9 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -1,19 +1,6 @@
 @import "../globalCssVariables";
-
 .collectionStackingView {
-    top: 0;
-    left: 0;
-    display: flex;
-    flex-direction: column;
-    width: 100%;
-    position: absolute;
     overflow-y: auto;
-    border-width: 0;
-    box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
-    border-color: $light-color-secondary;
-    border-style: solid;
-    border-radius: 0 0 $border-radius $border-radius;
-    box-sizing: border-box;
 
     .collectionStackingView-docView-container {
         width: 45%;
@@ -33,9 +20,12 @@
         width:100%;
         height:100%;
         position: absolute;
-    }
-    .collectionStackingView-masonryGrid {
         display:grid;
+        top: 0;
+        left: 0;
+        width: 100%;
+        position: absolute;
+        
     }
 
     .collectionStackingView-description {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index eeae498a6..b8eb4ac84 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -32,11 +32,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return (nw && nh) ? wid * aspect : d[HeightSym]();
     }
     componentDidMount() {
-        this._heightDisposer = reaction(() => [this.yMargin, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])],
+        this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])],
             () => {
                 if (this.singleColumn) {
-                    this.props.Document.height = this.childDocs.filter(d => !d.isMinimized).reduce((height, d) =>
-                        height + this.singleColDocHeight(d) + this.yMargin
+                    let children = this.childDocs.filter(d => !d.isMinimized);
+                    this.props.Document.height = children.reduce((height, d, i) =>
+                        height + this.singleColDocHeight(d) + (i === children.length - 1 ? this.yMargin : this.gridGap)
                         , this.yMargin);
                 }
             }, { fireImmediately: true });
@@ -78,7 +79,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
 
     @computed
     get singleColumnChildren() {
-        return this.childDocs.filter(d => !d.isMinimized).map((d, i) => {
+        let children = this.childDocs.filter(d => !d.isMinimized);
+        return children.map((d, i) => {
             let dref = React.createRef<HTMLDivElement>();
             let script = undefined;
             let colWidth = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth;
@@ -87,7 +89,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             return <div className="collectionStackingView-masonryDoc"
                 key={d[Id]}
                 ref={dref}
-                style={{ marginTop: `${i ? this.yMargin : 0}px`, width: colWidth(), height: rowHeight(), marginLeft: "auto", marginRight: "auto" }} >
+                style={{ width: colWidth(), height: rowHeight(), marginLeft: "auto", marginRight: "auto" }} >
                 <CollectionSchemaPreview
                     Document={d}
                     width={colWidth}
@@ -107,10 +109,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
     @computed
     get children() {
+        trace();
         return this.childDocs.filter(d => !d.isMinimized).map((d, i) => {
             let dref = React.createRef<HTMLDivElement>();
             let dxf = () => this.getDocTransform(d, dref.current!);
-            let colSpan = 1;//Math.ceil((this.columnWidth + this.gridGap) / (this._gridSize + this.gridGap));
             let rowSpan = Math.ceil((this.columnWidth / d[WidthSym]() * d[HeightSym]() + this.gridGap) / (this._gridSize + this.gridGap));
             let childFocus = (doc: Doc) => {
                 doc.libraryBrush = true;
@@ -124,7 +126,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                     height: NumCast(d.nativeHeight, d[HeightSym]()),
                     transformOrigin: "top left",
                     gridRowEnd: `span ${rowSpan}`,
-                    gridColumnEnd: `span ${colSpan}`,
+                    gridColumnEnd: `span 1`,
                     transform: `scale(${this.columnWidth / NumCast(d.nativeWidth, d[WidthSym]())}, ${this.columnWidth / NumCast(d.nativeWidth, d[WidthSym]())})`
                 }} >
                 <DocumentView key={d[Id]} Document={d}
@@ -157,19 +159,19 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         }
     }
     render() {
-        let cols = this.singleColumn ? 1 : Math.min(this.childDocs.filter(d => !d.isMinimized).length,
-            Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + 2 * this.gridGap)));
+        let cols = this.singleColumn ? 1 : Math.max(1, Math.min(this.childDocs.filter(d => !d.isMinimized).length,
+            Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
         let templatecols = "";
         for (let i = 0; i < cols; i++) templatecols += `${this.columnWidth}px `;
         return (
-            <div className="collectionStackingView" style={{ height: "100%" }}
-                onContextMenu={this.onContextMenu}
-                ref={this.createRef} onWheel={(e: React.WheelEvent) => e.stopPropagation()}>
+            <div className="collectionStackingView">
                 <div className={`collectionStackingView-masonry${this.singleColumn ? "Single" : "Grid"}`}
+                    onContextMenu={this.onContextMenu}
+                    ref={this.createRef} onWheel={(e: React.WheelEvent) => e.stopPropagation()}
                     style={{
-                        padding: `${this.yMargin}px ${this.xMargin}px 0px ${this.xMargin}px`,
+                        padding: this.singleColumn ? `${this.yMargin}px ${this.xMargin}px ${this.yMargin}px ${this.xMargin}px` : `${this.yMargin}px ${this.xMargin}px`,
                         margin: "auto",
-                        width: this.singleColumn ? undefined : `${cols * (this.columnWidth + this.gridGap)}px`,
+                        width: this.singleColumn ? undefined : `${cols * (this.columnWidth + this.gridGap) + 2 * this.xMargin - this.gridGap}px`,
                         height: "100%",
                         position: "relative",
                         gridGap: this.gridGap,
@@ -178,8 +180,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                     }}
                 >
                     {this.singleColumn ? this.singleColumnChildren : this.children}
-                </div>
-            </div>
+                </div></div>
         );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 36a5358f0..ff2b9842f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,6 +1,6 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash, faConciergeBell, faFolder, faMapPin, faLink, faFingerprint, faCrosshairs, faDesktop } from '@fortawesome/free-solid-svg-icons';
-import { action, computed, IReactionDisposer, reaction } from "mobx";
+import { action, computed, IReactionDisposer, reaction, trace } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc";
 import { List } from "../../../new_fields/List";
@@ -439,7 +439,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         var scaling = this.props.ContentScaling();
         var nativeHeight = this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
         var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%";
-
         return (
             <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
-- 
cgit v1.2.3-70-g09d2


From a2742057084ac0c78ed5f360b1078b5b267eff1f Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 9 Jun 2019 20:32:06 -0400
Subject: added a link context for link targets.

---
 src/client/documents/Documents.ts                  | 30 ++++++++++------------
 src/client/util/DocumentManager.ts                 | 29 ++++++++++++++++-----
 src/client/views/DocumentDecorations.tsx           |  3 +--
 .../views/collections/CollectionBaseView.tsx       |  6 ++---
 .../views/collections/CollectionStackingView.tsx   |  2 +-
 src/client/views/nodes/DocumentView.tsx            | 15 ++++++++---
 6 files changed, 52 insertions(+), 33 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index f0fb0c3ed..2ae127e21 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -69,31 +69,27 @@ export interface DocumentOptions {
 const delegateKeys = ["x", "y", "width", "height", "panX", "panY"];
 
 export namespace DocUtils {
-    export function MakeLink(source: Doc, target: Doc) {
+    export function MakeLink(source: Doc, target: Doc, targetContext?: Doc) {
         let protoSrc = source.proto ? source.proto : source;
         let protoTarg = target.proto ? target.proto : target;
         UndoManager.RunInBatch(() => {
             let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 });
-            //let linkDoc = new Doc;
-            linkDoc.proto!.title = "-link name-";
-            linkDoc.proto!.linkDescription = "";
-            linkDoc.proto!.linkTags = "Default";
+            let linkDocProto = Doc.GetProto(linkDoc);
+            linkDocProto.title = source.title + " to " + target.title;
+            linkDocProto.linkDescription = "";
+            linkDocProto.linkTags = "Default";
 
-            linkDoc.proto!.linkedTo = target;
-            linkDoc.proto!.linkedToPage = target.curPage;
-            linkDoc.proto!.linkedFrom = source;
-            linkDoc.proto!.linkedFromPage = source.curPage;
+            linkDocProto.linkedTo = target;
+            linkDocProto.linkedFrom = source;
+            linkDocProto.linkedToPage = target.curPage;
+            linkDocProto.linkedFromPage = source.curPage;
+            linkDocProto.linkedToContext = targetContext;
 
             let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc));
-            if (!linkedFrom) {
-                protoTarg.linkedFromDocs = linkedFrom = new List<Doc>();
-            }
-            linkedFrom.push(linkDoc);
-
             let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc));
-            if (!linkedTo) {
-                protoSrc.linkedToDocs = linkedTo = new List<Doc>();
-            }
+            !linkedFrom && (protoTarg.linkedFromDocs = linkedFrom = new List<Doc>());
+            !linkedTo && (protoSrc.linkedToDocs = linkedTo = new List<Doc>());
+            linkedFrom.push(linkDoc);
             linkedTo.push(linkDoc);
             return linkDoc;
         }, "make link");
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 65c4b9e4b..ff0c1560b 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -115,7 +115,7 @@ export class DocumentManager {
     }
 
     @undoBatch
-    public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number): Promise<void> => {
+    public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number, docContext?: Doc): Promise<void> => {
         let doc = Doc.GetProto(docDelegate);
         const contextDoc = await Cast(doc.annotationOn, Doc);
         if (contextDoc) {
@@ -123,6 +123,7 @@ export class DocumentManager {
             const curPage = NumCast(contextDoc.curPage, page);
             if (page !== curPage) contextDoc.curPage = page;
         }
+
         let docView: DocumentView | null;
         // using forceDockFunc as a flag for splitting linked to doc to the right...can change later if needed
         if (!forceDockFunc && (docView = DocumentManager.Instance.getDocumentView(doc))) {
@@ -131,18 +132,34 @@ export class DocumentManager {
             docView.props.focus(docView.props.Document);
         } else {
             if (!contextDoc) {
-                const actualDoc = Doc.MakeAlias(docDelegate);
-                actualDoc.libraryBrush = true;
-                if (linkPage !== undefined) actualDoc.curPage = linkPage;
-                (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc);
+                if (docContext) {
+                    let targetContextView: DocumentView | null;
+                    if (!forceDockFunc && docContext && (targetContextView = DocumentManager.Instance.getDocumentView(docContext))) {
+                        docContext.panTransformType = "Ease";
+                        targetContextView.props.focus(docDelegate);
+                    } else {
+                        (dockFunc || CollectionDockingView.Instance.AddRightSplit)(docContext);
+                        setTimeout(() => {
+                            this.jumpToDocument(docDelegate, forceDockFunc, dockFunc, linkPage);
+                        }, 10);
+                    }
+                } else {
+                    const actualDoc = Doc.MakeAlias(docDelegate);
+                    actualDoc.libraryBrush = true;
+                    if (linkPage !== undefined) actualDoc.curPage = linkPage;
+                    (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc);
+                }
             } else {
                 let contextView: DocumentView | null;
                 docDelegate.libraryBrush = true;
                 if (!forceDockFunc && (contextView = DocumentManager.Instance.getDocumentView(contextDoc))) {
                     contextDoc.panTransformType = "Ease";
-                    contextView.props.focus(contextDoc);
+                    contextView.props.focus(docDelegate);
                 } else {
                     (dockFunc || CollectionDockingView.Instance.AddRightSplit)(contextDoc);
+                    setTimeout(() => {
+                        this.jumpToDocument(docDelegate, forceDockFunc, dockFunc, linkPage);
+                    }, 10);
                 }
             }
         }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index f22fecb98..7260b00cf 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -432,7 +432,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
             if (rect.width !== 0 && (dX != 0 || dY != 0 || dW != 0 || dH != 0)) {
                 let doc = PositionDocument(element.props.Document);
-                let docHeightBefore = doc.height;
                 let nwidth = doc.nativeWidth || 0;
                 let nheight = doc.nativeHeight || 0;
                 let zoomBasis = NumCast(doc.zoomBasis, 1);
@@ -469,7 +468,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     }
                 } else {
                     doc.width = zoomBasis * actualdW;
-                    if (docHeightBefore === doc.height) doc.height = zoomBasis * actualdH;
+                    doc.height = zoomBasis * actualdH;
                 }
             }
         });
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index ddec587a9..d120c3a0c 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -101,9 +101,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
         let props = this.props;
         var curPage = NumCast(props.Document.curPage, -1);
-        Doc.SetOnPrototype(doc, "page", curPage);
+        Doc.GetProto(doc).page = curPage;
         if (curPage >= 0) {
-            Doc.SetOnPrototype(doc, "annotationOn", props.Document);
+            Doc.GetProto(doc).annotationOn = props.Document;
         }
         if (!this.createsCycle(doc, props.Document)) {
             //TODO This won't create the field if it doesn't already exist
@@ -141,7 +141,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
                 break;
             }
         }
-        PromiseValue(Cast(doc.annotationOn, Doc)).then((annotationOn) => {
+        PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn => {
             if (annotationOn === props.Document) {
                 doc.annotationOn = undefined;
             }
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 0a119a3b4..cad7cd50c 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -153,7 +153,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         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: "Toggle multi-column",
-                event: () => this.props.Document.singleColumn = !BoolCast(this.props.Document.singleColumn, false), icon: "file-pdf"
+                event: () => this.props.Document.singleColumn = !BoolCast(this.props.Document.singleColumn, true), icon: "file-pdf"
             });
         }
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 85b8a5596..2ac6d12bf 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -6,7 +6,7 @@ import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "..
 import { List } from "../../../new_fields/List";
 import { ObjectField } from "../../../new_fields/ObjectField";
 import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { BoolCast, Cast, FieldValue, StrCast, NumCast } from "../../../new_fields/Types";
+import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../../../new_fields/Types";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { emptyFunction, Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
@@ -261,12 +261,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                         linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : expandedDocs[0],
                         linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : expandedDocs[0]];
 
+                    let linkedFwdContextDocs = [
+                        linkedToDocs.length ? await (linkedToDocs[0].linkedToContext) as Doc : linkedFromDocs.length ? await PromiseValue(linkedFromDocs[0].linkedFromContext) as Doc : undefined,
+                        linkedFromDocs.length ? await (linkedFromDocs[0].linkedFromContext) as Doc : linkedToDocs.length ? await PromiseValue(linkedToDocs[0].linkedToContext) as Doc : undefined];
+
                     let linkedFwdPage = [
                         linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : undefined,
                         linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : undefined];
+
                     if (!linkedFwdDocs.some(l => l instanceof Promise)) {
                         let maxLocation = StrCast(linkedFwdDocs[altKey ? 1 : 0].maximizeLocation, "inTab");
-                        DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0]);
+                        DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0], linkedFwdContextDocs[altKey ? 1 : 0]);
                     }
                 }
             }
@@ -333,6 +338,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             let sourceDoc = de.data.linkSourceDocument;
             let destDoc = this.props.Document;
 
+            e.stopPropagation();
             if (de.mods === "AltKey") {
                 const protoDest = destDoc.proto;
                 const protoSrc = sourceDoc.proto;
@@ -343,10 +349,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 dst.nativeHeight = src.nativeHeight;
             }
             else {
-                DocUtils.MakeLink(sourceDoc, destDoc);
+                const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
+                const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView);
+                DocUtils.MakeLink(sourceDoc, destDoc, views.length ? views[0].props.Document : undefined);
                 de.data.droppedDocuments.push(destDoc);
             }
-            e.stopPropagation();
         }
     }
 
-- 
cgit v1.2.3-70-g09d2


From 06d5bb5c65da6f4a115ebf8118989115420bccef Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 11 Jun 2019 10:21:42 -0400
Subject: cleaned up some drop() code with text.  fixed linkview titling. 
 changed dragging to not deselect source collection.

---
 src/client/util/SelectionManager.ts                | 23 ++++++++++++++++------
 .../views/collections/CollectionBaseView.tsx       |  5 +++--
 .../CollectionFreeFormLinkView.tsx                 |  5 +++--
 src/client/views/nodes/FormattedTextBox.tsx        | 22 ---------------------
 4 files changed, 23 insertions(+), 32 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index ddad4b818..b26032b04 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -10,15 +10,23 @@ export namespace SelectionManager {
         @observable SelectedDocuments: Array<DocumentView> = [];
 
         @action
-        SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
+        SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
             // if doc is not in SelectedDocuments, add it
             if (!ctrlPressed) {
                 this.DeselectAll();
             }
 
-            if (manager.SelectedDocuments.indexOf(doc) === -1) {
-                manager.SelectedDocuments.push(doc);
-                doc.props.whenActiveChanged(true);
+            if (manager.SelectedDocuments.indexOf(docView) === -1) {
+                manager.SelectedDocuments.push(docView);
+                docView.props.whenActiveChanged(true);
+            }
+        }
+        @action
+        DeselectDoc(docView: DocumentView): void {
+            let ind = manager.SelectedDocuments.indexOf(docView);
+            if (ind !== -1) {
+                manager.SelectedDocuments.splice(ind, 1);
+                docView.props.whenActiveChanged(false);
             }
         }
         @action
@@ -31,8 +39,11 @@ export namespace SelectionManager {
 
     const manager = new Manager();
 
-    export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
-        manager.SelectDoc(doc, ctrlPressed);
+    export function DeselectDoc(docView: DocumentView): void {
+        manager.DeselectDoc(docView);
+    }
+    export function SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
+        manager.SelectDoc(docView, ctrlPressed);
     }
 
     export function IsSelected(doc: DocumentView): boolean {
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index d120c3a0c..5238ad114 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -10,6 +10,7 @@ import { SelectionManager } from '../../util/SelectionManager';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
 import './CollectionBaseView.scss';
+import { DocumentManager } from '../../util/DocumentManager';
 
 export enum CollectionViewType {
     Invalid,
@@ -129,7 +130,8 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     @action.bound
     removeDocument(doc: Doc): boolean {
-        SelectionManager.DeselectAll();
+        let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView)
+        docView && SelectionManager.DeselectDoc(docView);
         const props = this.props;
         //TODO This won't create the field if it doesn't already exist
         const value = Cast(props.Document[props.fieldKey], listSpec(Doc), []);
@@ -163,7 +165,6 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             return true;
         }
         if (this.removeDocument(doc)) {
-            SelectionManager.DeselectAll();
             return addDocument(doc);
         }
         return false;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index ca7c99f28..ba7e6cf9e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -44,8 +44,9 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
         let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / NumCast(b.zoomBasis, 1) / 2);
         let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / NumCast(b.zoomBasis, 1) / 2);
         let text = "";
-        this.props.LinkDocs.map(l => text += StrCast(l.title) + "(" + StrCast(l.linkDescription) + "), ");
-        text = text.substr(0, text.length - 2);
+        let first = this.props.LinkDocs[0];
+        if (this.props.LinkDocs.length === 1) text += first.title + (first.linkDescription ? "(" + StrCast(first.linkDescription) + ")" : "");
+        else text = "-multiple-";
         return (
             <>
                 <line key="linkLine" className="collectionfreeformlinkview-linkLine"
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 4325fd48c..2923fd378 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -75,7 +75,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     private _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
     private _lastState: any = undefined;
     private _applyingChange: boolean = false;
-    private _dropDisposer?: DragManager.DragDropDisposer;
     private _linkClicked = "";
     private _reactionDisposer: Opt<IReactionDisposer>;
     private _inputReactionDisposer: Opt<IReactionDisposer>;
@@ -136,25 +135,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         }
     }
 
-    @undoBatch
-    @action
-    drop = async (e: Event, de: DragManager.DropEvent) => {
-        if (de.data instanceof DragManager.LinkDragData) {
-            let sourceDoc = de.data.linkSourceDocument;
-            let destDoc = this.props.Document;
-
-            DocUtils.MakeLink(sourceDoc, destDoc);
-            de.data.droppedDocuments.push(destDoc);
-            e.stopPropagation();
-        }
-    }
-
     componentDidMount() {
-        if (this._ref.current) {
-            this._dropDisposer = DragManager.MakeDropTarget(this._ref.current, {
-                handlers: { drop: this.drop.bind(this) }
-            });
-        }
         const config = {
             schema,
             inpRules, //these currently don't do anything, but could eventually be helpful
@@ -250,9 +231,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         if (this._proxyReactionDisposer) {
             this._proxyReactionDisposer();
         }
-        if (this._dropDisposer) {
-            this._dropDisposer();
-        }
     }
 
     onPointerDown = (e: React.PointerEvent): void => {
-- 
cgit v1.2.3-70-g09d2


From 13e301dea2f537b67b338cc6a98d3f3b5a8e1f36 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 18 Jun 2019 20:58:32 -0400
Subject: Fixed linter errors

---
 src/client/northstar/dash-nodes/HistogramBox.tsx             |  3 +--
 src/client/util/DocumentManager.ts                           |  6 +++---
 src/client/util/DragManager.ts                               |  4 +++-
 src/client/util/RichTextSchema.tsx                           | 10 +++++-----
 src/client/util/TooltipTextMenu.tsx                          |  2 +-
 src/client/views/ContextMenu.tsx                             |  4 ++--
 src/client/views/DocumentDecorations.tsx                     |  2 +-
 src/client/views/MainOverlayTextBox.tsx                      |  2 +-
 src/client/views/MainView.tsx                                |  7 ++++---
 src/client/views/PresentationView.tsx                        |  4 ++--
 src/client/views/collections/CollectionBaseView.tsx          |  2 +-
 src/client/views/collections/CollectionDockingView.tsx       |  5 +++--
 src/client/views/collections/CollectionPDFView.tsx           |  2 +-
 src/client/views/collections/CollectionSchemaView.tsx        | 11 ++++++-----
 src/client/views/collections/CollectionStackingView.tsx      |  4 ++--
 src/client/views/collections/CollectionTreeView.tsx          | 10 +++++-----
 .../collectionFreeForm/CollectionFreeFormLinksView.tsx       |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx            |  2 +-
 .../views/collections/collectionFreeForm/MarqueeView.tsx     |  2 +-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx    |  2 +-
 src/client/views/nodes/DocumentView.tsx                      | 12 ++++++------
 src/client/views/nodes/FormattedTextBox.tsx                  |  2 +-
 src/client/views/nodes/ImageBox.tsx                          |  3 ++-
 src/client/views/pdf/PDFAnnotationLayer.tsx                  |  2 +-
 src/client/views/pdf/PDFMenu.tsx                             |  2 +-
 src/client/views/pdf/PDFViewer.tsx                           |  4 ++--
 src/server/index.ts                                          |  2 +-
 27 files changed, 59 insertions(+), 54 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index d7732ee86..a60eaea85 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -125,8 +125,7 @@ export class HistogramBox extends React.Component<FieldViewProps> {
                                 let mapped = brushingDocs.map((brush, i) => {
                                     brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length];
                                     let brushed = DocListCast(brush.brushingDocs);
-                                    if (!brushed.length)
-                                        return null;
+                                    if (!brushed.length) return null;
                                     return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] };
                                 });
                                 runInAction(() => this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped.filter(m => m) as { l: Doc, b: Doc }[]));
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ff0c1560b..862395d74 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -35,9 +35,9 @@ export class DocumentManager {
         let toReturn: DocumentView | null = null;
         let passes = preferredCollection ? [preferredCollection, undefined] : [undefined];
 
-        for (let i = 0; i < passes.length; i++) {
+        for (let pass of passes) {
             DocumentManager.Instance.DocumentViews.map(view => {
-                if (view.props.Document[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) {
+                if (view.props.Document[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) {
                     toReturn = view;
                     return;
                 }
@@ -45,7 +45,7 @@ export class DocumentManager {
             if (!toReturn) {
                 DocumentManager.Instance.DocumentViews.map(view => {
                     let doc = view.props.Document.proto;
-                    if (doc && doc[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) {
+                    if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) {
                         toReturn = view;
                     }
                 });
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 89566e777..c3c92daa5 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -282,11 +282,13 @@ export namespace DragManager {
             // }
             let set = dragElement.getElementsByTagName('*');
             if (dragElement.hasAttribute("style")) (dragElement as any).style.pointerEvents = "none";
-            for (let i = 0; i < set.length; i++)
+            // tslint:disable-next-line: prefer-for-of
+            for (let i = 0; i < set.length; i++) {
                 if (set[i].hasAttribute("style")) {
                     let s = set[i];
                     (s as any).style.pointerEvents = "none";
                 }
+            }
 
 
             dragDiv.appendChild(dragElement);
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index e1e595925..943cdb4d1 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -156,12 +156,12 @@ export const nodes: { [index: string]: NodeSpec } = {
                     title: dom.getAttribute("title"),
                     alt: dom.getAttribute("alt"),
                     width: Math.min(100, Number(dom.getAttribute("width"))),
-                }
+                };
             }
         }],
         toDOM(node) {
-            const attrs = { style: `width: ${node.attrs.width}` }
-            return ["video", { ...node.attrs, ...attrs }]
+            const attrs = { style: `width: ${node.attrs.width}` };
+            return ["video", { ...node.attrs, ...attrs }];
         }
     },
 
@@ -285,7 +285,7 @@ export const marks: { [index: string]: MarkSpec } = {
         toDOM() {
             return ['span', {
                 style: 'color: blue'
-            }]
+            }];
         }
     },
 
@@ -536,4 +536,4 @@ schema.nodeFromJSON = (json: any) => {
         node.attrs.oldtext = Slice.fromJSON(schema, node.attrs.oldtextslice);
     }
     return node;
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 0a61b7e7d..f2559db74 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -256,7 +256,7 @@ export class TooltipTextMenu {
             starButton.onclick = () => {
                 let state = this.view.state;
                 this.insertStar(state, this.view.dispatch);
-            }
+            };
 
             this.tooltip.appendChild(starButton);
         }
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index da374455e..eb1937683 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -1,8 +1,8 @@
 import React = require("react");
 import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem";
 import { observable, action } from "mobx";
-import { observer } from "mobx-react"
-import "./ContextMenu.scss"
+import { observer } from "mobx-react";
+import "./ContextMenu.scss";
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { faSearch, faCircle } from '@fortawesome/free-solid-svg-icons';
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ceca940b6..e60f8c86c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -466,7 +466,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         SelectionManager.SelectedDocuments().forEach(element => {
             const rect = element.ContentDiv ? element.ContentDiv.getBoundingClientRect() : new DOMRect();
 
-            if (rect.width !== 0 && (dX != 0 || dY != 0 || dW != 0 || dH != 0)) {
+            if (rect.width !== 0 && (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0)) {
                 let doc = PositionDocument(element.props.Document);
                 let nwidth = doc.nativeWidth || 0;
                 let nheight = doc.nativeHeight || 0;
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 0de880175..b4ad5f4d7 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -40,7 +40,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
                     this.TextDoc = box.props.Document;
                     let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined);
                     let xf = () => { box.props.ScreenToLocalTransform(); return new Transform(-sxf.translateX, -sxf.translateY, 1 / sxf.scale); };
-                    this.setTextDoc(box.props.fieldKey, box.CurrentDiv, xf, BoolCast(box.props.Document.autoHeight, false) || box.props.height === "min-content")
+                    this.setTextDoc(box.props.fieldKey, box.CurrentDiv, xf, BoolCast(box.props.Document.autoHeight, false) || box.props.height === "min-content");
                 }
                 else {
                     this.TextDoc = undefined;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index fd76cbbd3..7f979cd3b 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -237,10 +237,11 @@ export class MainView extends React.Component {
     }
 
     onColorClick = (e: React.MouseEvent) => {
-        let target = (e.nativeEvent! as any).path[0];
-        let parent = (e.nativeEvent! as any).path[1];
-        if (target.localName === "input" || parent.localName === "span")
+        let target = (e.nativeEvent as any).path[0];
+        let parent = (e.nativeEvent as any).path[1];
+        if (target.localName === "input" || parent.localName === "span") {
             e.stopPropagation();
+        }
     }
 
 
diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx
index d2d41a4ba..1dacbb663 100644
--- a/src/client/views/PresentationView.tsx
+++ b/src/client/views/PresentationView.tsx
@@ -40,8 +40,8 @@ class PresentationViewList extends React.Component<PresListProps> {
             //this doc is selected
             className += " presentationView-selected";
         }
-        let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; }
-        let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; }
+        let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; };
+        let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; };
         return (
             <div className={className} key={document[Id] + index}
                 onPointerEnter={onEnter} onPointerLeave={onLeave}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 5238ad114..1e42593d1 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -130,7 +130,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     @action.bound
     removeDocument(doc: Doc): boolean {
-        let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView)
+        let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
         docView && SelectionManager.DeselectDoc(docView);
         const props = this.props;
         //TODO This won't create the field if it doesn't already exist
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f2b3528b8..5beb89315 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -347,7 +347,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                             tab.header.parent.setActiveContentItem(tab.contentItem);
                         }
                         tab.setActive(true);
-                    }
+                    };
                     ReactDOM.render(<ParentDocSelector Document={doc} addDocTab={(doc, location) => CollectionDockingView.Instance.AddTab(stack, doc)} />, upDiv);
                     tab.reactComponents = [upDiv];
                     tab.element.append(upDiv);
@@ -432,8 +432,9 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     @observable private _document: Opt<Doc>;
     get _stack(): any {
         let parent = (this.props as any).glContainer.parent.parent;
-        if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1)
+        if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1) {
             return parent.parent.contentItems[1];
+        }
         return parent;
     }
     constructor(props: any) {
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index b62d3f7bb..b2d016934 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -40,7 +40,7 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
                 // console.log(this.props.Document[HeightSym]());
             },
             { fireImmediately: true }
-        )
+        );
     }
 
     public static LayoutString(fieldKey: string = "data") {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 14a7d19d0..faea8d44d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -87,8 +87,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             let columnDocs = DocListCast(schemaDoc.data);
             if (columnDocs) {
                 let ddoc = columnDocs.find(doc => doc.title === columnName);
-                if (ddoc)
+                if (ddoc) {
                     return ddoc;
+                }
             }
         }
         return this.props.Document;
@@ -285,7 +286,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
 
     getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(
-        - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth);
+        - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth)
 
 
     get documentKeysCheckList() {
@@ -334,7 +335,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             columns={this.tableColumns}
             column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
             getTrProps={this.getTrProps}
-        />
+        />;
     }
 
     @computed
@@ -360,7 +361,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             addDocTab={this.props.addDocTab}
             setPreviewScript={this.setPreviewScript}
             previewScript={this.previewScript}
-        />
+        />;
     }
     @action
     setPreviewScript = (script: string) => {
@@ -409,7 +410,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
     }
     private PanelWidth = () => this.nativeWidth * this.contentScaling();
     private PanelHeight = () => this.nativeHeight * this.contentScaling();
-    private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling())
+    private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling());
     get centeringOffset() { return (this.props.width() - this.nativeWidth * this.contentScaling()) / 2; }
     @action
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index e1ac3505b..f5ad4ee95 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -101,7 +101,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             let childFocus = (doc: Doc) => {
                 doc.libraryBrush = true;
                 this.props.focus(this.props.Document); // just focus on this collection, not the underlying document because the API doesn't support adding an offset to focus on and we can't pan zoom our contents to be centered.
-            }
+            };
             return (<div className="collectionStackingView-masonryDoc"
                 key={d[Id]}
                 ref={dref}
@@ -131,7 +131,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                     whenActiveChanged={this.props.whenActiveChanged}
                 />
             </div>);
-        })
+        });
     }
     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
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b13694e9d..3e495b734 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -67,8 +67,8 @@ class TreeView extends React.Component<TreeViewProps> {
     @undoBatch delete = () => this.props.deleteDoc(this.props.document);
     @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight");
 
-    @action onMouseEnter = () => { this._isOver = true; }
-    @action onMouseLeave = () => { this._isOver = false; }
+    @action onMouseEnter = () => { this._isOver = true; };
+    @action onMouseLeave = () => { this._isOver = false; };
 
     onPointerEnter = (e: React.PointerEvent): void => {
         this.props.active() && (this.props.document.libraryBrush = true);
@@ -89,8 +89,8 @@ class TreeView extends React.Component<TreeViewProps> {
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
         let before = x[1] < bounds[1];
         let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible);
-        this._header!.current!.className = "treeViewItem-header"
-        if (inside && this._bulletType != BulletType.List) this._header!.current!.className += " treeViewItem-header-inside";
+        this._header!.current!.className = "treeViewItem-header";
+        if (inside && this._bulletType !== BulletType.List) this._header!.current!.className += " treeViewItem-header-inside";
         else if (before) this._header!.current!.className += " treeViewItem-header-above";
         else if (!before) this._header!.current!.className += " treeViewItem-header-below";
         e.stopPropagation();
@@ -192,7 +192,7 @@ class TreeView extends React.Component<TreeViewProps> {
             if (inside) {
                 let docList = Cast(this.props.document.data, listSpec(Doc));
                 if (docList !== undefined) {
-                    addDoc = (doc: Doc) => { docList && docList.push(doc); return true; }
+                    addDoc = (doc: Doc) => { docList && docList.push(doc); return true; };
                 }
             }
             let added = false;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index c4dd534ed..be75c6c5c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -109,7 +109,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
                     }
                     return match || found;
                 }, false)) {
-                    drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] })
+                    drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] });
                 }
             });
             return drawnPairs;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 250b6bf5d..84841e469 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -342,7 +342,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private childViews = () => [
         <CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} />,
         ...this.views
-    ];
+    ]
     render() {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index dedcc3172..05dc6f534 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -321,7 +321,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                             summary.imageSummary = imageSummary;
                             this.props.addDocument(imageSummary, false);
                         }
-                    })
+                    });
                     newCollection.proto!.summaryDoc = summary;
                     selected = [newCollection];
                     newCollection.x = bounds.left + bounds.width;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index f6b1c62ee..858959d81 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -48,7 +48,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     panelHeight = () => this.props.PanelHeight();
     getTransform = (): Transform => this.props.ScreenToLocalTransform()
         .translate(-this.X, -this.Y)
-        .scale(1 / this.contentScaling()).scale(1 / this.zoom);
+        .scale(1 / this.contentScaling()).scale(1 / this.zoom)
 
     animateBetweenIcon = (icon: number[], stime: number, maximizing: boolean) => {
         this.props.bringToFront(this.props.Document);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7c058d91c..4992669df 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -168,8 +168,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     public static animateBetweenIconFunc = (doc: Doc, width: number, height: number, stime: number, maximizing: boolean, cb?: (progress: number) => void) => {
         setTimeout(() => {
             let now = Date.now();
-            let progress = now < stime + 200 ? Math.min(1, (now - stime) / 200) : 1
-            doc.width = progress === 1 ? width : maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress
+            let progress = now < stime + 200 ? Math.min(1, (now - stime) / 200) : 1;
+            doc.width = progress === 1 ? width : maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress;
             doc.height = progress === 1 ? height : maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress;
             cb && cb(progress);
             if (now < stime + 200) {
@@ -229,7 +229,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (minimizedDoc) {
             let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(
                 NumCast(minimizedDoc.x) - NumCast(this.Document.x), NumCast(minimizedDoc.y) - NumCast(this.Document.y));
-            this.collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs))
+            this.collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs));
         }
     }
 
@@ -372,8 +372,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         this._lastTap = Date.now();
     }
 
-    deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); }
-    fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") };
+    deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); };
+    fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight"); };
     makeBtnClicked = (): void => {
         let doc = Doc.GetProto(this.props.Document);
         doc.isButton = !BoolCast(doc.isButton, false);
@@ -527,7 +527,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; };
 
     isSelected = () => SelectionManager.IsSelected(this);
-    @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }
+    @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); };
 
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 36d902c4f..df12f261b 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -161,7 +161,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                     de.data.moveDocument(de.data.draggedDocuments[0], stackDoc, (doc) => {
                         Cast(stackDoc.data, listSpec(Doc))!.push(doc);
                         return true;
-                    })
+                    });
                 }
             }
         }
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 6b8b64c5f..f208ce2ce 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -188,8 +188,9 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
     }
     @action onError = () => {
         let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount;
-        if (timeout < 10)
+        if (timeout < 10) {
             setTimeout(this.retryPath, Math.min(10000, timeout * 5));
+        }
     }
     _curSuffix = "_m";
     render() {
diff --git a/src/client/views/pdf/PDFAnnotationLayer.tsx b/src/client/views/pdf/PDFAnnotationLayer.tsx
index e92dcacbf..1f49e0d2f 100644
--- a/src/client/views/pdf/PDFAnnotationLayer.tsx
+++ b/src/client/views/pdf/PDFAnnotationLayer.tsx
@@ -19,6 +19,6 @@ export class PDFAnnotationLayer extends React.Component {
             <div className="pdfAnnotationLayer-cont" style={{ width: "100%", height: "100%", position: "relative", top: "-200%" }} onPointerDown={this.onPointerDown}>
 
             </div>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index 7817e8c26..2ed891131 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -162,6 +162,6 @@ export default class PDFMenu extends React.Component {
                 </button>
                 <div className="pdfMenu-dragger" onPointerDown={this.dragStart} style={{ width: this._pinned ? "20px" : "0px" }} />
             </div >
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 69372f43b..8c0aaea00 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -198,7 +198,7 @@ class Viewer extends React.Component<IViewerProps> {
                 <Page
                     pdf={this.props.pdf}
                     page={page}
-                    numPages={this.props.pdf!.numPages}
+                    numPages={this.props.pdf.numPages}
                     key={`rendered-${page + 1}`}
                     name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`}
                     pageLoaded={this.pageLoaded}
@@ -219,7 +219,7 @@ class Viewer extends React.Component<IViewerProps> {
     @action
     getPageImage = async (page: number) => {
         let handleError = () => this.getRenderedPage(page);
-        if (this._isPage[page] != "image") {
+        if (this._isPage[page] !== "image") {
             this._isPage[page] = "image";
             const address = this.props.url;
             let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`)));
diff --git a/src/server/index.ts b/src/server/index.ts
index 7ef542b01..2901f61ed 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -172,7 +172,7 @@ function LoadPage(file: string, pageNumber: number, res: Response) {
                     canvasContext: canvasAndContext.context,
                     viewport: viewport,
                     canvasFactory: factory
-                }
+                };
                 console.log("read " + pageNumber);
 
                 page.render(renderContext).promise
-- 
cgit v1.2.3-70-g09d2


From cccc43c64a749e34a993e32f8616ac7e0532c7d9 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 21 Jun 2019 09:18:45 -0400
Subject: more templating fixes.

---
 src/client/views/DocumentDecorations.tsx                |  1 +
 src/client/views/collections/CollectionBaseView.tsx     | 16 ++++++++++------
 src/client/views/collections/CollectionSchemaView.tsx   |  9 ++++++---
 src/client/views/collections/CollectionStackingView.tsx |  2 ++
 src/client/views/collections/CollectionTreeView.tsx     |  1 +
 src/client/views/collections/CollectionView.tsx         |  4 +++-
 src/client/views/nodes/FormattedTextBox.tsx             |  2 +-
 7 files changed, 24 insertions(+), 11 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index d6010ec33..b3f5340d9 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -80,6 +80,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 let template = Doc.MakeAlias(collection);
                 template.title = "FIELD-" + this._fieldKey;
                 template.layout = FormattedTextBox.LayoutString(this._fieldKey);
+                template.isTemplate = true;
                 template.x = NumCast(first.x);
                 template.y = NumCast(first.y);
                 template.width = first[WidthSym]();
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 1e42593d1..038a73626 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -5,7 +5,7 @@ import { Doc, DocListCast, Opt } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
 import { listSpec } from '../../../new_fields/Schema';
-import { Cast, FieldValue, NumCast, PromiseValue } from '../../../new_fields/Types';
+import { Cast, FieldValue, NumCast, PromiseValue, StrCast } from '../../../new_fields/Types';
 import { SelectionManager } from '../../util/SelectionManager';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
@@ -77,10 +77,12 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         if (!(documentToAdd instanceof Doc)) {
             return false;
         }
-        let data = DocListCast(documentToAdd.data);
-        for (const doc of data) {
-            if (this.createsCycle(doc, containerDocument)) {
-                return true;
+        if (StrCast(documentToAdd.layout).indexOf("CollectionView") !== -1) {
+            let data = DocListCast(documentToAdd.data);
+            for (const doc of data) {
+                if (this.createsCycle(doc, containerDocument)) {
+                    return true;
+                }
             }
         }
         let annots = DocListCast(documentToAdd.annotations);
@@ -106,6 +108,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         if (curPage >= 0) {
             Doc.GetProto(doc).annotationOn = props.Document;
         }
+        allowDuplicates = true;
         if (!this.createsCycle(doc, props.Document)) {
             //TODO This won't create the field if it doesn't already exist
             const value = Cast(props.Document[props.fieldKey], listSpec(Doc));
@@ -124,8 +127,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
                 let zoom = NumCast(this.props.Document.scale, 1);
                 // Doc.GetProto(doc).zoomBasis = zoom;
             }
+            return true;
         }
-        return true;
+        return false;
     }
 
     @action.bound
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index c5b0527cc..d539835b9 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -347,9 +347,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @computed
     get previewPanel() {
-        trace();
         return <CollectionSchemaPreview
             Document={this.previewDocument}
+            DataDocument={this.previewDocument}
             width={this.previewWidth}
             height={this.previewHeight}
             getTransform={this.getPreviewTransform}
@@ -384,6 +384,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 }
 interface CollectionSchemaPreviewProps {
     Document?: Doc;
+    DataDocument?: Doc;
     width: () => number;
     height: () => number;
     CollectionView?: CollectionView | CollectionPDFView | CollectionVideoView;
@@ -422,9 +423,11 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
             <input className="collectionSchemaView-input" value={this.props.previewScript} onChange={this.onPreviewScriptChange}
                 style={{ left: `calc(50% - ${Math.min(75, (this.props.Document ? this.PanelWidth() / 2 : 75))}px)` }} />;
         return (<div className="collectionSchemaView-previewRegion" style={{ width: this.props.width(), height: "100%" }}>
-            {!this.props.Document || !this.props.width ? (null) : (
+            {!this.props.Document || !this.props.DataDocument || !this.props.width ? (null) : (
                 <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.centeringOffset}px, 0px)`, height: "100%" }}>
-                    <DocumentView DataDoc={this.props.Document} Document={this.props.Document} isTopMost={false} selectOnLoad={false}
+                    <DocumentView
+                        DataDoc={this.props.DataDocument}
+                        Document={this.props.Document} isTopMost={false} selectOnLoad={false}
                         addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} moveDocument={this.props.moveDocument}
                         ScreenToLocalTransform={this.getTransform}
                         ContentScaling={this.contentScaling}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index c855cb43a..a1e84302b 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -76,6 +76,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 style={{ width: width(), height: height() }} >
                 <CollectionSchemaPreview
                     Document={d}
+                    DataDocument={this.props.DataDoc !== this.props.Document ? this.props.DataDoc : d}
                     width={width}
                     height={height}
                     getTransform={dxf}
@@ -107,6 +108,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 style={{ gridRowEnd: `span ${rowSpan}` }} >
                 <CollectionSchemaPreview
                     Document={d}
+                    DataDocument={this.props.DataDoc !== this.props.Document ? this.props.DataDoc : d}
                     CollectionView={this.props.CollectionView}
                     addDocument={this.props.addDocument}
                     moveDocument={this.props.moveDocument}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index eaa3add40..7528bc29d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -276,6 +276,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.props.panelHeight() }} key={this.props.document[Id]}>
                     <CollectionSchemaPreview
                         Document={this.props.document}
+                        DataDocument={this.props.document}
                         width={docWidth}
                         height={this.props.panelHeight}
                         getTransform={this.docTransform}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e24466d57..f254e6005 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -64,6 +64,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
                     Doc.GetProto(collection).description = "my first templated box";
                     let template = Doc.MakeAlias(collection);
                     template.layout = FormattedTextBox.LayoutString("description");
+                    template.isTemplate = true;
                     template.x = 0;
                     template.y = 0;
                     template.width = 100;
@@ -76,6 +77,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
                     Doc.GetProto(this.props.Document).summary = "my first templated box";
                     let template = Doc.MakeAlias(this.props.Document);
                     template.layout = FormattedTextBox.LayoutString("summary");
+                    template.isTemplate = true;
                     template.x = 0;
                     template.y = 0;
                     template.width = 100;
@@ -88,7 +90,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
                     let otherdoc = Docs.TextDocument({ width: 100, height: 50, title: "applied template" });
                     Doc.GetProto(otherdoc).description = "THIS DESCRIPTION IS REALLY IMPORTANT!";
                     Doc.GetProto(otherdoc).summary = "THIS SUMMARY IS MEANINGFUL!";
-                    Doc.GetProto(otherdoc).layout = this.props.Document;
+                    Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document);
                     this.props.addDocTab && this.props.addDocTab(otherdoc, "onRight");
                 }), icon: "project-diagram"
             });
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 92835ba39..f59af226d 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -104,7 +104,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         }
     }
 
-    @computed get dataDoc() { return this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
 
     dispatchTransaction = (tx: Transaction) => {
         if (this._editorView) {
-- 
cgit v1.2.3-70-g09d2


From c9a36bc25ed8bb8144dbef6c7cc2a09447867aa8 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 21 Jun 2019 22:46:24 -0400
Subject: fixes to allow collections to be template fields

---
 src/client/views/DocumentDecorations.tsx           | 21 +++++++
 .../views/collections/CollectionBaseView.tsx       | 45 +++++---------
 src/client/views/collections/CollectionSubView.tsx |  4 +-
 .../views/collections/CollectionTreeView.tsx       | 71 ++++++++++++++--------
 src/client/views/collections/CollectionView.tsx    |  7 +++
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  5 +-
 src/client/views/nodes/DocumentView.tsx            |  1 +
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 8 files changed, 96 insertions(+), 60 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 8f02f04d7..bdc814546 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -26,6 +26,7 @@ import { Template, Templates } from "./Templates";
 import React = require("react");
 import { URLField } from '../../new_fields/URLField';
 import { templateLiteral } from 'babel-types';
+import { CollectionViewType } from './collections/CollectionBaseView';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -74,6 +75,26 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             if (text[0] === '#') {
                 this._fieldKey = text.slice(1, text.length);
                 this._title = this.selectionTitle;
+            } else if (text.startsWith(">>>")) {
+                let metaKey = text.slice(3, text.length);
+                let collection = SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView!.props.Document;
+                Doc.GetProto(collection)[metaKey] = new List<Doc>([
+                    Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
+                    Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
+                ]);
+                let template = Doc.MakeAlias(collection);
+                template.title = metaKey;
+                template.embed = true;
+                template.layout = CollectionView.LayoutString(metaKey);
+                template.viewType = CollectionViewType.Freeform;
+                template.x = 0;
+                template.y = 0;
+                template.width = 300;
+                template.height = 300;
+                template.isTemplate = true;
+                template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
+                Doc.AddDocToList(collection, "data", template);
+                SelectionManager.SelectedDocuments().map(dv => dv.props.removeDocument && dv.props.removeDocument(dv.props.Document));
             } else if (text[0] === ">") {
                 let metaKey = text.slice(1, text.length);
                 let first = SelectionManager.SelectedDocuments()[0].props.Document!;
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 038a73626..75bdf755c 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -5,7 +5,7 @@ import { Doc, DocListCast, Opt } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
 import { listSpec } from '../../../new_fields/Schema';
-import { Cast, FieldValue, NumCast, PromiseValue, StrCast } from '../../../new_fields/Types';
+import { Cast, FieldValue, NumCast, PromiseValue, StrCast, BoolCast } from '../../../new_fields/Types';
 import { SelectionManager } from '../../util/SelectionManager';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
@@ -60,6 +60,8 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         }
     }
 
+    @computed get dataDoc() { return (BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document); }
+
     active = (): boolean => {
         var isSelected = this.props.isSelected();
         var topMost = this.props.isTopMost;
@@ -102,30 +104,21 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
-        let props = this.props;
-        var curPage = NumCast(props.Document.curPage, -1);
+        var curPage = NumCast(this.props.Document.curPage, -1);
         Doc.GetProto(doc).page = curPage;
         if (curPage >= 0) {
-            Doc.GetProto(doc).annotationOn = props.Document;
+            Doc.GetProto(doc).annotationOn = this.props.Document;
         }
         allowDuplicates = true;
-        if (!this.createsCycle(doc, props.Document)) {
+        if (!this.createsCycle(doc, this.dataDoc)) {
             //TODO This won't create the field if it doesn't already exist
-            const value = Cast(props.Document[props.fieldKey], listSpec(Doc));
-            let alreadyAdded = true;
+            const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc));
             if (value !== undefined) {
                 if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
-                    alreadyAdded = false;
                     value.push(doc);
                 }
             } else {
-                alreadyAdded = false;
-                Doc.SetOnPrototype(this.props.Document, this.props.fieldKey, new List([doc]));
-            }
-            // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument?
-            if (!alreadyAdded && (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid)) {
-                let zoom = NumCast(this.props.Document.scale, 1);
-                // Doc.GetProto(doc).zoomBasis = zoom;
+                Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new List([doc]));
             }
             return true;
         }
@@ -136,22 +129,12 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
     removeDocument(doc: Doc): boolean {
         let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
         docView && SelectionManager.DeselectDoc(docView);
-        const props = this.props;
         //TODO This won't create the field if it doesn't already exist
-        const value = Cast(props.Document[props.fieldKey], listSpec(Doc), []);
-        let index = -1;
-        for (let i = 0; i < value.length; i++) {
-            let v = value[i];
-            if (v instanceof Doc && v[Id] === doc[Id]) {
-                index = i;
-                break;
-            }
-        }
-        PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn => {
-            if (annotationOn === props.Document) {
-                doc.annotationOn = undefined;
-            }
-        });
+        const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc), []);
+        let index = value.reduce((p, v, i) => (v instanceof Doc && v[Id] === doc[Id]) ? i : p, -1);
+        PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn =>
+            annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined)
+        );
 
         if (index !== -1) {
             value.splice(index, 1);
@@ -165,7 +148,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     @action.bound
     moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean {
-        if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
+        if (Doc.AreProtosEqual(this.dataDoc, targetCollection)) {
             return true;
         }
         if (this.removeDocument(doc)) {
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 699bddc7c..a887d8ec8 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -4,7 +4,7 @@ import CursorField from "../../../new_fields/CursorField";
 import { Doc, DocListCast, Opt } from "../../../new_fields/Doc";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
-import { Cast, PromiseValue } from "../../../new_fields/Types";
+import { Cast, PromiseValue, BoolCast } from "../../../new_fields/Types";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { RouteStore } from "../../../server/RouteStore";
 import { DocServer } from "../../DocServer";
@@ -48,7 +48,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
         get childDocs() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return DocListCast(this.props.Document[this.props.fieldKey]);
+            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document)[this.props.fieldKey]);
         }
 
         @action
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 83a7c9e3a..05252f632 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -28,6 +28,8 @@ import React = require("react");
 import { FormattedTextBox } from '../nodes/FormattedTextBox';
 import { ImageField } from '../../../new_fields/URLField';
 import { ImageBox } from '../nodes/ImageBox';
+import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
+import { CollectionView } from './CollectionView';
 
 
 export interface TreeViewProps {
@@ -150,42 +152,63 @@ class TreeView extends React.Component<TreeViewProps> {
         SetValue={(value: string) => {
             let res = (Doc.GetProto(this.props.document)[key] = value) ? true : true;
 
-            if (value.startsWith(">>")) {
-                let metaKey = value.slice(2, value.length);
+            if (value.startsWith(">>>")) {
+                let metaKey = value.slice(3, value.length);
                 let collection = this.props.containingCollection;
-                Doc.GetProto(collection)[metaKey] = new ImageField("http://www.cs.brown.edu/~bcz/face.gif");
+                Doc.GetProto(collection)[metaKey] = new List<Doc>([
+                    Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
+                    Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
+                ]);
                 let template = Doc.MakeAlias(collection);
                 template.title = metaKey;
                 template.embed = true;
-                template.layout = ImageBox.LayoutString(metaKey);
+                template.layout = CollectionView.LayoutString(metaKey);
+                template.viewType = CollectionViewType.Freeform;
                 template.x = 0;
                 template.y = 0;
-                template.nativeWidth = 300;
-                template.nativeHeight = 300;
                 template.width = 300;
                 template.height = 300;
                 template.isTemplate = true;
                 template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
                 Doc.AddDocToList(collection, "data", template);
                 this.delete();
-            }
-            if (value.startsWith(">")) {
-                let metaKey = value.slice(1, value.length);
-                let collection = this.props.containingCollection;
-                Doc.GetProto(collection)[metaKey] = "-empty field-";
-                let template = Doc.MakeAlias(collection);
-                template.title = metaKey;
-                template.embed = true;
-                template.layout = FormattedTextBox.LayoutString(metaKey);
-                template.x = 0;
-                template.y = 0;
-                template.width = 100;
-                template.height = 50;
-                template.isTemplate = true;
-                template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
-                Doc.AddDocToList(collection, "data", template);
-                this.delete();
-            }
+            } else
+                if (value.startsWith(">>")) {
+                    let metaKey = value.slice(2, value.length);
+                    let collection = this.props.containingCollection;
+                    Doc.GetProto(collection)[metaKey] = new ImageField("http://www.cs.brown.edu/~bcz/face.gif");
+                    let template = Doc.MakeAlias(collection);
+                    template.title = metaKey;
+                    template.embed = true;
+                    template.layout = ImageBox.LayoutString(metaKey);
+                    template.x = 0;
+                    template.y = 0;
+                    template.nativeWidth = 300;
+                    template.nativeHeight = 300;
+                    template.width = 300;
+                    template.height = 300;
+                    template.isTemplate = true;
+                    template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
+                    Doc.AddDocToList(collection, "data", template);
+                    this.delete();
+                } else
+                    if (value.startsWith(">")) {
+                        let metaKey = value.slice(1, value.length);
+                        let collection = this.props.containingCollection;
+                        Doc.GetProto(collection)[metaKey] = "-empty field-";
+                        let template = Doc.MakeAlias(collection);
+                        template.title = metaKey;
+                        template.embed = true;
+                        template.layout = FormattedTextBox.LayoutString(metaKey);
+                        template.x = 0;
+                        template.y = 0;
+                        template.width = 100;
+                        template.height = 50;
+                        template.isTemplate = true;
+                        template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
+                        Doc.AddDocToList(collection, "data", template);
+                        this.delete();
+                    }
 
             return res;
         }}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 10e6fb885..872cb3f1c 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -66,6 +66,13 @@ export class CollectionView extends React.Component<FieldViewProps> {
                     Doc.GetProto(otherdoc).summary = "THIS SUMMARY IS MEANINGFUL!";
                     Doc.GetProto(otherdoc).photo = new ImageField("http://www.cs.brown.edu/~bcz/snowbeast.JPG");
                     Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document);
+                    Doc.GetProto(otherdoc).publication = new List<Doc>([
+                        Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
+                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
+                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
+                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
+                        Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
+                    ]);
                     this.props.addDocTab && this.props.addDocTab(otherdoc, otherdoc, "onRight");
                 }), icon: "project-diagram"
             });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 5c2ea3ef0..20a9a172c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -45,6 +45,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private get _pwidth() { return this.props.PanelWidth(); }
     private get _pheight() { return this.props.PanelHeight(); }
 
+    @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
     public get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; }
@@ -163,7 +164,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
                     [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
                 }, [[minx, maxx], [miny, maxy]]);
-                let ink = Cast(this.props.Document.ink, InkField);
+                let ink = Cast(this.dataDoc.ink, InkField);
                 if (ink && ink.inkData) {
                     ink.inkData.forEach((value: StrokeData, key: string) => {
                         let bounds = InkingCanvas.StrokeRect(value);
@@ -296,7 +297,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     getDocumentViewProps(layoutDoc: Doc): DocumentViewProps {
         return {
-            DataDoc: this.props.DataDoc !== this.props.Document ? this.props.DataDoc : layoutDoc,
+            DataDoc: this.props.DataDoc !== this.props.Document && !BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : layoutDoc,
             Document: layoutDoc,
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 08f58dcd6..1a92d7152 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -536,6 +536,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
     @computed get contents() {
+        console.log("dv = " + this.props.Document.title + " " + this.props.DataDoc.title);
         return (
             <DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} selectOnLoad={this.props.selectOnLoad} layoutKey={"layout"} />);
     }
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 241a593b0..008a09130 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -68,7 +68,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.DocumentDragData) {
             de.data.droppedDocuments.forEach(action((drop: Doc) => {
-                if (this.dataDoc !== this.props.Document && drop.data instanceof ImageField) {
+                if (/*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) {
                     this.dataDoc[this.props.fieldKey] = new ImageField(drop.data.url);
                     e.stopPropagation();
                 } else {
-- 
cgit v1.2.3-70-g09d2


From 6df09d7d646c16e6469b198e7d270b6a1e45b0c7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 24 Jun 2019 13:23:28 -0400
Subject: fixes for templates with annotations and more.

---
 src/client/util/TooltipTextMenu.tsx                |   2 +-
 src/client/views/DocumentDecorations.tsx           |  55 +++++------
 src/client/views/InkingCanvas.tsx                  |   7 +-
 src/client/views/InkingControl.tsx                 |   3 +-
 src/client/views/MainView.tsx                      |   4 +-
 .../views/collections/CollectionBaseView.tsx       |   1 -
 .../views/collections/CollectionTreeView.tsx       | 106 +++++++++------------
 src/client/views/collections/CollectionView.tsx    |  17 +---
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   5 +-
 src/client/views/pdf/PDFViewer.tsx                 |   1 +
 src/new_fields/Doc.ts                              |   2 +-
 11 files changed, 82 insertions(+), 121 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index c9216199b..048fb7133 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -222,7 +222,7 @@ export class TooltipTextMenu {
                                 if (DocumentManager.Instance.getDocumentView(f)) {
                                     DocumentManager.Instance.getDocumentView(f)!.props.focus(f);
                                 }
-                                else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f);
+                                else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f, f);
                             }
                         }));
                     }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 0d5cca9f1..9be5c9cd6 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -24,9 +24,10 @@ import { LinkMenu } from "./nodes/LinkMenu";
 import { TemplateMenu } from "./TemplateMenu";
 import { Template, Templates } from "./Templates";
 import React = require("react");
-import { URLField } from '../../new_fields/URLField';
+import { URLField, ImageField } from '../../new_fields/URLField';
 import { templateLiteral } from 'babel-types';
 import { CollectionViewType } from './collections/CollectionBaseView';
+import { ImageBox } from './nodes/ImageBox';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -75,41 +76,29 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             if (text[0] === '#') {
                 this._fieldKey = text.slice(1, text.length);
                 this._title = this.selectionTitle;
-            } else if (text.startsWith(">>>")) {
-                let metaKey = text.slice(3, text.length);
-                let collection = SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView!.props.Document;
-                Doc.GetProto(collection)[metaKey] = new List<Doc>([
-                    Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
-                    Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
-                ]);
-                let template = Doc.MakeAlias(collection);
+            } else if (text.startsWith(">")) {
+                let metaKey = text.slice(text.startsWith(">>>") ? 3 : text.startsWith(">>") ? 2 : 1, text.length);
+                let field = SelectionManager.SelectedDocuments()[0];
+                let collectionKey = field.props.ContainingCollectionView!.props.fieldKey;
+                let collection = field.props.ContainingCollectionView!.props.Document;
+                let collectionKeyProp = `fieldKey={"${collectionKey}"}`;
+                let collectionAnnotationsKeyProp = `fieldKey={"annotations"}`;
+                let metaKeyProp = `fieldKey={"${metaKey}"}`;
+                let metaAnnotationsKeyProp = `fieldKey={"${metaKey}_annotations"}`;
+                let template = Doc.MakeAlias(field.props.Document);
+                template.proto = collection;
                 template.title = metaKey;
+                template.nativeWidth = Cast(field.nativeWidth, "number");
+                template.nativeHeight = Cast(field.nativeHeight, "number");
                 template.embed = true;
-                template.layout = CollectionView.LayoutString(metaKey);
-                template.viewType = CollectionViewType.Freeform;
-                template.x = 0;
-                template.y = 0;
-                template.width = 300;
-                template.height = 300;
                 template.isTemplate = true;
-                template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
-                Doc.AddDocToList(collection, "data", template);
-                SelectionManager.SelectedDocuments().map(dv => dv.props.removeDocument && dv.props.removeDocument(dv.props.Document));
-            } else if (text[0] === ">") {
-                let metaKey = text.slice(1, text.length);
-                let first = SelectionManager.SelectedDocuments()[0].props.Document!;
-                let collection = SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView!.props.Document;
-                Doc.GetProto(collection)[metaKey] = "-empty field-";
-                let template = Doc.MakeAlias(collection);
-                template.title = metaKey;
-                template.layout = FormattedTextBox.LayoutString(metaKey);
-                template.isTemplate = true;
-                template.x = NumCast(first.x);
-                template.y = NumCast(first.y);
-                template.width = first[WidthSym]();
-                template.height = first[HeightSym]();
-                template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
-                Doc.AddDocToList(collection, "data", template);
+                template.templates = new List<string>([Templates.TitleBar(metaKey)]);
+                template.layout = StrCast(field.props.Document.layout).replace(collectionKeyProp, metaKeyProp);
+                if (field.props.Document.backgroundLayout) {
+                    template.layout = StrCast(field.props.Document.layout).replace(collectionAnnotationsKeyProp, metaAnnotationsKeyProp);
+                    template.backgroundLayout = StrCast(field.props.Document.backgroundLayout).replace(collectionKeyProp, metaKeyProp);
+                }
+                Doc.AddDocToList(collection, collectionKey, template);
                 SelectionManager.SelectedDocuments().map(dv => dv.props.removeDocument && dv.props.removeDocument(dv.props.Document));
             }
             else {
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 5d4ea76cd..fd7e5b07d 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -14,6 +14,7 @@ import { Cast, PromiseValue, NumCast } from "../../new_fields/Types";
 interface InkCanvasProps {
     getScreenTransform: () => Transform;
     Document: Doc;
+    inkFieldKey: string;
     children: () => JSX.Element[];
 }
 
@@ -40,7 +41,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
     }
 
     componentDidMount() {
-        PromiseValue(Cast(this.props.Document.ink, InkField)).then(ink => runInAction(() => {
+        PromiseValue(Cast(this.props.Document[this.props.inkFieldKey], InkField)).then(ink => runInAction(() => {
             if (ink) {
                 let bounds = Array.from(ink.inkData).reduce(([mix, max, miy, may], [id, strokeData]) =>
                     strokeData.pathData.reduce(([mix, max, miy, may], p) =>
@@ -55,12 +56,12 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
 
     @computed
     get inkData(): Map<string, StrokeData> {
-        let map = Cast(this.props.Document.ink, InkField);
+        let map = Cast(this.props.Document[this.props.inkFieldKey], InkField);
         return !map ? new Map : new Map(map.inkData);
     }
 
     set inkData(value: Map<string, StrokeData>) {
-        Doc.GetProto(this.props.Document).ink = new InkField(value);
+        Doc.GetProto(this.props.Document)[this.props.inkFieldKey] = new InkField(value);
     }
 
     @action
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 0837e07a9..6cde73933 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -8,6 +8,7 @@ import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-s
 import { SelectionManager } from "../util/SelectionManager";
 import { InkTool } from "../../new_fields/InkField";
 import { Doc } from "../../new_fields/Doc";
+import { InkingCanvas } from "./InkingCanvas";
 
 library.add(faPen, faHighlighter, faEraser, faBan);
 
@@ -39,7 +40,7 @@ export class InkingControl extends React.Component {
     @action
     switchColor = (color: ColorResult): void => {
         this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff");
-        SelectionManager.SelectedDocuments().forEach(doc => Doc.GetProto(doc.props.Document).backgroundColor = this._selectedColor);
+        if (InkingControl.Instance.selectedTool === InkTool.None) SelectionManager.SelectedDocuments().forEach(doc => Doc.GetProto(doc.props.Document).backgroundColor = this._selectedColor);
     }
 
     @action
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8198b88d2..a72f25b99 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -144,7 +144,7 @@ export class MainView extends React.Component {
         const list = Cast(CurrentUserUtils.UserDocument.data, listSpec(Doc));
         if (list) {
             let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, width: this.pwidth * .7, height: this.pheight, title: `WS collection ${list.length + 1}` });
-            var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(CurrentUserUtils.UserDocument, 150), CollectionDockingView.makeDocumentConfig(freeformDoc, 600)] }] };
+            var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(CurrentUserUtils.UserDocument, CurrentUserUtils.UserDocument, 150), CollectionDockingView.makeDocumentConfig(freeformDoc, freeformDoc, 600)] }] };
             let mainDoc = Docs.DockDocument([CurrentUserUtils.UserDocument, freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${list.length + 1}` }, id);
             list.push(mainDoc);
             // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
@@ -177,7 +177,7 @@ export class MainView extends React.Component {
 
     openNotifsCol = () => {
         if (this._notifsCol && CollectionDockingView.Instance) {
-            CollectionDockingView.Instance.AddRightSplit(this._notifsCol);
+            CollectionDockingView.Instance.AddRightSplit(this._notifsCol, this._notifsCol);
         }
     }
 
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 75bdf755c..79a9f3be0 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -100,7 +100,6 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         }
         return false;
     }
-    @computed get isAnnotationOverlay() { return this.props.fieldKey === "annotations"; }
 
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b3f1b1c88..f5f323269 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -28,7 +28,6 @@ import React = require("react");
 import { FormattedTextBox } from '../nodes/FormattedTextBox';
 import { ImageField } from '../../../new_fields/URLField';
 import { ImageBox } from '../nodes/ImageBox';
-import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
 import { CollectionView } from './CollectionView';
 
 
@@ -71,11 +70,23 @@ class TreeView extends React.Component<TreeViewProps> {
     @observable _collapsed: boolean = true;
 
     @computed get fieldKey() {
+        let keys = Array.from(Object.keys(this.dataDoc));
+        if (this.dataDoc.proto instanceof Doc) {
+            keys.push(...Array.from(Object.keys(this.dataDoc.proto)));
+            while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
+        }
+        let keyList: string[] = [];
+        keys.map(key => {
+            let docList = Cast(this.dataDoc[key], listSpec(Doc));
+            if (docList && docList.length > 0) {
+                keyList.push(key);
+            }
+        });
         let layout = StrCast(this.props.document.layout);
         if (layout.indexOf("fieldKey={\"") !== -1) {
             return layout.split("fieldKey={\"")[1].split("\"")[0];
         }
-        return "data";
+        return keyList.length ? keyList[0] : "data";
     }
 
     @computed get dataDoc() { return (BoolCast(this.props.document.isTemplate) ? this.props.dataDoc : this.props.document); }
@@ -163,63 +174,39 @@ class TreeView extends React.Component<TreeViewProps> {
         SetValue={(value: string) => {
             let res = (Doc.GetProto(this.dataDoc)[key] = value) ? true : true;
 
-            if (value.startsWith(">>>")) {
-                let metaKey = value.slice(3, value.length);
+            if (value.startsWith(">")) {
+                let metaKey = value.slice(value.startsWith(">>>") ? 3 : value.startsWith(">>") ? 2 : 1, value.length);
                 let collection = this.props.containingCollection;
-                Doc.GetProto(collection)[metaKey] = new List<Doc>([
-                    Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
-                    Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
-                ]);
                 let template = Doc.MakeAlias(collection);
                 template.title = metaKey;
                 template.embed = true;
-                template.layout = CollectionView.LayoutString(metaKey);
-                template.viewType = CollectionViewType.Freeform;
                 template.x = 0;
                 template.y = 0;
                 template.width = 300;
                 template.height = 300;
                 template.isTemplate = true;
                 template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
-                Doc.AddDocToList(collection, "data", template);
-                this.delete();
-            } else
-                if (value.startsWith(">>")) {
-                    let metaKey = value.slice(2, value.length);
-                    let collection = this.props.containingCollection;
+                if (value.startsWith(">>>")) { // Collection
+                    Doc.GetProto(collection)[metaKey] = new List<Doc>([
+                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
+                        Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
+                    ]);
+                    template.layout = CollectionView.LayoutString(metaKey);
+                    template.viewType = CollectionViewType.Freeform;
+                } else if (value.startsWith(">>")) { // Image
                     Doc.GetProto(collection)[metaKey] = new ImageField("http://www.cs.brown.edu/~bcz/face.gif");
-                    let template = Doc.MakeAlias(collection);
-                    template.title = metaKey;
-                    template.embed = true;
                     template.layout = ImageBox.LayoutString(metaKey);
-                    template.x = 0;
-                    template.y = 0;
                     template.nativeWidth = 300;
                     template.nativeHeight = 300;
-                    template.width = 300;
-                    template.height = 300;
-                    template.isTemplate = true;
-                    template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
-                    Doc.AddDocToList(collection, "data", template);
-                    this.delete();
-                } else
-                    if (value.startsWith(">")) {
-                        let metaKey = value.slice(1, value.length);
-                        let collection = this.props.containingCollection;
-                        Doc.GetProto(collection)[metaKey] = "-empty field-";
-                        let template = Doc.MakeAlias(collection);
-                        template.title = metaKey;
-                        template.embed = true;
-                        template.layout = FormattedTextBox.LayoutString(metaKey);
-                        template.x = 0;
-                        template.y = 0;
-                        template.width = 100;
-                        template.height = 50;
-                        template.isTemplate = true;
-                        template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
-                        Doc.AddDocToList(collection, "data", template);
-                        this.delete();
-                    }
+                } else if (value.startsWith(">")) {  // Text
+                    Doc.GetProto(collection)[metaKey] = "-empty field-";
+                    template.layout = FormattedTextBox.LayoutString(metaKey);
+                    template.width = 100;
+                    template.height = 50;
+                }
+                Doc.AddDocToList(collection, "data", template);
+                this.delete();
+            }
 
             return res;
         }}
@@ -238,14 +225,8 @@ class TreeView extends React.Component<TreeViewProps> {
             keys.push(...Array.from(Object.keys(this.dataDoc.proto)));
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
-        let keyList: string[] = [];
-        keys.map(key => {
-            let docList = Cast(this.dataDoc[key], listSpec(Doc));
-            let doc = Cast(this.dataDoc[key], Doc);
-            if (doc instanceof Doc || docList) {
-                keyList.push(key);
-            }
-        });
+        let keyList: string[] = keys.reduce((l, key) => Cast(this.dataDoc[key], listSpec(Doc)) ? [...l, key] : l, [] as string[]);
+        keys.map(key => Cast(this.dataDoc[key], Doc) instanceof Doc && keyList.push(key));
         if (keyList.indexOf(this.fieldKey) !== -1) {
             keyList.splice(keyList.indexOf(this.fieldKey), 1);
         }
@@ -291,16 +272,16 @@ class TreeView extends React.Component<TreeViewProps> {
     onWorkspaceContextMenu = (e: React.MouseEvent): void => {
         if (!e.isPropagationStopped()) { // 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: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.dataDoc)) });
-            ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.KVPDocument(this.dataDoc, { width: 300, height: 300 }); this.props.addDocTab(kvp, kvp, "onRight"); }, icon: "layer-group" });
+            ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, kvp, "onRight"); }, icon: "layer-group" });
             if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) {
-                ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.props.document, "inTab"), icon: "folder" });
-                ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.props.document, "onRight"), icon: "caret-square-right" });
+                ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.dataDoc, "inTab"), icon: "folder" });
+                ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.dataDoc, "onRight"), icon: "caret-square-right" });
                 if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) {
                     ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.dataDoc).map(view => view.props.focus(this.props.document)) });
                 }
-                ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.dataDoc)) });
+                ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)) });
             } else {
-                ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.dataDoc)) });
+                ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)) });
             }
             ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15);
             e.stopPropagation();
@@ -349,14 +330,14 @@ class TreeView extends React.Component<TreeViewProps> {
         if (!this._collapsed) {
             if (!this.props.document.embed) {
                 contentElement = <ul key={this._chosenKey + "more"}>
-                    {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.props.dataDoc, this._chosenKey, addDoc, remDoc, this.move,
+                    {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.dataDoc, this._chosenKey, addDoc, remDoc, this.move,
                         this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth)}
                 </ul >;
             } else {
                 contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.props.panelHeight() }} key={this.props.document[Id]}>
                     <CollectionSchemaPreview
                         Document={this.props.document}
-                        DataDocument={this.props.dataDoc}
+                        DataDocument={this.dataDoc}
                         width={docWidth}
                         height={this.props.panelHeight}
                         getTransform={this.docTransform}
@@ -400,7 +381,7 @@ class TreeView extends React.Component<TreeViewProps> {
         active: () => boolean,
         panelWidth: () => number,
     ) {
-        let docList = docs.filter(child => !child.excludeFromLibrary && (key !== this.fieldKey || !child.isMinimized));
+        let docList = docs.filter(child => !child.excludeFromLibrary);
         let rowWidth = () => panelWidth() - 20;
         return docList.map((child, i) => {
             let indent = i === 0 ? undefined : () => {
@@ -475,6 +456,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
 
     outerXf = () => Utils.GetScreenTransform(this._mainEle!);
     onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {});
+    @computed get dataDoc() { return (BoolCast(this.props.DataDoc.isTemplate) ? this.props.DataDoc : this.props.Document); }
 
     render() {
         let dropAction = StrCast(this.props.Document.dropAction) as dropActionType;
@@ -502,7 +484,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                     }} />
                 <ul className="no-indent" style={{ width: "max-content" }} >
                     {
-                        TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.Document, this.props.DataDoc, this.props.fieldKey, addDoc, this.remove,
+                        TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.Document, this.dataDoc, this.props.fieldKey, addDoc, this.remove,
                             moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.outerXf, this.props.active, this.props.PanelWidth)
                     }
                 </ul>
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 872cb3f1c..cc097f371 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -2,8 +2,10 @@ import { library } from '@fortawesome/fontawesome-svg-core';
 import { faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons';
 import { observer } from "mobx-react";
 import * as React from 'react';
+import { Doc } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
+import { Docs } from '../../documents/Documents';
 import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from '../ContextMenuItem';
@@ -14,11 +16,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionSchemaView } from "./CollectionSchemaView";
 import { CollectionStackingView } from './CollectionStackingView';
 import { CollectionTreeView } from "./CollectionTreeView";
-import { Doc } from '../../../new_fields/Doc';
-import { FormattedTextBox } from '../nodes/FormattedTextBox';
-import { Docs } from '../../documents/Documents';
-import { List } from '../../../new_fields/List';
-import { ImageField } from '../../../new_fields/URLField';
 export const COLLECTION_BORDER_WIDTH = 2;
 
 library.add(faTh);
@@ -62,17 +59,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
             ContextMenu.Instance.addItem({
                 description: "Apply Template", event: undoBatch(() => {
                     let otherdoc = Docs.TextDocument({ width: 100, height: 50, title: "applied template" });
-                    Doc.GetProto(otherdoc).description = "THIS DESCRIPTION IS REALLY IMPORTANT!";
-                    Doc.GetProto(otherdoc).summary = "THIS SUMMARY IS MEANINGFUL!";
-                    Doc.GetProto(otherdoc).photo = new ImageField("http://www.cs.brown.edu/~bcz/snowbeast.JPG");
                     Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document);
-                    Doc.GetProto(otherdoc).publication = new List<Doc>([
-                        Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
-                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
-                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
-                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
-                        Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
-                    ]);
                     this.props.addDocTab && this.props.addDocTab(otherdoc, otherdoc, "onRight");
                 }), icon: "project-diagram"
             });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 71964ef82..c6f003a81 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -370,7 +370,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     }
 
     private childViews = () => [
-        <CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} />,
+        <CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} DataDoc={this.props.DataDoc} />,
         ...this.views
     ]
     render() {
@@ -387,7 +387,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                         easing={easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
 
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
-                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
+                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.DataDoc} inkFieldKey={this.props.fieldKey + "_ink"} >
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
@@ -414,6 +414,7 @@ class CollectionFreeFormOverlayView extends React.Component<DocumentViewProps &
 @observer
 class CollectionFreeFormBackgroundView extends React.Component<DocumentViewProps & { isSelected: () => boolean }> {
     @computed get backgroundView() {
+        let props = this.props;
         return (<DocumentContentsView {...this.props} layoutKey={"backgroundLayout"}
             isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />);
     }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 7000352e7..6adead626 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -203,6 +203,7 @@ class Viewer extends React.Component<IViewerProps> {
             this._isPage[page] = "page";
             this._visibleElements[page] = (
                 <Page
+                    size={this._pageSizes[page]}
                     pdf={this.props.pdf}
                     page={page}
                     numPages={this.props.pdf.numPages}
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 27b3473f8..0a1964dea 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -215,7 +215,7 @@ export namespace Doc {
 
     // gets the document's prototype or returns the document if it is a prototype
     export function GetProto(doc: Doc) {
-        return Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc);
+        return Doc.GetT(doc, "isPrototype", "boolean", true) || doc.isTemplate ? doc : (doc.proto || doc);
     }
 
     export function allKeys(doc: Doc): string[] {
-- 
cgit v1.2.3-70-g09d2


From 45ded4da2592bc2a8201e1260dfb6a80485684c7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 25 Jun 2019 09:35:09 -0400
Subject: converted isTopMost into renderDepth and capped renderDepth at 7. 
 removed previous cycle detection.

---
 src/client/documents/Documents.ts                  |  6 +--
 src/client/util/DragManager.ts                     |  2 -
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/MainOverlayTextBox.tsx            |  2 +-
 src/client/views/MainView.tsx                      |  2 +-
 .../views/collections/CollectionBaseView.tsx       | 48 ++++------------------
 .../views/collections/CollectionDockingView.tsx    |  2 +-
 .../views/collections/CollectionSchemaView.tsx     |  4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  8 ++--
 src/client/views/nodes/DocumentContentsView.tsx    |  1 +
 src/client/views/nodes/DocumentView.tsx            | 11 ++---
 src/client/views/nodes/FieldView.tsx               |  4 +-
 src/client/views/nodes/KeyValuePair.tsx            |  2 +-
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 14 files changed, 31 insertions(+), 65 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b04fc401a..ac8a892b8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -344,7 +344,7 @@ export namespace Docs {
         {layout}
     </div>
     <div style="height:(100% + 25px); width:100%; position:absolute">
-        <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+        <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} renderDepth={renderDepth}/>
     </div>
 </div>       
         `);
@@ -356,7 +356,7 @@ export namespace Docs {
             {layout}
         </div>
         <div style="height:25px; width:100%; position:absolute">
-            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} renderDepth={renderDepth}/>
         </div>
     </div>       
             `);
@@ -379,7 +379,7 @@ export namespace Docs {
             {layout}
         </div>
         <div style="height:15%; width:100%; position:absolute">
-            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/>
+            <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} renderDepth={renderDepth}/>
         </div>
     </div>       
             `);
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 3143924fc..442187912 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -28,7 +28,6 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: ()
         document.removeEventListener('pointerup', onRowUp);
     };
     let onItemDown = async (e: React.PointerEvent) => {
-        // if (this.props.isSelected() || this.props.isTopMost) {
         if (e.button === 0) {
             e.stopPropagation();
             if (e.shiftKey && CollectionDockingView.Instance) {
@@ -38,7 +37,6 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: ()
                 document.addEventListener("pointerup", onRowUp);
             }
         }
-        //}
     };
     return onItemDown;
 }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 9d5844426..042306997 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -153,7 +153,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
         return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
-            if (documentView.props.isTopMost) {
+            if (documentView.props.renderDepth === 0) {
                 return bounds;
             }
             let transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse();
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index b2cfc82c4..7363b08ef 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -123,7 +123,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
                         <FormattedTextBox color={`${this._textColor}`} fieldKey={this.TextFieldKey} hideOnLeave={this._textHideOnLeave} isOverlay={true}
                             Document={FormattedTextBox.InputBoxOverlay.props.Document}
                             DataDoc={FormattedTextBox.InputBoxOverlay.props.DataDoc}
-                            isSelected={returnTrue} select={emptyFunction} isTopMost={true} selectOnLoad={true}
+                            isSelected={returnTrue} select={emptyFunction} renderDepth={0} selectOnLoad={true}
                             ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
                             ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} addDocTab={this.addDocTab} outer_div={(dominus: HTMLElement) => this._dominus = dominus} />
                     </div>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index a72f25b99..d26e24748 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -211,7 +211,7 @@ export class MainView extends React.Component {
                 ContentScaling={returnOne}
                 PanelWidth={this.getPWidth}
                 PanelHeight={this.getPHeight}
-                isTopMost={true}
+                renderDepth={0}
                 selectOnLoad={false}
                 focus={emptyFunction}
                 parentActive={returnTrue}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 79a9f3be0..50d1a5071 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -64,8 +64,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     active = (): boolean => {
         var isSelected = this.props.isSelected();
-        var topMost = this.props.isTopMost;
-        return isSelected || this._isChildActive || topMost;
+        return isSelected || this._isChildActive || this.props.renderDepth === 0;
     }
 
     //TODO should this be observable?
@@ -75,32 +74,6 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         this.props.whenActiveChanged(isActive);
     }
 
-    createsCycle(documentToAdd: Doc, containerDocument: Doc): boolean {
-        if (!(documentToAdd instanceof Doc)) {
-            return false;
-        }
-        if (StrCast(documentToAdd.layout).indexOf("CollectionView") !== -1) {
-            let data = DocListCast(documentToAdd.data);
-            for (const doc of data) {
-                if (this.createsCycle(doc, containerDocument)) {
-                    return true;
-                }
-            }
-        }
-        let annots = DocListCast(documentToAdd.annotations);
-        for (const annot of annots) {
-            if (this.createsCycle(annot, containerDocument)) {
-                return true;
-            }
-        }
-        for (let containerProto: Opt<Doc> = containerDocument; containerProto !== undefined; containerProto = FieldValue(containerProto.proto)) {
-            if (containerProto[Id] === documentToAdd[Id]) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
         var curPage = NumCast(this.props.Document.curPage, -1);
@@ -109,19 +82,16 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             Doc.GetProto(doc).annotationOn = this.props.Document;
         }
         allowDuplicates = true;
-        if (!this.createsCycle(doc, this.dataDoc)) {
-            //TODO This won't create the field if it doesn't already exist
-            const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc));
-            if (value !== undefined) {
-                if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
-                    value.push(doc);
-                }
-            } else {
-                Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new List([doc]));
+        //TODO This won't create the field if it doesn't already exist
+        const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc));
+        if (value !== undefined) {
+            if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
+                value.push(doc);
             }
-            return true;
+        } else {
+            Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new List([doc]));
         }
-        return false;
+        return true;
     }
 
     @action.bound
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 82cb5dbbb..6d2f61173 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -535,7 +535,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     PanelWidth={this.nativeWidth}
                     PanelHeight={this.nativeHeight}
                     ScreenToLocalTransform={this.ScreenToLocalTransform}
-                    isTopMost={true}
+                    renderDepth={0}
                     selectOnLoad={false}
                     parentActive={returnTrue}
                     whenActiveChanged={emptyFunction}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index b4158a5b1..f03afe7e0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -104,7 +104,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             ContainingCollectionView: this.props.CollectionView,
             isSelected: returnFalse,
             select: emptyFunction,
-            isTopMost: false,
+            renderDepth: this.props.renderDepth + 1,
             selectOnLoad: false,
             ScreenToLocalTransform: Transform.Identity,
             focus: emptyFunction,
@@ -454,7 +454,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                 <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.centeringOffset}px, 0px)`, height: "100%" }}>
                     <DocumentView
                         DataDoc={this.props.DataDocument}
-                        Document={this.props.Document} isTopMost={false} selectOnLoad={false}
+                        Document={this.props.Document} renderDepth={0} selectOnLoad={false}
                         addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} moveDocument={this.props.moveDocument}
                         ScreenToLocalTransform={this.getTransform}
                         ContentScaling={this.contentScaling}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c6f003a81..05909c9f7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -199,7 +199,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             var dv = DocumentManager.Instance.getDocumentView(doc);
             return dv && SelectionManager.IsSelected(dv) ? true : false;
         });
-        if (!this.props.isSelected() && !childSelected && !this.props.isTopMost) {
+        if (!this.props.isSelected() && !childSelected && this.props.renderDepth > 0) {
             return;
         }
         e.stopPropagation();
@@ -303,7 +303,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             removeDocument: this.props.removeDocument,
             moveDocument: this.props.moveDocument,
             ScreenToLocalTransform: this.getTransform,
-            isTopMost: false,
+            renderDepth: this.props.renderDepth + 1,
             selectOnLoad: layoutDoc[Id] === this._selectOnLoaded,
             PanelWidth: layoutDoc[WidthSym],
             PanelHeight: layoutDoc[HeightSym],
@@ -404,7 +404,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 class CollectionFreeFormOverlayView extends React.Component<DocumentViewProps & { isSelected: () => boolean }> {
     @computed get overlayView() {
         return (<DocumentContentsView {...this.props} layoutKey={"overlayLayout"}
-            isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />);
+            renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />);
     }
     render() {
         return this.overlayView;
@@ -416,7 +416,7 @@ class CollectionFreeFormBackgroundView extends React.Component<DocumentViewProps
     @computed get backgroundView() {
         let props = this.props;
         return (<DocumentContentsView {...this.props} layoutKey={"backgroundLayout"}
-            isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />);
+            renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />);
     }
     render() {
         return this.props.Document.backgroundLayout ? this.backgroundView : (null);
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index a4316c143..0da4888a1 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -103,6 +103,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     }
 
     render() {
+        if (this.props.renderDepth > 7) return (null);
         if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
         return <ObserverJsxParser
             components={{ FormattedTextBox, ImageBox, IconBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 5530d5c01..c586885a3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -72,7 +72,7 @@ export interface DocumentViewProps {
     removeDocument?: (doc: Doc) => boolean;
     moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
     ScreenToLocalTransform: () => Transform;
-    isTopMost: boolean;
+    renderDepth: number;
     ContentScaling: () => number;
     PanelWidth: () => number;
     PanelHeight: () => number;
@@ -120,7 +120,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     public get ContentDiv() { return this._mainCont.current; }
     @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); }
-    @computed get topMost(): boolean { return this.props.isTopMost; }
+    @computed get topMost(): boolean { return this.props.renderDepth === 0; }
     @computed get templates(): List<string> {
         let field = this.props.Document.templates;
         if (field && field instanceof List) {
@@ -268,7 +268,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.stopPropagation();
         let altKey = e.altKey;
         let ctrlKey = e.ctrlKey;
-        if (this._doubleTap && !this.props.isTopMost) {
+        if (this._doubleTap && !this.props.renderDepth) {
             this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab");
             SelectionManager.DeselectAll();
             this.props.Document.libraryBrush = false;
@@ -436,7 +436,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @action
     addTemplate = (template: Template) => {
         this.templates.push(template.Layout);
-        this.templates = this.templates;
     }
 
     @action
@@ -447,7 +446,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 break;
             }
         }
-        this.templates = this.templates;
     }
 
     freezeNativeDimensions = (): void => {
@@ -549,7 +547,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%";
         var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
         return (
-            <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`}
+            <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
                 style={{
                     outlineColor: "maroon",
@@ -565,7 +563,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     transform: `scale(${scaling}, ${scaling})`
                 }}
                 onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
-
                 onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}
             >
                 {this.contents}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 8879da55f..374a523cb 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -33,7 +33,7 @@ export interface FieldViewProps {
     DataDoc: Doc;
     isSelected: () => boolean;
     select: (isCtrlPressed: boolean) => void;
-    isTopMost: boolean;
+    renderDepth: number;
     selectOnLoad: boolean;
     addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean;
     addDocTab: (document: Doc, dataDoc: Doc, where: string) => void;
@@ -97,7 +97,7 @@ export class FieldView extends React.Component<FieldViewProps> {
             //         ContentScaling={returnOne}
             //         PanelWidth={returnHundred}
             //         PanelHeight={returnHundred}
-            //         isTopMost={true} //TODO Why is this top most?
+            //         renderDepth={0} //TODO Why is renderDepth reset?
             //         selectOnLoad={false}
             //         focus={emptyFunction}
             //         isSelected={this.props.isSelected}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 3e03e7e75..3dda81db7 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -32,7 +32,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             fieldKey: this.props.keyName,
             isSelected: returnFalse,
             select: emptyFunction,
-            isTopMost: false,
+            renderDepth: 1,
             selectOnLoad: false,
             active: returnFalse,
             whenActiveChanged: emptyFunction,
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index b9e93b4da..10c66d318 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -492,7 +492,7 @@ interface IAnnotationProps {
 //                         <DocumentView Document={targetDoc}
 //                             ContainingCollectionView={undefined}
 //                             ScreenToLocalTransform={this.props.parent.props.parent.props.ScreenToLocalTransform}
-//                             isTopMost={false}
+//                             renderDepth={1} // what should renderDepth be?
 //                             ContentScaling={() => 1}
 //                             PanelWidth={() => NumCast(this.props.parent.props.parent.Document.nativeWidth)}
 //                             PanelHeight={() => NumCast(this.props.parent.props.parent.Document.nativeHeight)}
-- 
cgit v1.2.3-70-g09d2


From 8af69f89c93b7f4287c1fba237ea42aa741c4137 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 25 Jun 2019 16:42:02 -0400
Subject: testing stuff for document field extensions.

---
 src/client/views/DocumentDecorations.tsx                     | 10 ++++------
 src/client/views/collections/CollectionBaseView.tsx          | 12 +++++++++---
 src/client/views/collections/CollectionSchemaView.tsx        |  1 +
 src/client/views/collections/CollectionSubView.tsx           | 11 +++++++++--
 .../collectionFreeForm/CollectionFreeFormView.tsx            | 11 ++++++++++-
 src/client/views/nodes/FieldView.tsx                         |  5 ++---
 src/client/views/nodes/KeyValuePair.tsx                      |  1 +
 7 files changed, 36 insertions(+), 15 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 042306997..9ce68d200 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -80,14 +80,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 let field = SelectionManager.SelectedDocuments()[0];
                 let collection = field.props.ContainingCollectionView!.props.Document;
 
-                let metaKey = text.slice(1, text.length - 1);
-                let metaKeyProp = `fieldKey={"${metaKey}"}`;
-                let metaAnoKey = metaKey + "_annotations";
-                let metaAnoKeyProp = `fieldKey={"${metaAnoKey}"}`;
                 let collectionKey = field.props.ContainingCollectionView!.props.fieldKey;
                 let collectionKeyProp = `fieldKey={"${collectionKey}"}`;
-                let collectionAnoKey = "annotations";
-                let collectionAnoKeyProp = `fieldKey={"${collectionAnoKey}"}`;
+                let collectionAnoKeyProp = `fieldKey={"annotations"}`;
+                let metaKey = text.slice(1, text.length);
+                let metaKeyProp = `fieldKey={"${metaKey}"}`;
+                let metaAnoKeyProp = `fieldKey={"${metaKey}"} fieldExt={"annotations"}`;
 
                 let template = Doc.MakeAlias(field.props.Document);
                 template.proto = collection;
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 50d1a5071..bb5cad6f3 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -74,6 +74,13 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         this.props.whenActiveChanged(isActive);
     }
 
+    @computed get extDoc() {
+        return this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.dataDoc[this.props.fieldKey + "_ext"] as Doc : this.dataDoc;
+    }
+    @computed get extField() {
+        return this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.props.fieldExt : this.props.fieldKey;
+    }
+
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
         var curPage = NumCast(this.props.Document.curPage, -1);
@@ -82,14 +89,13 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             Doc.GetProto(doc).annotationOn = this.props.Document;
         }
         allowDuplicates = true;
-        //TODO This won't create the field if it doesn't already exist
-        const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc));
+        const value = Cast(this.extDoc[this.extField], listSpec(Doc));
         if (value !== undefined) {
             if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
                 value.push(doc);
             }
         } else {
-            Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new List([doc]));
+            Doc.SetOnPrototype(this.extDoc, this.extField, new List([doc]));
         }
         return true;
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index b3d8451dc..17d87be7e 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -101,6 +101,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             Document: rowProps.original,
             DataDoc: rowProps.original,
             fieldKey: rowProps.column.id as string,
+            fieldExt: "",
             ContainingCollectionView: this.props.CollectionView,
             isSelected: returnFalse,
             select: emptyFunction,
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a887d8ec8..caf6aa0c9 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,4 +1,4 @@
-import { action } from "mobx";
+import { action, computed } from "mobx";
 import * as rp from 'request-promise';
 import CursorField from "../../../new_fields/CursorField";
 import { Doc, DocListCast, Opt } from "../../../new_fields/Doc";
@@ -45,10 +45,17 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
+
+        @computed get extDoc() {
+            return this.props.DataDoc && this.props.fieldExt && this.props.DataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.props.DataDoc[this.props.fieldKey + "_ext"] as Doc : this.props.DataDoc;
+        }
+        @computed get extField() {
+            return this.props.DataDoc && this.props.fieldExt && this.props.DataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.props.fieldExt : this.props.fieldKey;
+        }
         get childDocs() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document)[this.props.fieldKey]);
+            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.extDoc : this.props.Document)[this.extField]);
         }
 
         @action
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 05909c9f7..a9db64f81 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -27,6 +27,8 @@ import React = require("react");
 import v5 = require("uuid/v5");
 import PDFMenu from "../../pdf/PDFMenu";
 import { ContextMenu } from "../../ContextMenu";
+import { Docs } from "../../../documents/Documents";
+import { thisExpression } from "babel-types";
 
 export const panZoomSchema = createSchema({
     panX: "number",
@@ -369,6 +371,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         });
     }
 
+    @computed get extDoc() {
+        return this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.dataDoc[this.props.fieldKey + "_ext"] as Doc : this.dataDoc;
+    }
+
     private childViews = () => [
         <CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} DataDoc={this.props.DataDoc} />,
         ...this.views
@@ -376,6 +382,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     render() {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
+        if (this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] === undefined) {
+            setTimeout(() => { console.log("Extending: " + this.dataDoc.title); let doc = new Doc(this.dataDoc[Id] + this.props.fieldKey, true); doc.title = "Extension"; this.dataDoc[this.props.fieldKey + "_ext"] = doc; }, 0);
+        }
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
                 style={{ borderRadius: "inherit" }}
@@ -387,7 +396,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                         easing={easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
 
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
-                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.DataDoc} inkFieldKey={this.props.fieldKey + "_ink"} >
+                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.extDoc} inkFieldKey={this.props.fieldExt ? "ink" : this.props.fieldKey + "_ink"} >
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 374a523cb..5688f9c53 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -7,18 +7,16 @@ import { IconField } from "../../../new_fields/IconField";
 import { List } from "../../../new_fields/List";
 import { RichTextField } from "../../../new_fields/RichTextField";
 import { AudioField, ImageField, VideoField } from "../../../new_fields/URLField";
-import { emptyFunction, returnFalse, returnOne } from "../../../Utils";
 import { Transform } from "../../util/Transform";
 import { CollectionPDFView } from "../collections/CollectionPDFView";
 import { CollectionVideoView } from "../collections/CollectionVideoView";
 import { CollectionView } from "../collections/CollectionView";
 import { AudioBox } from "./AudioBox";
-import { DocumentContentsView } from "./DocumentContentsView";
 import { FormattedTextBox } from "./FormattedTextBox";
 import { IconBox } from "./IconBox";
 import { ImageBox } from "./ImageBox";
-import { VideoBox } from "./VideoBox";
 import { PDFBox } from "./PDFBox";
+import { VideoBox } from "./VideoBox";
 
 
 //
@@ -28,6 +26,7 @@ import { PDFBox } from "./PDFBox";
 //
 export interface FieldViewProps {
     fieldKey: string;
+    fieldExt: string;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Doc;
     DataDoc: Doc;
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 3dda81db7..ede4e3858 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -30,6 +30,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             DataDoc: this.props.doc,
             ContainingCollectionView: undefined,
             fieldKey: this.props.keyName,
+            fieldExt: "",
             isSelected: returnFalse,
             select: emptyFunction,
             renderDepth: 1,
-- 
cgit v1.2.3-70-g09d2


From e49fa36db6eab77bcd89c48969f555ae0579aa9a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 25 Jun 2019 19:03:25 -0400
Subject: fixed setup of documents to extend fields

---
 src/client/views/collections/CollectionBaseView.tsx            |  2 +-
 src/client/views/collections/CollectionView.tsx                |  2 +-
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx  |  5 +++--
 src/client/views/nodes/FieldView.tsx                           |  3 ++-
 src/new_fields/Doc.ts                                          | 10 ++++++++++
 5 files changed, 17 insertions(+), 5 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index bb5cad6f3..13c4a33a8 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> {
                 value.push(doc);
             }
         } else {
-            Doc.SetOnPrototype(this.extDoc, this.extField, new List([doc]));
+            Doc.GetProto(this.extDoc)[this.extField] = new List([doc]);
         }
         return true;
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index cc097f371..ab1dbc499 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -43,7 +43,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
         return (null);
     }
 
-    get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's?
+    get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldExt === "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
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a9db64f81..9f4daf38d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -50,7 +50,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
-    public get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; }
+    public get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldExt === "annotations"; }
     private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
     private panX = () => this.Document.panX || 0;
     private panY = () => this.Document.panY || 0;
@@ -383,7 +383,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
         if (this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] === undefined) {
-            setTimeout(() => { console.log("Extending: " + this.dataDoc.title); let doc = new Doc(this.dataDoc[Id] + this.props.fieldKey, true); doc.title = "Extension"; this.dataDoc[this.props.fieldKey + "_ext"] = doc; }, 0);
+            console.log("Timeout " + this.dataDoc.title + " " + this.props.fieldKey);
+            setTimeout(() => Doc.MakeFieldExtension(this.dataDoc, this.props.fieldKey), 0);
         }
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 5688f9c53..8a481144e 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -17,6 +17,7 @@ import { IconBox } from "./IconBox";
 import { ImageBox } from "./ImageBox";
 import { PDFBox } from "./PDFBox";
 import { VideoBox } from "./VideoBox";
+import { Id } from "../../../new_fields/FieldSymbols";
 
 
 //
@@ -85,7 +86,7 @@ export class FieldView extends React.Component<FieldViewProps> {
             return <p>{field.date.toLocaleString()}</p>;
         }
         else if (field instanceof Doc) {
-            return <p><b>{field.title}</b></p>;
+            return <p><b>{field.title + " + " + field[Id]}</b></p>;
             // let returnHundred = () => 100;
             // return (
             //     <DocumentContentsView Document={field}
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index e0937c619..621f87981 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -249,6 +249,16 @@ export namespace Doc {
         return true;
     }
 
+    export function MakeFieldExtension(doc: Doc, fieldKey: string) {
+        let fieldExtension = new Doc(doc[Id] + fieldKey, true);
+        fieldExtension.title = "Extension of " + doc.title + "'s field:" + fieldKey;
+        let proto: Doc | undefined = doc;
+        while (proto && !Doc.IsPrototype(proto)) {
+            proto = proto.proto;
+        }
+        (proto ? proto : doc)[fieldKey + "_ext"] = fieldExtension;
+    }
+
     export function MakeAlias(doc: Doc) {
         if (!GetT(doc, "isPrototype", "boolean", true)) {
             return Doc.MakeCopy(doc);
-- 
cgit v1.2.3-70-g09d2


From 46c51661acb042ed2779d26a6a8305ec15bec25b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 25 Jun 2019 20:18:06 -0400
Subject: cleaned up version of templates with annotations.

---
 .../views/collections/CollectionBaseView.tsx       | 11 ++++-----
 src/client/views/collections/CollectionSubView.tsx |  6 +++--
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 10 +-------
 src/client/views/nodes/ImageBox.tsx                |  4 ++--
 src/new_fields/Doc.ts                              | 27 ++++++++++++++--------
 5 files changed, 30 insertions(+), 28 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 13c4a33a8..22e8259e7 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -1,16 +1,16 @@
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc, DocListCast, Opt } from '../../../new_fields/Doc';
+import { Doc } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
 import { listSpec } from '../../../new_fields/Schema';
-import { Cast, FieldValue, NumCast, PromiseValue, StrCast, BoolCast } from '../../../new_fields/Types';
+import { BoolCast, Cast, NumCast, PromiseValue } from '../../../new_fields/Types';
+import { DocumentManager } from '../../util/DocumentManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
 import './CollectionBaseView.scss';
-import { DocumentManager } from '../../util/DocumentManager';
 
 export enum CollectionViewType {
     Invalid,
@@ -36,7 +36,6 @@ export interface CollectionViewProps extends FieldViewProps {
     contentRef?: React.Ref<HTMLDivElement>;
 }
 
-
 @observer
 export class CollectionBaseView extends React.Component<CollectionViewProps> {
     @observable private static _safeMode = false;
@@ -75,10 +74,10 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
     }
 
     @computed get extDoc() {
-        return this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.dataDoc[this.props.fieldKey + "_ext"] as Doc : this.dataDoc;
+        return Doc.extDoc(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
     }
     @computed get extField() {
-        return this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.props.fieldExt : this.props.fieldKey;
+        return Doc.extField(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
     }
 
     @action.bound
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index caf6aa0c9..1b1f765ed 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -45,13 +45,15 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
+        @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
 
         @computed get extDoc() {
-            return this.props.DataDoc && this.props.fieldExt && this.props.DataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.props.DataDoc[this.props.fieldKey + "_ext"] as Doc : this.props.DataDoc;
+            return Doc.extDoc(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
         }
         @computed get extField() {
-            return this.props.DataDoc && this.props.fieldExt && this.props.DataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.props.fieldExt : this.props.fieldKey;
+            return Doc.extField(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
         }
+
         get childDocs() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9f4daf38d..7489af1aa 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -47,7 +47,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private get _pwidth() { return this.props.PanelWidth(); }
     private get _pheight() { return this.props.PanelHeight(); }
 
-    @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
     public get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldExt === "annotations"; }
@@ -371,10 +370,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         });
     }
 
-    @computed get extDoc() {
-        return this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] instanceof Doc ? this.dataDoc[this.props.fieldKey + "_ext"] as Doc : this.dataDoc;
-    }
-
     private childViews = () => [
         <CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} DataDoc={this.props.DataDoc} />,
         ...this.views
@@ -382,10 +377,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     render() {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
-        if (this.dataDoc && this.props.fieldExt && this.dataDoc[this.props.fieldKey + "_ext"] === undefined) {
-            console.log("Timeout " + this.dataDoc.title + " " + this.props.fieldKey);
-            setTimeout(() => Doc.MakeFieldExtension(this.dataDoc, this.props.fieldKey), 0);
-        }
+        if (this.props.fieldExt) Doc.UpdateFieldExtension(this.dataDoc, this.props.fieldKey);
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
                 style={{ borderRadius: "inherit" }}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 008a09130..09bf21228 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -69,14 +69,14 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
         if (de.data instanceof DragManager.DocumentDragData) {
             de.data.droppedDocuments.forEach(action((drop: Doc) => {
                 if (/*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) {
-                    this.dataDoc[this.props.fieldKey] = new ImageField(drop.data.url);
+                    Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url);
                     e.stopPropagation();
                 } else {
                     let layout = StrCast(drop.backgroundLayout);
                     if (layout.indexOf(ImageBox.name) !== -1) {
                         let imgData = this.dataDoc[this.props.fieldKey];
                         if (imgData instanceof ImageField) {
-                            Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new List([imgData]));
+                            Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new List([imgData]);
                         }
                         let imgList = Cast(this.dataDoc[this.props.fieldKey], listSpec(ImageField), [] as any[]);
                         if (imgList) {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 621f87981..675278ed5 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -224,7 +224,7 @@ export namespace Doc {
 
     // gets the document's prototype or returns the document if it is a prototype
     export function GetProto(doc: Doc) {
-        return Doc.GetT(doc, "isPrototype", "boolean", true) || doc.isTemplate ? doc : (doc.proto || doc);
+        return Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc);
     }
 
     export function allKeys(doc: Doc): string[] {
@@ -249,16 +249,25 @@ export namespace Doc {
         return true;
     }
 
-    export function MakeFieldExtension(doc: Doc, fieldKey: string) {
-        let fieldExtension = new Doc(doc[Id] + fieldKey, true);
-        fieldExtension.title = "Extension of " + doc.title + "'s field:" + fieldKey;
-        let proto: Doc | undefined = doc;
-        while (proto && !Doc.IsPrototype(proto)) {
-            proto = proto.proto;
+    export function extDoc(doc: Doc, fieldKey: string, fieldExt: string) {
+        return doc && fieldExt && doc[fieldKey + "_ext"] instanceof Doc ? doc[fieldKey + "_ext"] as Doc : doc;
+    }
+    export function extField(doc: Doc, fieldKey: string, fieldExt: string) {
+        return doc && fieldExt && doc[fieldKey + "_ext"] instanceof Doc ? fieldExt : fieldKey;
+    }
+    export function UpdateFieldExtension(doc: Doc, fieldKey: string) {
+        if (doc && doc[fieldKey + "_ext"] === undefined) {
+            setTimeout(() => {
+                let fieldExtension = new Doc(doc[Id] + fieldKey, true);
+                fieldExtension.title = "Extension of " + doc.title + "'s field:" + fieldKey;
+                let proto: Doc | undefined = doc;
+                while (proto && !Doc.IsPrototype(proto)) {
+                    proto = proto.proto;
+                }
+                (proto ? proto : doc)[fieldKey + "_ext"] = fieldExtension;
+            }, 0);
         }
-        (proto ? proto : doc)[fieldKey + "_ext"] = fieldExtension;
     }
-
     export function MakeAlias(doc: Doc) {
         if (!GetT(doc, "isPrototype", "boolean", true)) {
             return Doc.MakeCopy(doc);
-- 
cgit v1.2.3-70-g09d2


From 24d835913f919d99df56303982c38a441ac57e59 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 25 Jun 2019 21:17:42 -0400
Subject: more cleanup

---
 src/client/views/DocumentDecorations.tsx           |  7 ++--
 .../views/collections/CollectionBaseView.tsx       |  4 +-
 src/client/views/collections/CollectionSubView.tsx | 11 ++----
 .../views/collections/CollectionTreeView.tsx       | 43 +---------------------
 src/client/views/collections/CollectionView.tsx    |  5 ++-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  2 +-
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 src/client/views/nodes/PDFBox.tsx                  |  2 +-
 9 files changed, 19 insertions(+), 59 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 9ce68d200..e8ea7d5fc 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -82,10 +82,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
                 let collectionKey = field.props.ContainingCollectionView!.props.fieldKey;
                 let collectionKeyProp = `fieldKey={"${collectionKey}"}`;
-                let collectionAnoKeyProp = `fieldKey={"annotations"}`;
                 let metaKey = text.slice(1, text.length);
                 let metaKeyProp = `fieldKey={"${metaKey}"}`;
-                let metaAnoKeyProp = `fieldKey={"${metaKey}"} fieldExt={"annotations"}`;
 
                 let template = Doc.MakeAlias(field.props.Document);
                 template.proto = collection;
@@ -95,10 +93,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 template.embed = true;
                 template.isTemplate = true;
                 template.templates = new List<string>([Templates.TitleBar(metaKey)]);
-                template.layout = StrCast(field.props.Document.layout).replace(collectionKeyProp, metaKeyProp);
                 if (field.props.Document.backgroundLayout) {
+                    let metaAnoKeyProp = `fieldKey={"${metaKey}"} fieldExt={"annotations"}`;
+                    let collectionAnoKeyProp = `fieldKey={"annotations"}`;
                     template.layout = StrCast(field.props.Document.layout).replace(collectionAnoKeyProp, metaAnoKeyProp);
                     template.backgroundLayout = StrCast(field.props.Document.backgroundLayout).replace(collectionKeyProp, metaKeyProp);
+                } else {
+                    template.layout = StrCast(field.props.Document.layout).replace(collectionKeyProp, metaKeyProp);
                 }
                 Doc.AddDocToList(collection, collectionKey, template);
                 SelectionManager.SelectedDocuments().map(dv => dv.props.removeDocument && dv.props.removeDocument(dv.props.Document));
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 22e8259e7..4ef84ac66 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -59,7 +59,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         }
     }
 
-    @computed get dataDoc() { return (BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document); }
+    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
 
     active = (): boolean => {
         var isSelected = this.props.isSelected();
@@ -104,7 +104,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
         docView && SelectionManager.DeselectDoc(docView);
         //TODO This won't create the field if it doesn't already exist
-        const value = Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc), []);
+        const value = Cast(this.extDoc[this.extField], listSpec(Doc), []);
         let index = value.reduce((p, v, i) => (v instanceof Doc && v[Id] === doc[Id]) ? i : p, -1);
         PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn =>
             annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined)
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 1b1f765ed..f1f1d9127 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -45,14 +45,9 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
-        @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
-
-        @computed get extDoc() {
-            return Doc.extDoc(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
-        }
-        @computed get extField() {
-            return Doc.extField(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
-        }
+        @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+        @computed get extDoc() { return Doc.extDoc(this.dataDoc, this.props.fieldKey, this.props.fieldExt); }
+        @computed get extField() { return Doc.extField(this.dataDoc, this.props.fieldKey, this.props.fieldExt); }
 
         get childDocs() {
             //TODO tfs: This might not be what we want?
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index f5f323269..eeacb02e8 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -89,7 +89,7 @@ class TreeView extends React.Component<TreeViewProps> {
         return keyList.length ? keyList[0] : "data";
     }
 
-    @computed get dataDoc() { return (BoolCast(this.props.document.isTemplate) ? this.props.dataDoc : this.props.document); }
+    @computed get dataDoc() { return BoolCast(this.props.document.isTemplate) ? this.props.dataDoc : this.props.document; }
 
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
         this._treedropDisposer && this._treedropDisposer();
@@ -171,45 +171,7 @@ class TreeView extends React.Component<TreeViewProps> {
         height={36}
         fontStyle={style}
         GetValue={() => StrCast(this.props.document[key])}
-        SetValue={(value: string) => {
-            let res = (Doc.GetProto(this.dataDoc)[key] = value) ? true : true;
-
-            if (value.startsWith(">")) {
-                let metaKey = value.slice(value.startsWith(">>>") ? 3 : value.startsWith(">>") ? 2 : 1, value.length);
-                let collection = this.props.containingCollection;
-                let template = Doc.MakeAlias(collection);
-                template.title = metaKey;
-                template.embed = true;
-                template.x = 0;
-                template.y = 0;
-                template.width = 300;
-                template.height = 300;
-                template.isTemplate = true;
-                template.templates = new List<string>([Templates.TitleBar(metaKey)]);//`{props.DataDoc.${metaKey}_text}`)]);
-                if (value.startsWith(">>>")) { // Collection
-                    Doc.GetProto(collection)[metaKey] = new List<Doc>([
-                        Docs.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { width: 300, height: 300 }),
-                        Docs.TextDocument({ documentText: "hello world!", width: 300, height: 300 }),
-                    ]);
-                    template.layout = CollectionView.LayoutString(metaKey);
-                    template.viewType = CollectionViewType.Freeform;
-                } else if (value.startsWith(">>")) { // Image
-                    Doc.GetProto(collection)[metaKey] = new ImageField("http://www.cs.brown.edu/~bcz/face.gif");
-                    template.layout = ImageBox.LayoutString(metaKey);
-                    template.nativeWidth = 300;
-                    template.nativeHeight = 300;
-                } else if (value.startsWith(">")) {  // Text
-                    Doc.GetProto(collection)[metaKey] = "-empty field-";
-                    template.layout = FormattedTextBox.LayoutString(metaKey);
-                    template.width = 100;
-                    template.height = 50;
-                }
-                Doc.AddDocToList(collection, "data", template);
-                this.delete();
-            }
-
-            return res;
-        }}
+        SetValue={(value: string) => (Doc.GetProto(this.dataDoc)[key] = value) ? true : true}
         OnFillDown={(value: string) => {
             Doc.GetProto(this.dataDoc)[key] = value;
             let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) });
@@ -456,7 +418,6 @@ export class CollectionTreeView extends CollectionSubView(Document) {
 
     outerXf = () => Utils.GetScreenTransform(this._mainEle!);
     onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {});
-    @computed get dataDoc() { return (BoolCast(this.props.DataDoc.isTemplate) ? this.props.DataDoc : this.props.Document); }
 
     render() {
         let dropAction = StrCast(this.props.Document.dropAction) as dropActionType;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index ab1dbc499..a133eacb1 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -58,7 +58,10 @@ export class CollectionView extends React.Component<FieldViewProps> {
             ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems });
             ContextMenu.Instance.addItem({
                 description: "Apply Template", event: undoBatch(() => {
-                    let otherdoc = Docs.TextDocument({ width: 100, height: 50, title: "applied template" });
+                    let otherdoc = new Doc();
+                    otherdoc.width = 100;
+                    otherdoc.height = 50;
+                    Doc.GetProto(otherdoc).title = "applied(" + this.props.Document.title + ")";
                     Doc.GetProto(otherdoc).layout = Doc.MakeDelegate(this.props.Document);
                     this.props.addDocTab && this.props.addDocTab(otherdoc, otherdoc, "onRight");
                 }), icon: "project-diagram"
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7489af1aa..cbd9e3de3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -298,7 +298,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     getDocumentViewProps(layoutDoc: Doc): DocumentViewProps {
         return {
-            DataDoc: this.props.DataDoc !== this.props.Document && !BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : layoutDoc,
+            DataDoc: BoolCast(this.props.Document.isTemplate) ? layoutDoc : this.props.DataDoc,
             Document: layoutDoc,
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index c18bc8f22..0a1a86226 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -110,7 +110,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         }
     }
 
-    @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
 
     dispatchTransaction = (tx: Transaction) => {
         if (this._editorView) {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 09bf21228..0da774db1 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -46,7 +46,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
     private dropDisposer?: DragManager.DragDropDisposer;
 
 
-    @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
 
 
     protected createDropTarget = (ele: HTMLDivElement) => {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 61789bb30..f8bf5faf3 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -27,7 +27,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
 
     @observable private _alt = false;
     @observable private _scrollY: number = 0;
-    @computed get dataDoc() { return this.props.DataDoc && BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
 
     private _reactionDisposer?: IReactionDisposer;
 
-- 
cgit v1.2.3-70-g09d2


From 5f3ba2363b74dc493b96ef2253560a48d3a7c711 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 25 Jun 2019 22:16:07 -0400
Subject: final cleanup for now

---
 src/client/views/DocumentDecorations.tsx           |  9 +++-----
 .../views/collections/CollectionBaseView.tsx       | 16 +++++---------
 src/client/views/collections/CollectionSubView.tsx | 13 ++++++-----
 .../views/collections/CollectionTreeView.tsx       |  8 ++-----
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 12 +++++------
 src/new_fields/Doc.ts                              | 25 +++++++++++++---------
 6 files changed, 36 insertions(+), 47 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index e8ea7d5fc..b9537fca6 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -3,10 +3,11 @@ import { faLink } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, WidthSym, HeightSym } from "../../new_fields/Doc";
+import { Doc } from "../../new_fields/Doc";
 import { List } from "../../new_fields/List";
 import { listSpec } from "../../new_fields/Schema";
-import { Cast, NumCast, StrCast, BoolCast } from "../../new_fields/Types";
+import { BoolCast, Cast, NumCast, StrCast } from "../../new_fields/Types";
+import { URLField } from '../../new_fields/URLField';
 import { emptyFunction, Utils } from "../../Utils";
 import { Docs } from "../documents/Documents";
 import { DocumentManager } from "../util/DocumentManager";
@@ -24,10 +25,6 @@ import { LinkMenu } from "./nodes/LinkMenu";
 import { TemplateMenu } from "./TemplateMenu";
 import { Template, Templates } from "./Templates";
 import React = require("react");
-import { URLField, ImageField } from '../../new_fields/URLField';
-import { templateLiteral } from 'babel-types';
-import { CollectionViewType } from './collections/CollectionBaseView';
-import { ImageBox } from './nodes/ImageBox';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 4ef84ac66..a4a9ec994 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -59,7 +59,8 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         }
     }
 
-    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
+    @computed get dataField() { return this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; }
 
     active = (): boolean => {
         var isSelected = this.props.isSelected();
@@ -73,13 +74,6 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         this.props.whenActiveChanged(isActive);
     }
 
-    @computed get extDoc() {
-        return Doc.extDoc(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
-    }
-    @computed get extField() {
-        return Doc.extField(this.dataDoc, this.props.fieldKey, this.props.fieldExt);
-    }
-
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
         var curPage = NumCast(this.props.Document.curPage, -1);
@@ -88,13 +82,13 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             Doc.GetProto(doc).annotationOn = this.props.Document;
         }
         allowDuplicates = true;
-        const value = Cast(this.extDoc[this.extField], listSpec(Doc));
+        const value = Cast(this.dataDoc[this.dataField], listSpec(Doc));
         if (value !== undefined) {
             if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
                 value.push(doc);
             }
         } else {
-            Doc.GetProto(this.extDoc)[this.extField] = new List([doc]);
+            Doc.GetProto(this.dataDoc)[this.dataField] = new List([doc]);
         }
         return true;
     }
@@ -104,7 +98,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
         docView && SelectionManager.DeselectDoc(docView);
         //TODO This won't create the field if it doesn't already exist
-        const value = Cast(this.extDoc[this.extField], listSpec(Doc), []);
+        const value = Cast(this.dataDoc[this.dataField], listSpec(Doc), []);
         let index = value.reduce((p, v, i) => (v instanceof Doc && v[Id] === doc[Id]) ? i : p, -1);
         PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn =>
             annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined)
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index f1f1d9127..58251cd6e 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -2,9 +2,10 @@ import { action, computed } from "mobx";
 import * as rp from 'request-promise';
 import CursorField from "../../../new_fields/CursorField";
 import { Doc, DocListCast, Opt } from "../../../new_fields/Doc";
+import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
-import { Cast, PromiseValue, BoolCast } from "../../../new_fields/Types";
+import { BoolCast, Cast } from "../../../new_fields/Types";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { RouteStore } from "../../../server/RouteStore";
 import { DocServer } from "../../DocServer";
@@ -13,12 +14,11 @@ import { DragManager } from "../../util/DragManager";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { DocComponent } from "../DocComponent";
 import { FieldViewProps } from "../nodes/FieldView";
+import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { CollectionPDFView } from "./CollectionPDFView";
 import { CollectionVideoView } from "./CollectionVideoView";
 import { CollectionView } from "./CollectionView";
 import React = require("react");
-import { FormattedTextBox } from "../nodes/FormattedTextBox";
-import { Id } from "../../../new_fields/FieldSymbols";
 
 export interface CollectionViewProps extends FieldViewProps {
     addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
@@ -45,14 +45,13 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
-        @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
-        @computed get extDoc() { return Doc.extDoc(this.dataDoc, this.props.fieldKey, this.props.fieldExt); }
-        @computed get extField() { return Doc.extField(this.dataDoc, this.props.fieldKey, this.props.fieldExt); }
+        @computed get dataDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
+        @computed get dataField() { return this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; }
 
         get childDocs() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.extDoc : this.props.Document)[this.extField]);
+            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.dataDoc : this.props.Document)[this.dataField]);
         }
 
         @action
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index eeacb02e8..3fe8f9ab5 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,7 +1,7 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faAngleRight, faCaretDown, faCaretRight, faTrashAlt, faCaretSquareRight, faCaretSquareDown } from '@fortawesome/free-solid-svg-icons';
+import { faAngleRight, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, observable, computed } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, WidthSym } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
@@ -25,10 +25,6 @@ import { CollectionSchemaPreview } from './CollectionSchemaView';
 import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import React = require("react");
-import { FormattedTextBox } from '../nodes/FormattedTextBox';
-import { ImageField } from '../../../new_fields/URLField';
-import { ImageBox } from '../nodes/ImageBox';
-import { CollectionView } from './CollectionView';
 
 
 export interface TreeViewProps {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index cbd9e3de3..dc916a613 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,6 +1,6 @@
 import { action, computed } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, HeightSym, WidthSym, DocListCastAsync } from "../../../../new_fields/Doc";
+import { Doc, DocListCastAsync, HeightSym, WidthSym } from "../../../../new_fields/Doc";
 import { Id } from "../../../../new_fields/FieldSymbols";
 import { InkField, StrokeData } from "../../../../new_fields/InkField";
 import { createSchema, makeInterface } from "../../../../new_fields/Schema";
@@ -13,11 +13,13 @@ import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
 import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
+import { ContextMenu } from "../../ContextMenu";
 import { InkingCanvas } from "../../InkingCanvas";
 import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
 import { DocumentContentsView } from "../../nodes/DocumentContentsView";
 import { DocumentViewProps, positionSchema } from "../../nodes/DocumentView";
 import { pageSchema } from "../../nodes/ImageBox";
+import PDFMenu from "../../pdf/PDFMenu";
 import { CollectionSubView } from "../CollectionSubView";
 import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
 import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
@@ -25,10 +27,6 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import v5 = require("uuid/v5");
-import PDFMenu from "../../pdf/PDFMenu";
-import { ContextMenu } from "../../ContextMenu";
-import { Docs } from "../../../documents/Documents";
-import { thisExpression } from "babel-types";
 
 export const panZoomSchema = createSchema({
     panX: "number",
@@ -377,7 +375,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     render() {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
-        if (this.props.fieldExt) Doc.UpdateFieldExtension(this.dataDoc, this.props.fieldKey);
+        if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.dataDoc, this.props.fieldKey);
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
                 style={{ borderRadius: "inherit" }}
@@ -389,7 +387,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                         easing={easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
 
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
-                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.extDoc} inkFieldKey={this.props.fieldExt ? "ink" : this.props.fieldKey + "_ink"} >
+                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.dataDoc} inkFieldKey={this.props.fieldExt ? "ink" : this.props.fieldKey + "_ink"} >
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 675278ed5..8825bc13a 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -249,22 +249,27 @@ export namespace Doc {
         return true;
     }
 
-    export function extDoc(doc: Doc, fieldKey: string, fieldExt: string) {
-        return doc && fieldExt && doc[fieldKey + "_ext"] instanceof Doc ? doc[fieldKey + "_ext"] as Doc : doc;
+    //
+    // Resolves a reference to a field by returning 'doc' if o field extension is specified,
+    // otherwise, it returns the extension document stored in doc.<fieldKey>_ext.
+    // This mechanism allows any fields to be extended with an extension document that can
+    // be used to capture field-specific metadata.  For example, an image field can be extended
+    // to store annotations, ink, and other data.
+    //
+    export function resolvedFieldDataDoc(doc: Doc, fieldKey: string, fieldExt: string) {
+        return fieldExt && doc[fieldKey + "_ext"] instanceof Doc ? doc[fieldKey + "_ext"] as Doc : doc;
     }
-    export function extField(doc: Doc, fieldKey: string, fieldExt: string) {
-        return doc && fieldExt && doc[fieldKey + "_ext"] instanceof Doc ? fieldExt : fieldKey;
-    }
-    export function UpdateFieldExtension(doc: Doc, fieldKey: string) {
-        if (doc && doc[fieldKey + "_ext"] === undefined) {
+
+    export function UpdateDocumentExtensionForField(doc: Doc, fieldKey: string) {
+        if (doc[fieldKey + "_ext"] === undefined) {
             setTimeout(() => {
-                let fieldExtension = new Doc(doc[Id] + fieldKey, true);
-                fieldExtension.title = "Extension of " + doc.title + "'s field:" + fieldKey;
+                let docExtensionForField = new Doc(doc[Id] + fieldKey, true);
+                docExtensionForField.title = "Extension of " + doc.title + "'s field:" + fieldKey;
                 let proto: Doc | undefined = doc;
                 while (proto && !Doc.IsPrototype(proto)) {
                     proto = proto.proto;
                 }
-                (proto ? proto : doc)[fieldKey + "_ext"] = fieldExtension;
+                (proto ? proto : doc)[fieldKey + "_ext"] = docExtensionForField;
             }, 0);
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 0d5e2537520ca1e6a6b52f4d0f03aa2bcfc6c5c6 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com>
Date: Wed, 26 Jun 2019 12:30:16 -0400
Subject: cleanup

---
 src/client/views/collections/CollectionBaseView.tsx | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 6639879e1..7b2f216dd 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -146,9 +146,6 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
             }
         });
 
-        //initial
-        //
-
         if (index !== -1) {
             value.splice(index, 1);
 
@@ -189,4 +186,4 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         );
     }
 
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3-70-g09d2


From 084dd6d9b0ad51133025ba6bd2702fc44b1b6c31 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 26 Jun 2019 12:56:22 -0400
Subject: fixes to datadoc usage.  fixed tree view for textboxes.

---
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/MainView.tsx                      |  2 +-
 .../views/collections/CollectionBaseView.tsx       |  2 +-
 .../views/collections/CollectionSchemaView.tsx     | 10 +--
 src/client/views/collections/CollectionSubView.tsx |  5 +-
 .../views/collections/CollectionTreeView.tsx       | 81 +++++++++++-----------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  9 +--
 src/client/views/nodes/DocumentView.tsx            | 19 ++---
 src/client/views/nodes/FieldView.tsx               |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  6 +-
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 src/client/views/nodes/PDFBox.tsx                  |  2 +-
 src/new_fields/Doc.ts                              |  2 +-
 13 files changed, 75 insertions(+), 69 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b9537fca6..557db3639 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -176,7 +176,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         let dragDocView = SelectionManager.SelectedDocuments()[0];
         const [left, top] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).inverse().transformPoint(0, 0);
         const [xoff, yoff] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.x - left, e.y - top);
-        let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document), SelectionManager.SelectedDocuments().map(dv => dv.props.DataDoc));
+        let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document), SelectionManager.SelectedDocuments().map(dv => dv.props.DataDoc ? dv.props.DataDoc : dv.props.Document));
         dragData.xOffset = xoff;
         dragData.yOffset = yoff;
         dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d26e24748..e48de27d7 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -203,7 +203,7 @@ export class MainView extends React.Component {
         let mainCont = this.mainContainer;
         let content = !mainCont ? (null) :
             <DocumentView Document={mainCont}
-                DataDoc={mainCont}
+                DataDoc={undefined}
                 addDocument={undefined}
                 addDocTab={emptyFunction}
                 removeDocument={undefined}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index a4a9ec994..22f0cf6e2 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -59,7 +59,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         }
     }
 
-    @computed get dataDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
+    @computed get dataDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc ? this.props.DataDoc : this.props.Document : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
     @computed get dataField() { return this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; }
 
     active = (): boolean => {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 796882724..a8061f9f1 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -437,15 +437,16 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
         }
         return true;
     }
-    private PanelWidth = () => this.nativeWidth * this.contentScaling();
-    private PanelHeight = () => this.nativeHeight * this.contentScaling();
+    private PanelWidth = () => this.nativeWidth ? this.nativeWidth * this.contentScaling() : this.props.width();
+    private PanelHeight = () => this.nativeHeight ? this.nativeHeight * this.contentScaling() : this.props.height();
     private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling());
-    get centeringOffset() { return (this.props.width() - this.nativeWidth * this.contentScaling()) / 2; }
+    get centeringOffset() { return this.nativeWidth ? (this.props.width() - this.nativeWidth * this.contentScaling()) / 2 : 0; }
     @action
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.props.setPreviewScript(e.currentTarget.value);
     }
     render() {
+        let self = this;
         let input = this.props.previewScript === undefined ? (null) :
             <div ref={this.createTarget}><input className="collectionSchemaView-input" value={this.props.previewScript} onChange={this.onPreviewScriptChange}
                 style={{ left: `calc(50% - ${Math.min(75, (this.props.Document ? this.PanelWidth() / 2 : 75))}px)` }} /></div>;
@@ -462,7 +463,8 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         moveDocument={this.props.moveDocument}
                         ScreenToLocalTransform={this.getTransform}
                         ContentScaling={this.contentScaling}
-                        PanelWidth={this.PanelWidth} PanelHeight={this.PanelHeight}
+                        PanelWidth={this.PanelWidth}
+                        PanelHeight={this.PanelHeight}
                         ContainingCollectionView={this.props.CollectionView}
                         focus={emptyFunction}
                         parentActive={this.props.active}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 58251cd6e..0bed196e6 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -45,13 +45,12 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
-        @computed get dataDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
-        @computed get dataField() { return this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; }
+        @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
 
         get childDocs() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.dataDoc : this.props.Document)[this.dataField]);
+            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.extensionDoc : this.props.Document)[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey]);
         }
 
         @action
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index d33a4786c..a8324eba2 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -29,7 +29,7 @@ import React = require("react");
 
 export interface TreeViewProps {
     document: Doc;
-    dataDoc: Doc;
+    dataDoc?: Doc;
     containingCollection: Doc;
     deleteDoc: (doc: Doc) => boolean;
     moveDocument: DragManager.MoveFunction;
@@ -66,14 +66,14 @@ class TreeView extends React.Component<TreeViewProps> {
     @observable _collapsed: boolean = true;
 
     @computed get fieldKey() {
-        let keys = Array.from(Object.keys(this.dataDoc));
-        if (this.dataDoc.proto instanceof Doc) {
-            keys.push(...Array.from(Object.keys(this.dataDoc.proto)));
+        let keys = Array.from(Object.keys(this.resolvedDataDoc));
+        if (this.resolvedDataDoc.proto instanceof Doc) {
+            keys.push(...Array.from(Object.keys(this.resolvedDataDoc.proto)));
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
         let keyList: string[] = [];
         keys.map(key => {
-            let docList = Cast(this.dataDoc[key], listSpec(Doc));
+            let docList = Cast(this.resolvedDataDoc[key], listSpec(Doc));
             if (docList && docList.length > 0) {
                 keyList.push(key);
             }
@@ -85,7 +85,7 @@ class TreeView extends React.Component<TreeViewProps> {
         return keyList.length ? keyList[0] : "data";
     }
 
-    @computed get dataDoc() { return BoolCast(this.props.document.isTemplate) ? this.props.dataDoc : this.props.document; }
+    @computed get resolvedDataDoc() { return BoolCast(this.props.document.isTemplate) && this.props.dataDoc ? this.props.dataDoc : this.props.document; }
 
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
         this._treedropDisposer && this._treedropDisposer();
@@ -94,7 +94,7 @@ class TreeView extends React.Component<TreeViewProps> {
         }
     }
 
-    @undoBatch delete = () => this.props.deleteDoc(this.dataDoc);
+    @undoBatch delete = () => this.props.deleteDoc(this.resolvedDataDoc);
     @undoBatch openRight = async () => this.props.addDocTab(this.props.document, this.props.document, "onRight");
 
     onPointerDown = (e: React.PointerEvent) => e.stopPropagation();
@@ -126,7 +126,7 @@ class TreeView extends React.Component<TreeViewProps> {
 
     @action
     remove = (document: Document, key: string): boolean => {
-        let children = Cast(this.dataDoc[key], listSpec(Doc), []);
+        let children = Cast(this.resolvedDataDoc[key], listSpec(Doc), []);
         if (children.indexOf(document) !== -1) {
             children.splice(children.indexOf(document), 1);
             return true;
@@ -142,8 +142,8 @@ class TreeView extends React.Component<TreeViewProps> {
     indent = () => this.props.addDocument(this.props.document) && this.delete()
 
     renderBullet() {
-        let docList = Cast(this.dataDoc[this.fieldKey], listSpec(Doc));
-        let doc = Cast(this.dataDoc[this.fieldKey], Doc);
+        let docList = Cast(this.resolvedDataDoc[this.fieldKey], listSpec(Doc));
+        let doc = Cast(this.resolvedDataDoc[this.fieldKey], Doc);
         let isDoc = doc instanceof Doc || docList;
         return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)}>
             {<FontAwesomeIcon icon={this._collapsed ? (isDoc ? "caret-square-right" : "caret-right") : (isDoc ? "caret-square-down" : "caret-down")} />}
@@ -161,15 +161,15 @@ class TreeView extends React.Component<TreeViewProps> {
     editableView = (key: string, style?: string) => (<EditableView
         oneLine={true}
         display={"inline"}
-        editing={this.dataDoc[Id] === TreeView.loadId}
+        editing={this.resolvedDataDoc[Id] === TreeView.loadId}
         contents={StrCast(this.props.document[key])}
         onClick={this.titleClicked}
         height={36}
         fontStyle={style}
         GetValue={() => StrCast(this.props.document[key])}
-        SetValue={(value: string) => (Doc.GetProto(this.dataDoc)[key] = value) ? true : true}
+        SetValue={(value: string) => (Doc.GetProto(this.resolvedDataDoc)[key] = value) ? true : true}
         OnFillDown={(value: string) => {
-            Doc.GetProto(this.dataDoc)[key] = value;
+            Doc.GetProto(this.resolvedDataDoc)[key] = value;
             let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) });
             TreeView.loadId = doc[Id];
             return this.props.addDocument(doc);
@@ -178,13 +178,13 @@ class TreeView extends React.Component<TreeViewProps> {
     />)
 
     @computed get keyList() {
-        let keys = Array.from(Object.keys(this.dataDoc));
-        if (this.dataDoc.proto instanceof Doc) {
-            keys.push(...Array.from(Object.keys(this.dataDoc.proto)));
+        let keys = Array.from(Object.keys(this.resolvedDataDoc));
+        if (this.resolvedDataDoc.proto instanceof Doc) {
+            keys.push(...Array.from(Object.keys(this.resolvedDataDoc.proto)));
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
-        let keyList: string[] = keys.reduce((l, key) => Cast(this.dataDoc[key], listSpec(Doc)) ? [...l, key] : l, [] as string[]);
-        keys.map(key => Cast(this.dataDoc[key], Doc) instanceof Doc && keyList.push(key));
+        let keyList: string[] = keys.reduce((l, key) => Cast(this.resolvedDataDoc[key], listSpec(Doc)) ? [...l, key] : l, [] as string[]);
+        keys.map(key => Cast(this.resolvedDataDoc[key], Doc) instanceof Doc && keyList.push(key));
         if (keyList.indexOf(this.fieldKey) !== -1) {
             keyList.splice(keyList.indexOf(this.fieldKey), 1);
         }
@@ -196,7 +196,7 @@ class TreeView extends React.Component<TreeViewProps> {
      */
     renderTitle() {
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId, true);
+        let onItemDown = SetupDrag(reference, () => this.resolvedDataDoc, this.move, this.props.dropAction, this.props.treeViewId, true);
 
         let headerElements = (
             <span className="collectionTreeView-keyHeader" key={this._chosenKey}
@@ -208,7 +208,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 {this._chosenKey}
             </span>);
         let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document[this.fieldKey], listSpec(Doc), []) : [];
-        let openRight = dataDocs && dataDocs.indexOf(this.dataDoc) !== -1 ? (null) : (
+        let openRight = dataDocs && dataDocs.indexOf(this.resolvedDataDoc) !== -1 ? (null) : (
             <div className="treeViewItem-openRight" onPointerDown={this.onPointerDown} onClick={this.openRight}>
                 <FontAwesomeIcon icon="angle-right" size="lg" />
             </div>);
@@ -229,13 +229,13 @@ class TreeView extends React.Component<TreeViewProps> {
 
     onWorkspaceContextMenu = (e: React.MouseEvent): void => {
         if (!e.isPropagationStopped()) { // 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: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.dataDoc)) });
+            ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.resolvedDataDoc)) });
             ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, kvp, "onRight"); }, icon: "layer-group" });
             if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) {
-                ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.dataDoc, "inTab"), icon: "folder" });
-                ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.dataDoc, "onRight"), icon: "caret-square-right" });
-                if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) {
-                    ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.dataDoc).map(view => view.props.focus(this.props.document)) });
+                ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "inTab"), icon: "folder" });
+                ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "onRight"), icon: "caret-square-right" });
+                if (DocumentManager.Instance.getDocumentViews(this.resolvedDataDoc).length) {
+                    ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.resolvedDataDoc).map(view => view.props.focus(this.props.document)) });
                 }
                 ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)) });
             } else {
@@ -252,9 +252,9 @@ class TreeView extends React.Component<TreeViewProps> {
         let before = x[1] < bounds[1];
         let inside = x[0] > bounds[0] + 75 || (!before && !this._collapsed);
         if (de.data instanceof DragManager.DocumentDragData) {
-            let addDoc = (doc: Doc) => this.props.addDocument(doc, this.dataDoc, before);
+            let addDoc = (doc: Doc) => this.props.addDocument(doc, this.resolvedDataDoc, before);
             if (inside) {
-                let docList = Cast(this.dataDoc.data, listSpec(Doc));
+                let docList = Cast(this.resolvedDataDoc.data, listSpec(Doc));
                 if (docList !== undefined) {
                     addDoc = (doc: Doc) => { docList && docList.push(doc); return true; };
                 }
@@ -262,10 +262,10 @@ class TreeView extends React.Component<TreeViewProps> {
             e.stopPropagation();
             let movedDocs = (de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
             return (de.data.dropAction || de.data.userDropAction) ?
-                de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.dataDoc, before) || added, false)
+                de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.resolvedDataDoc, before) || added, false)
                 : (de.data.moveDocument) ?
-                    movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, this.dataDoc, addDoc) || added, false)
-                    : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.dataDoc, before), false);
+                    movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, this.resolvedDataDoc, addDoc) || added, false)
+                    : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.resolvedDataDoc, before), false);
         }
         return false;
     }
@@ -280,22 +280,23 @@ class TreeView extends React.Component<TreeViewProps> {
 
     render() {
         let contentElement: (JSX.Element | null) = null;
-        let docList = Cast(this.dataDoc[this._chosenKey], listSpec(Doc));
+        let docList = Cast(this.resolvedDataDoc[this._chosenKey], listSpec(Doc));
         let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
-        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this._chosenKey, doc, addBefore, before);
-        let doc = Cast(this.dataDoc[this._chosenKey], Doc);
+        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.resolvedDataDoc, this._chosenKey, doc, addBefore, before);
+        let doc = Cast(this.resolvedDataDoc[this._chosenKey], Doc);
         let docWidth = () => NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5;
         if (!this._collapsed) {
             if (!this.props.document.embed) {
                 contentElement = <ul key={this._chosenKey + "more"}>
-                    {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.dataDoc, this._chosenKey, addDoc, remDoc, this.move,
+                    {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.props.dataDoc, this._chosenKey, addDoc, remDoc, this.move,
                         this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth)}
                 </ul >;
             } else {
+                console.log("PW = " + this.props.panelWidth());
                 contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.props.panelHeight() }} key={this.props.document[Id]}>
                     <CollectionSchemaPreview
                         Document={this.props.document}
-                        DataDocument={this.dataDoc}
+                        DataDocument={this.resolvedDataDoc}
                         width={docWidth}
                         height={this.props.panelHeight}
                         getTransform={this.docTransform}
@@ -327,7 +328,7 @@ class TreeView extends React.Component<TreeViewProps> {
         docs: Doc[],
         treeViewId: string,
         containingCollection: Doc,
-        dataDoc: Doc,
+        dataDoc: Doc | undefined,
         key: string,
         add: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean,
         remove: ((doc: Doc) => boolean),
@@ -412,6 +413,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         }
     }
 
+    @computed get resolvedDataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
+
     outerXf = () => Utils.GetScreenTransform(this._mainEle!);
     onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {});
 
@@ -428,11 +431,11 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                 onDrop={this.onTreeDrop}
                 ref={this.createTreeDropTarget}>
                 <EditableView
-                    contents={this.props.DataDoc.title}
+                    contents={this.resolvedDataDoc.title}
                     display={"block"}
                     height={72}
-                    GetValue={() => StrCast(this.props.DataDoc.title)}
-                    SetValue={(value: string) => (Doc.GetProto(this.props.DataDoc).title = value) ? true : true}
+                    GetValue={() => StrCast(this.resolvedDataDoc.title)}
+                    SetValue={(value: string) => (Doc.GetProto(this.resolvedDataDoc).title = value) ? true : true}
                     OnFillDown={(value: string) => {
                         Doc.GetProto(this.props.Document).title = value;
                         let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a3ca02941..6672b3a07 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -163,7 +163,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
                     [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
                 }, [[minx, maxx], [miny, maxy]]);
-                let ink = Cast(this.dataDoc.ink, InkField);
+                let ink = Cast(this.extensionDoc.ink, InkField);
                 if (ink && ink.inkData) {
                     ink.inkData.forEach((value: StrokeData, key: string) => {
                         let bounds = InkingCanvas.StrokeRect(value);
@@ -295,8 +295,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
 
     getDocumentViewProps(layoutDoc: Doc): DocumentViewProps {
+        let datadoc = BoolCast(this.props.Document.isTemplate) || this.props.DataDoc === this.props.Document ? undefined : this.props.DataDoc;
         return {
-            DataDoc: BoolCast(this.props.Document.isTemplate) ? layoutDoc : this.props.DataDoc,
+            DataDoc: datadoc,
             Document: layoutDoc,
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
@@ -375,7 +376,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     render() {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
-        if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.dataDoc, this.props.fieldKey);
+        if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.extensionDoc, this.props.fieldKey);
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
                 style={{ borderRadius: "inherit" }}
@@ -387,7 +388,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                         easing={easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
 
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
-                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.dataDoc} inkFieldKey={this.props.fieldExt ? "ink" : this.props.fieldKey + "_ink"} >
+                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.extensionDoc} inkFieldKey={this.props.fieldExt ? "ink" : this.props.fieldKey + "_ink"} >
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9c3479ec2..eb4f56af1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -67,7 +67,7 @@ const LinkDoc = makeInterface(linkSchema);
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Doc;
-    DataDoc: Doc;
+    DataDoc?: Doc;
     addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean;
     removeDocument?: (doc: Doc) => boolean;
     moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
@@ -209,10 +209,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         e.stopPropagation();
     }
 
+    get dataDoc() { return this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
     startDragging(x: number, y: number, dropAction: dropActionType, dragSubBullets: boolean) {
         if (this._mainCont.current) {
             let allConnected = [this.props.Document, ...(dragSubBullets ? DocListCast(this.props.Document.subBulletDocs) : [])];
-            let alldataConnected = [this.props.DataDoc, ...(dragSubBullets ? DocListCast(this.props.Document.subBulletDocs) : [])];
+            let alldataConnected = [this.dataDoc, ...(dragSubBullets ? DocListCast(this.props.Document.subBulletDocs) : [])];
             const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0);
             let dragData = new DragManager.DocumentDragData(allConnected, alldataConnected);
             const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
@@ -271,7 +272,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (this._doubleTap && this.props.renderDepth) {
             let fullScreenAlias = Doc.MakeAlias(this.props.Document);
             fullScreenAlias.templates = new List<string>();
-            this.props.addDocTab(fullScreenAlias, this.props.DataDoc, "inTab");
+            this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab");
             SelectionManager.DeselectAll();
             this.props.Document.libraryBrush = false;
         }
@@ -348,7 +349,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         this._downY = e.clientY;
         this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0;
         if (e.shiftKey && e.buttons === 1 && CollectionDockingView.Instance) {
-            CollectionDockingView.Instance.StartOtherDrag(e, [Doc.MakeAlias(this.props.Document)], [this.props.DataDoc]);
+            CollectionDockingView.Instance.StartOtherDrag(e, [Doc.MakeAlias(this.props.Document)], [this.dataDoc]);
             e.stopPropagation();
         } else {
             if (this.active) e.stopPropagation(); // events stop at the lowest document that is active.  
@@ -393,7 +394,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
     }
     fullScreenClicked = (): void => {
-        CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(Doc.MakeAlias(this.props.Document), this.props.DataDoc);
+        CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(Doc.MakeAlias(this.props.Document), this.dataDoc);
         SelectionManager.DeselectAll();
     }
 
@@ -476,10 +477,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const cm = ContextMenu.Instance;
         let subitems: ContextMenuProps[] = [];
         subitems.push({ description: "Open Full Screen", event: this.fullScreenClicked, icon: "desktop" });
-        subitems.push({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab"), icon: "folder" });
-        subitems.push({ description: "Open Tab Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" });
-        subitems.push({ description: "Open Right", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight"), icon: "caret-square-right" });
-        subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" });
+        subitems.push({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, this.dataDoc, "inTab"), icon: "folder" });
+        subitems.push({ description: "Open Tab Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "inTab"), icon: "folder" });
+        subitems.push({ description: "Open Right", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, this.dataDoc, "onRight"), icon: "caret-square-right" });
+        subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" });
         subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" });
         cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" });
         cm.addItem({ description: BoolCast(this.props.Document.ignoreAspect, false) || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "edit" });
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 8a481144e..55f61ddff 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -30,7 +30,7 @@ export interface FieldViewProps {
     fieldExt: string;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Doc;
-    DataDoc: Doc;
+    DataDoc?: Doc;
     isSelected: () => boolean;
     select: (isCtrlPressed: boolean) => void;
     renderDepth: number;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 0a1a86226..e1a496574 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -110,15 +110,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         }
     }
 
-    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
 
     dispatchTransaction = (tx: Transaction) => {
         if (this._editorView) {
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
             this._applyingChange = true;
-            Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey, new RichTextField(JSON.stringify(state.toJSON())));
-            Doc.SetOnPrototype(this.dataDoc, this.props.fieldKey + "_text", state.doc.textBetween(0, state.doc.content.size, "\n\n"));
+            Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()));
+            Doc.GetProto(this.dataDoc)[this.props.fieldKey + "_text"] = state.doc.textBetween(0, state.doc.content.size, "\n\n");
             this._applyingChange = false;
             let title = StrCast(this.dataDoc.title);
             if (title && title.startsWith("-") && this._editorView) {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 0da774db1..0e6c1ee19 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -46,7 +46,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
     private dropDisposer?: DragManager.DragDropDisposer;
 
 
-    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
 
 
     protected createDropTarget = (ele: HTMLDivElement) => {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index f8bf5faf3..b863ee4fc 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -27,7 +27,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
 
     @observable private _alt = false;
     @observable private _scrollY: number = 0;
-    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) ? this.props.DataDoc : this.props.Document; }
+    @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
 
     private _reactionDisposer?: IReactionDisposer;
 
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 8825bc13a..ddbbc1436 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -178,7 +178,7 @@ export namespace Doc {
     export async function SetInPlace(doc: Doc, key: string, value: Field | undefined, defaultProto: boolean) {
         let hasProto = doc.proto instanceof Doc;
         let onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1;
-        let onProto = Object.getOwnPropertyNames(doc.proto).indexOf(key) !== -1;
+        let onProto = hasProto && Object.getOwnPropertyNames(doc.proto).indexOf(key) !== -1;
         if (onDeleg || !hasProto || (!onProto && !defaultProto))
             doc[key] = value;
         else doc.proto![key] = value;
-- 
cgit v1.2.3-70-g09d2


From 31f8a808640a598a923096900ceaa2cd95a30c7d Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 5 Jul 2019 16:18:25 -0400
Subject: fixed dragging from sidebar

---
 src/client/views/collections/CollectionBaseView.tsx    | 2 +-
 src/server/authentication/models/current_user_utils.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 879898018..e4f9b5058 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -64,7 +64,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     active = (): boolean => {
         var isSelected = this.props.isSelected();
-        return isSelected || this._isChildActive || this.props.renderDepth === 0;
+        return isSelected || this._isChildActive || this.props.renderDepth === 0 || BoolCast(this.props.Document.excludeFromLibrary);
     }
 
     //TODO should this be observable?
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 3134ecaff..c76d2cd30 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -35,7 +35,7 @@ export class CurrentUserUtils {
         (doc.workspaces as Doc).excludeFromLibrary = true;
         (doc.workspaces as Doc).workspaceLibrary = true;
         doc.recentlyClosed = Docs.TreeDocument([], { title: "Recently Closed", height: 75 });
-        (doc.workspaces as Doc).excludeFromLibrary = true;
+        (doc.recentlyClosed as Doc).excludeFromLibrary = true;
         doc.sidebar = Docs.StackingDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" });
         (doc.sidebar as Doc).excludeFromLibrary = true;
         (doc.sidebar as Doc).gridGap = 5;
-- 
cgit v1.2.3-70-g09d2


From 0058f56fda4e9e6a70ec7c23e1c141927715f9c1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 11 Jul 2019 00:38:37 -0400
Subject: trying to make everything work the same way

---
 src/client/documents/Documents.ts                  |  8 +++---
 src/client/util/LinkManager.ts                     |  4 +--
 src/client/util/TooltipTextMenu.tsx                |  2 +-
 .../views/collections/CollectionBaseView.tsx       | 19 ++++++++++---
 src/client/views/collections/CollectionPDFView.tsx |  4 +--
 .../views/collections/CollectionStackingView.tsx   | 10 +++----
 src/client/views/collections/CollectionSubView.tsx | 10 ++++---
 .../views/collections/CollectionTreeView.tsx       |  2 +-
 .../views/collections/CollectionVideoView.tsx      |  4 +--
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.scss |  4 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 33 +++++++++++-----------
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 src/client/views/nodes/FieldView.tsx               |  4 +--
 src/client/views/nodes/FormattedTextBox.tsx        |  3 +-
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 src/new_fields/Doc.ts                              |  2 +-
 17 files changed, 64 insertions(+), 51 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d1c9feb32..46255b5d5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -174,7 +174,7 @@ export namespace Docs {
     }
 
     function CreateImagePrototype(): Doc {
-        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("annotations"),
+        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("data", "annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: ImageBox.LayoutString(), curPage: 0, type: DocTypes.IMG });
         return imageProto;
     }
@@ -185,7 +185,7 @@ export namespace Docs {
     }
 
     function CreateHistogramPrototype(): Doc {
-        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("annotations"),
+        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("data"),
             { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString(), type: DocTypes.HIST });
         return histoProto;
     }
@@ -200,7 +200,7 @@ export namespace Docs {
         return textProto;
     }
     function CreatePdfPrototype(): Doc {
-        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("annotations"),
+        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("data", "annotations"),
             { x: 0, y: 0, width: 300, height: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1, type: DocTypes.PDF });
         return pdfProto;
     }
@@ -221,7 +221,7 @@ export namespace Docs {
         return kvpProto;
     }
     function CreateVideoPrototype(): Doc {
-        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("annotations"),
+        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("data", "annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: VideoBox.LayoutString(), curPage: 0, type: DocTypes.VID });
         return videoProto;
     }
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 944bc532f..d6ea6013b 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -234,9 +234,9 @@ export class LinkManager {
     //TODO This should also await the return value of the anchor so we don't filter out promises
     public getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc {
         if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, null))) {
-            return Cast(linkDoc.anchor2, Doc, null)!;
+            return Cast(linkDoc.anchor2, Doc, null);
         } else {
-            return Cast(linkDoc.anchor1, Doc, null)!;
+            return Cast(linkDoc.anchor1, Doc, null);
         }
     }
 }
\ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index cb7ed976a..4fcc16ddd 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -448,7 +448,7 @@ export class TooltipTextMenu {
                     let node = state.doc.nodeAt(from);
                     node && node.marks.map(m => {
                         m.type === markType && (curLink = m.attrs.href);
-                    })
+                    });
                     //toggleMark(markType)(state, dispatch);
                     //return true;
                 }
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index e4f9b5058..079a44b88 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -74,21 +74,27 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         this.props.whenActiveChanged(isActive);
     }
 
+    public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
+    @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
+        let self = this;
         var curPage = NumCast(this.props.Document.curPage, -1);
         Doc.GetProto(doc).page = curPage;
         if (curPage >= 0) {
             Doc.GetProto(doc).annotationOn = this.props.Document;
         }
         allowDuplicates = true;
-        const value = Cast(this.dataDoc[this.dataField], listSpec(Doc));
+        let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document;
+        let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey;
+        const value = Cast(targetDataDoc[targetField], listSpec(Doc));
         if (value !== undefined) {
             if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
                 value.push(doc);
             }
         } else {
-            Doc.GetProto(this.dataDoc)[this.dataField] = new List([doc]);
+            Doc.GetProto(targetDataDoc)[targetField] = new List([doc]);
         }
         return true;
     }
@@ -98,7 +104,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
         docView && SelectionManager.DeselectDoc(docView);
         //TODO This won't create the field if it doesn't already exist
-        const value = Cast(this.dataDoc[this.dataField], listSpec(Doc), []);
+        let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document;
+        let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey;
+        let value = Cast(targetDataDoc[targetField], listSpec(Doc), []);
         let index = value.reduce((p, v, i) => (v instanceof Doc && v[Id] === doc[Id]) ? i : p, -1);
         PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn =>
             annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined)
@@ -116,7 +124,10 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     @action.bound
     moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean {
-        if (Doc.AreProtosEqual(this.dataDoc, targetCollection)) {
+        let self = this;
+        let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document;
+        if (Doc.AreProtosEqual(targetDataDoc, targetCollection)) {
+            //if (Doc.AreProtosEqual(this.extensionDoc, targetCollection)) {
             return true;
         }
         if (this.removeDocument(doc)) {
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 31a73ab36..c97443785 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -47,8 +47,8 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
         this._reactionDisposer && this._reactionDisposer();
     }
 
-    public static LayoutString(fieldKey: string = "data") {
-        return FieldView.LayoutString(CollectionPDFView, fieldKey);
+    public static LayoutString(fieldKey: string = "data", fieldExt: string = "annotations") {
+        return FieldView.LayoutString(CollectionPDFView, fieldKey, fieldExt);
     }
     @observable _inThumb = false;
 
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 372891923..9266fc8fd 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -50,11 +50,11 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     overlays = (doc: Doc) => {
-        return doc.type === DocTypes.IMG ? { title: "title", caption: "caption" } : {}
+        return doc.type === DocTypes.IMG ? { title: "title", caption: "caption" } : {};
     }
 
     getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) {
-        let dataDoc = d !== this.props.DataDoc ? this.props.DataDoc : undefined
+        let dataDoc = d !== this.props.DataDoc ? this.props.DataDoc : undefined;
         let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth;
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
@@ -75,7 +75,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             addDocTab={this.props.addDocTab}
             setPreviewScript={emptyFunction}
             previewScript={undefined}>
-        </CollectionSchemaPreview>
+        </CollectionSchemaPreview>;
     }
     getDocHeight(d: Doc) {
         let nw = NumCast(d.nativeWidth);
@@ -176,7 +176,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) {
                     targInd = i;
                 }
-            })
+            });
         }
         if (super.drop(e, de)) {
             let newDoc = de.data.droppedDocuments[0];
@@ -202,7 +202,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) {
                 targInd = i;
             }
-        })
+        });
         super.onDrop(e, {}, () => {
             if (targInd !== -1) {
                 let newDoc = this.childDocs[this.childDocs.length - 1];
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 496f7e461..e72e69330 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -46,18 +46,20 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
-        @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
+        public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
+        @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+
 
         get childDocs() {
             let self = this;
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.extensionDoc : this.props.Document)[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey]);
+            return DocListCast(this.extensionDoc[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey]);
         }
         get childDocList() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return Cast((BoolCast(this.props.Document.isTemplate) ? this.extensionDoc : this.props.Document)[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey], listSpec(Doc));
+            return Cast(this.extensionDoc[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey], listSpec(Doc));
         }
 
         @action
@@ -102,7 +104,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 } else if (de.data.moveDocument) {
                     let movedDocs = de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments;
                     added = movedDocs.reduce((added: boolean, d) =>
-                        de.data.moveDocument(d, this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.addDocument) || added, false);
+                        de.data.moveDocument(d, /*this.props.DataDoc ? this.props.DataDoc :*/ this.props.Document, this.props.addDocument) || added, false);
                 } else {
                     added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false);
                 }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 3674a743a..1280d515c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -75,7 +75,7 @@ class TreeView extends React.Component<TreeViewProps> {
     @computed get fieldKey() {
         let keys = Array.from(Object.keys(this.resolvedDataDoc));  // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
         if (this.resolvedDataDoc.proto instanceof Doc) {
-            let arr = Array.from(Object.keys(this.resolvedDataDoc.proto!));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
+            let arr = Array.from(Object.keys(this.resolvedDataDoc.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
             keys.push(...arr);
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 1984965ba..16287a658 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -21,8 +21,8 @@ import { Docs, DocUtils } from "../../documents/Documents";
 export class CollectionVideoView extends React.Component<FieldViewProps> {
     private _videoBox?: VideoBox;
 
-    public static LayoutString(fieldKey: string = "data") {
-        return FieldView.LayoutString(CollectionVideoView, fieldKey);
+    public static LayoutString(fieldKey: string = "data", fieldExt: string = "annotations") {
+        return FieldView.LayoutString(CollectionVideoView, fieldKey, fieldExt);
     }
     private get uIButtons() {
         let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e500e5c70..e69696390 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -27,7 +27,7 @@ library.add(faThList);
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(CollectionView, fieldStr); }
+    public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); }
 
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index ccf261c95..51cfa77b1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -38,7 +38,7 @@
     // }
     box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
     border: 0px solid $light-color-secondary;
-    border-radius: $border-radius;
+    border-radius: inherit;
     box-sizing: border-box;
     position: absolute;
 
@@ -71,7 +71,7 @@
 
     opacity: 0.99;
     border: 0px solid transparent;
-    border-radius: $border-radius;
+    border-radius: inherit;
     box-sizing: border-box;
     position:absolute;
     z-index: -1;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2c9b6b6a9..c931c74bc 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -54,7 +54,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
-    public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
+    public get isAnnotationOverlay() { return this.props.fieldExt === "annotations"; }
     private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
     private panX = () => this.props.fitToBox ? this.props.fitToBox()[0] : this.Document.panX || 0;
     private panY = () => this.props.fitToBox ? this.props.fitToBox()[1] : this.Document.panY || 0;
@@ -86,6 +86,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         });
     }
 
+    @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+
+
     @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
@@ -93,10 +96,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             if (de.data instanceof DragManager.DocumentDragData) {
                 if (de.data.droppedDocuments.length) {
                     let dragDoc = de.data.droppedDocuments[0];
-                    let zoom = NumCast(dragDoc.zoomBasis, 1);
                     let [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
-                    let x = xp - de.data.xOffset / zoom;
-                    let y = yp - de.data.yOffset / zoom;
+                    let x = xp - de.data.xOffset;
+                    let y = yp - de.data.yOffset;
                     let dropX = NumCast(de.data.droppedDocuments[0].x);
                     let dropY = NumCast(de.data.droppedDocuments[0].y);
                     de.data.droppedDocuments.forEach(d => {
@@ -117,10 +119,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             else if (de.data instanceof DragManager.AnnotationDragData) {
                 if (de.data.dropDocument) {
                     let dragDoc = de.data.dropDocument;
-                    let zoom = NumCast(dragDoc.zoomBasis, 1);
                     let [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
-                    let x = xp - de.data.xOffset / zoom;
-                    let y = yp - de.data.yOffset / zoom;
+                    let x = xp - de.data.xOffset;
+                    let y = yp - de.data.yOffset;
                     let dropX = NumCast(de.data.dropDocument.x);
                     let dropY = NumCast(de.data.dropDocument.y);
                     dragDoc.x = x + NumCast(dragDoc.x) - dropX;
@@ -159,14 +160,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             if (!this.isAnnotationOverlay) {
                 PDFMenu.Instance.fadeOut(true);
                 let minx = docs.length ? NumCast(docs[0].x) : 0;
-                let maxx = docs.length ? NumCast(docs[0].width) / NumCast(docs[0].zoomBasis, 1) + minx : minx;
+                let maxx = docs.length ? NumCast(docs[0].width) + minx : minx;
                 let miny = docs.length ? NumCast(docs[0].y) : 0;
-                let maxy = docs.length ? NumCast(docs[0].height) / NumCast(docs[0].zoomBasis, 1) + miny : miny;
+                let maxy = docs.length ? NumCast(docs[0].height) + miny : miny;
                 let ranges = docs.filter(doc => doc).reduce((range, doc) => {
                     let x = NumCast(doc.x);
-                    let xe = x + NumCast(doc.width) / NumCast(doc.zoomBasis, 1);
+                    let xe = x + NumCast(doc.width);
                     let y = NumCast(doc.y);
-                    let ye = y + NumCast(doc.height) / NumCast(doc.zoomBasis, 1);
+                    let ye = y + NumCast(doc.height);
                     return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
                     [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
                 }, [[minx, maxx], [miny, maxy]]);
@@ -299,8 +300,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             }
         }
         SelectionManager.DeselectAll();
-        const newPanX = NumCast(doc.x) + NumCast(doc.width) / NumCast(doc.zoomBasis, 1) / 2;
-        const newPanY = NumCast(doc.y) + NumCast(doc.height) / NumCast(doc.zoomBasis, 1) / 2;
+        const newPanX = NumCast(doc.x) + NumCast(doc.width) / 2;
+        const newPanY = NumCast(doc.y) + NumCast(doc.height) / 2;
         const newState = HistoryUtil.getState();
         newState.initializers[id] = { panX: newPanX, panY: newPanY };
         HistoryUtil.pushState(newState);
@@ -501,19 +502,17 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
 
-        if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
+        Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
-                style={{ borderRadius: "inherit" }}
                 onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onContextMenu={this.onContextMenu}>
                 <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} isSelected={this.props.isSelected}
                     addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
                     getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
                     <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
                         easing={easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
-
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
-                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.extensionDoc} inkFieldKey={this.props.fieldExt ? "ink" : this.props.fieldKey + "_ink"} >
+                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.extensionDoc} inkFieldKey={"ink"} >
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6f3adb6b5..613cbf98e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -530,7 +530,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 this.props.addDocument && this.props.addDocument(coll);
                 this.props.removeDocument && this.props.removeDocument(this.props.Document);
             }, icon: "window-restore"
-        })
+        });
         cm.addItem({
             description: "Find aliases", event: async () => {
                 const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index c5fc6c65a..abd0d9e12 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -55,8 +55,8 @@ export interface FieldViewProps {
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: { name: string }, fieldStr: string = "data") {
-        return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"} />`;
+    public static LayoutString(fieldType: { name: string }, fieldStr: string = "data", fieldExt: string = "") {
+        return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"} fieldExt={"${fieldExt}"} />`;
     }
 
     @computed
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 5475aa2b2..084fd4c96 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -232,9 +232,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 return field ? field.Data : `{"doc":{"type":"doc","content":[]},"selection":{"type":"text","anchor":0,"head":0}}`;
             },
             field2 => {
-                if (StrCast(this.props.Document.layout).indexOf("\"" + this.props.fieldKey + "\"") !== -1) // bcz: UGH!  why is this needed... something is happening out of order.  test with making a collection, then adding a text note and converting that to a template field.
+                if (StrCast(this.props.Document.layout).indexOf("\"" + this.props.fieldKey + "\"") !== -1) { // bcz: UGH!  why is this needed... something is happening out of order.  test with making a collection, then adding a text note and converting that to a template field.
                     this._editorView && !this._applyingChange &&
                         this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field2)));
+                }
             }
         );
 
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 8af29110f..8bba05850 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -588,7 +588,7 @@ export class Viewer extends React.Component<IViewerProps> {
             }
             return true;
         });
-        this.Index = Math.min(this.Index + 1, filtered.length - 1)
+        this.Index = Math.min(this.Index + 1, filtered.length - 1);
     }
 
     nextResult = () => {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 3d46243e0..cc0dc71dd 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -372,7 +372,7 @@ export namespace Doc {
         }
         let layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`);
         if (backgroundLayout) {
-            layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"annotations"}/, `fieldKey={"${metaKey}"} fieldExt={"annotations"}`);
+            layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"} fieldExt={"annotations"}`);
             backgroundLayout = backgroundLayout.replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`);
         }
         let nw = Cast(fieldTemplate.nativeWidth, "number");
-- 
cgit v1.2.3-70-g09d2


From 1b203afbd297f8ae9400a47c9379df912f9ef3b5 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 11 Jul 2019 15:43:39 -0400
Subject: tweaks to annotationOverlay.

---
 src/client/views/collections/CollectionBaseView.tsx     | 3 +--
 src/client/views/collections/CollectionStackingView.tsx | 4 +++-
 src/client/views/collections/CollectionSubView.tsx      | 3 +--
 src/client/views/collections/CollectionView.tsx         | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 079a44b88..2eb2a727c 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -74,8 +74,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         this.props.whenActiveChanged(isActive);
     }
 
-    public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
-    @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+    @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
 
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 9266fc8fd..62968821a 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -14,6 +14,7 @@ import { undoBatch } from "../../util/UndoManager";
 import { DragManager } from "../../util/DragManager";
 import { DocTypes } from "../../documents/Documents";
 import { Transform } from "../../util/Transform";
+import { resolve } from "bluebird";
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -54,13 +55,14 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) {
+        let resolvedDataDoc = !this.props.Document.isTemplate && this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined;
         let dataDoc = d !== this.props.DataDoc ? this.props.DataDoc : undefined;
         let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth;
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
         return <CollectionSchemaPreview
             Document={layoutDoc}
-            DataDocument={dataDoc}
+            DataDocument={resolvedDataDoc}
             showOverlays={this.overlays}
             renderDepth={this.props.renderDepth}
             width={width}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index e72e69330..d2b808d4a 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -46,8 +46,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
-        public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
-        @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+        @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
 
 
         get childDocs() {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e69696390..56750668d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -43,7 +43,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
         return (null);
     }
 
-    get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
+    get isAnnotationOverlay() { return this.props.fieldExt ? true : false; }
 
     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
-- 
cgit v1.2.3-70-g09d2


From d7f84cf69a34d7f176d72452311183303a489eca Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Jul 2019 14:01:03 -0400
Subject: changed a bunch of style/color things with treeView and toolbar

---
 src/client/views/Main.scss                         |  9 +++----
 src/client/views/MainView.tsx                      | 28 +++++++++++-----------
 src/client/views/PreviewCursor.tsx                 |  7 +++---
 .../views/collections/CollectionBaseView.scss      |  3 ++-
 .../views/collections/CollectionBaseView.tsx       |  6 +++--
 .../views/collections/CollectionStackingView.tsx   |  2 --
 .../views/collections/CollectionTreeView.tsx       |  5 ++--
 .../collectionFreeForm/CollectionFreeFormView.scss |  1 -
 .../authentication/models/current_user_utils.ts    |  5 ++++
 9 files changed, 37 insertions(+), 29 deletions(-)

(limited to 'src/client/views/collections/CollectionBaseView.tsx')

diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index f52e3b658..a16123476 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -235,16 +235,17 @@ ul#add-options-list {
 }
 
 .mainView-libraryHandle {
-    opacity: 0.6;
     width: 20px;
     height: 40px;
     top: 50%;
-    border-radius: 20px;
+    border: 1px solid black;
+    border-radius: 5px;
     position: absolute;
     z-index: 1;
-    background: gray;
 }
-
+.svg-inline--fa {
+    vertical-align: unset;
+}
 .mainView-workspace {
     height:200px;
     position:relative;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 935f00332..ec5ec6e8b 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,5 +1,5 @@
 import { IconName, library } from '@fortawesome/fontawesome-svg-core';
-import { faArrowDown, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons';
+import { faArrowDown, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, configure, observable, runInAction, reaction, trace } from 'mobx';
 import { observer } from 'mobx-react';
@@ -13,7 +13,7 @@ import { Id } from '../../new_fields/FieldSymbols';
 import { InkTool } from '../../new_fields/InkField';
 import { List } from '../../new_fields/List';
 import { listSpec } from '../../new_fields/Schema';
-import { Cast, FieldValue, NumCast, BoolCast } from '../../new_fields/Types';
+import { Cast, FieldValue, NumCast, BoolCast, StrCast } from '../../new_fields/Types';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { RouteStore } from '../../server/RouteStore';
 import { emptyFunction, returnOne, returnTrue } from '../../Utils';
@@ -105,7 +105,7 @@ export class MainView extends React.Component {
 
         library.add(faFont);
         library.add(faExclamation);
-        library.add(faImage);
+        library.add(faPortrait);
         library.add(faFilePdf);
         library.add(faObjectGroup);
         library.add(faTable);
@@ -325,13 +325,15 @@ export class MainView extends React.Component {
     }
     @computed
     get mainContent() {
+        let sidebar = CurrentUserUtils.UserDocument.sidebar;
+        if (!(sidebar instanceof Doc)) return (null);
         return <div>
             <div className="mainView-libraryHandle"
-                style={{ left: `${this.flyoutWidth - 10}px` }}
+                style={{ left: `${this.flyoutWidth - 10}px`, backgroundColor: `${StrCast(sidebar.backgroundColor, "lightGray")}` }}
                 onPointerDown={this.onPointerDown}>
                 <span title="library View Dragger" style={{ width: "100%", height: "100%", position: "absolute" }} />
             </div>
-            <div className="mainView-libraryFlyout" style={{ width: `${this.flyoutWidth}px` }}>
+            <div className="mainView-libraryFlyout" style={{ width: `${this.flyoutWidth}px`, zIndex: 1 }}>
                 {this.flyout}
             </div>
             {this.dockingContent}
@@ -371,28 +373,21 @@ export class MainView extends React.Component {
         let addImportCollectionNode = action(() => Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 }));
 
         let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Doc][] = [
-            [React.createRef<HTMLDivElement>(), "image", "Add Image", addImageNode],
+            [React.createRef<HTMLDivElement>(), "portrait", "Add Cat Image", addImageNode],
             [React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode],
-            [React.createRef<HTMLDivElement>(), "tree", "Add Tree", addTreeNode],
-            [React.createRef<HTMLDivElement>(), "table", "Add Schema", addSchemaNode],
             // [React.createRef<HTMLDivElement>(), "clone", "Add Docking Frame", addDockingNode],
             [React.createRef<HTMLDivElement>(), "arrow-up", "Import Directory", addImportCollectionNode],
         ];
 
         return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 5 }} >
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
-            <label htmlFor="add-menu-toggle" title="Add Node"><p>+</p></label>
+            <label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Add Node"><p>+</p></label>
 
             <div id="add-options-content">
                 <ul id="add-options-list">
                     <li key="search"><button className="add-button round-button" title="Search" onClick={this.toggleSearch}><FontAwesomeIcon icon="search" size="sm" /></button></li>
                     <li key="undo"><button className="add-button round-button" title="Undo" style={{ opacity: UndoManager.CanUndo() ? 1 : 0.5, transition: "0.4s ease all" }} onClick={() => UndoManager.Undo()}><FontAwesomeIcon icon="undo-alt" size="sm" /></button></li>
                     <li key="redo"><button className="add-button round-button" title="Redo" style={{ opacity: UndoManager.CanRedo() ? 1 : 0.5, transition: "0.4s ease all" }} onClick={() => UndoManager.Redo()}><FontAwesomeIcon icon="redo-alt" size="sm" /></button></li>
-                    <li key="color"><button className="add-button round-button" title="Select Color" onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
-                        <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
-                            <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
-                        </div>
-                    </div></button></li>
                     {btns.map(btn =>
                         <li key={btn[1]} ><div ref={btn[0]}>
                             <button className="round-button add-button" title={btn[2]} onPointerDown={SetupDrag(btn[0], btn[3])}>
@@ -400,6 +395,11 @@ export class MainView extends React.Component {
                             </button>
                         </div></li>)}
                     <li key="undoTest"><button className="add-button round-button" onClick={() => UndoManager.PrintBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
+                    <li key="color"><button className="add-button round-button" title="Select Color" onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
+                        <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
+                            <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
+                        </div>
+                    </div></button></li>
                     <li key="ink" style={{ paddingRight: "6px" }}><button className="toolbar-button round-button" title="Ink" onClick={() => InkingControl.Instance.toggleDisplay()}><FontAwesomeIcon icon="pen-nib" size="sm" /> </button></li>
                     <li key="pen"><button onClick={() => InkingControl.Instance.switchTool(InkTool.Pen)} title="Pen" style={this.selected(InkTool.Pen)}><FontAwesomeIcon icon="pen" size="lg" /></button></li>
                     <li key="marker"><button onClick={() => InkingControl.Instance.switchTool(InkTool.Highlighter)} title="Highlighter" style={this.selected(InkTool.Highlighter)}><FontAwesomeIcon icon="highlighter" size="lg" /></button></li>
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 7c1d00eb0..ef68c4489 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -35,9 +35,10 @@ export class PreviewCursor extends React.Component<{}> {
         // 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.key.startsWith("F") && !e.key.endsWith("F")) {
-        } else if (e.key !== "Escape" && e.key !== "Alt" && e.key !== "Shift" && e.key !== "Meta" && e.key !== "Control" && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
-            if ((!e.ctrlKey && !e.metaKey) || (e.key >= "a" && e.key <= "z")) {
+        if (e.key !== "Escape" && e.key !== "Backspace" && e.key !== "Delete" &&
+            e.key !== "Alt" && e.key !== "Shift" && e.key !== "Meta" && e.key !== "Control" &&
+            !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
+            if (!e.ctrlKey && !e.metaKey) {//  /^[a-zA-Z0-9$*^%#@+-=_|}{[]"':;?/><.,}]$/.test(e.key)) {
                 PreviewCursor.Visible && PreviewCursor._onKeyPress && PreviewCursor._onKeyPress(e);
                 PreviewCursor.Visible = false;
             }
diff --git a/src/client/views/collections/CollectionBaseView.scss b/src/client/views/collections/CollectionBaseView.scss
index 1f5acb96a..34bcb705e 100644
--- a/src/client/views/collections/CollectionBaseView.scss
+++ b/src/client/views/collections/CollectionBaseView.scss
@@ -1,11 +1,12 @@
 @import "../globalCssVariables";
 #collectionBaseView {
     border-width: 0;
-    box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
     border-color: $light-color-secondary;
     border-style: solid;
     border-radius: 0 0 $border-radius $border-radius;
     box-sizing: border-box;
     border-radius: inherit;
     pointer-events: all;
+    width:100%;
+    height:100%;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 2eb2a727c..eba69b448 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -5,7 +5,7 @@ import { Doc } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
 import { listSpec } from '../../../new_fields/Schema';
-import { BoolCast, Cast, NumCast, PromiseValue } from '../../../new_fields/Types';
+import { BoolCast, Cast, NumCast, PromiseValue, StrCast } from '../../../new_fields/Types';
 import { DocumentManager } from '../../util/DocumentManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { ContextMenu } from '../ContextMenu';
@@ -145,7 +145,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         };
         const viewtype = this.collectionViewType;
         return (
-            <div id="collectionBaseView" className={this.props.className || "collectionView-cont"}
+            <div id="collectionBaseView"
+                style={{ boxShadow: `#9c9396 ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}` }}
+                className={this.props.className || "collectionView-cont"}
                 onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
                 {viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
             </div>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index c667b3f3c..a84fd9cfe 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -14,7 +14,6 @@ import { undoBatch } from "../../util/UndoManager";
 import { DragManager } from "../../util/DragManager";
 import { DocumentType } from "../../documents/Documents";
 import { Transform } from "../../util/Transform";
-import { resolve } from "bluebird";
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -56,7 +55,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
 
     getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) {
         let resolvedDataDoc = !this.props.Document.isTemplate && this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined;
-        let dataDoc = d !== this.props.DataDoc ? this.props.DataDoc : undefined;
         let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth;
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 188b78d63..200e9558d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -153,7 +153,8 @@ class TreeView extends React.Component<TreeViewProps> {
         let docList = Cast(this.resolvedDataDoc[this.fieldKey], listSpec(Doc));
         let doc = Cast(this.resolvedDataDoc[this.fieldKey], Doc);
         let isDoc = doc instanceof Doc || docList;
-        return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)}>
+        let c
+        return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)} style={{ color: StrCast(this.props.document.color, "black"), opacity: 0.4 }}>
             {<FontAwesomeIcon icon={this._collapsed ? (isDoc ? "caret-square-right" : "caret-right") : (isDoc ? "caret-square-down" : "caret-down")} />}
         </div>;
     }
@@ -532,7 +533,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
         return !this.childDocs ? (null) : (
             <div id="body" className="collectionTreeView-dropTarget"
-                style={{ overflow: "auto" }}
+                style={{ overflow: "auto", background: StrCast(this.props.Document.backgroundColor, "gray") }}
                 onContextMenu={this.onContextMenu}
                 onWheel={(e: React.WheelEvent) => (e.target as any).scrollHeight > (e.target as any).clientHeight && e.stopPropagation()}
                 onDrop={this.onTreeDrop}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index ec0e446e9..00407d39a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -36,7 +36,6 @@
     //   linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px);
     // background-size: 30px 30px;
     // }
-    box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
     opacity: 0.99;
     border: 0px solid $light-color-secondary;
     border-radius: inherit;
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 763693dd6..695ddc3ec 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -37,6 +37,7 @@ export class CurrentUserUtils {
         doc.gridGap = 5;
         doc.xMargin = 5;
         doc.yMargin = 5;
+        doc.boxShadow = "0 0";
         doc.excludeFromLibrary = true;
         doc.optionalRightCollection = Docs.Create.StackingDocument([], { title: "New mobile uploads" });
         // doc.library = Docs.Create.TreeDocument([doc], { title: `Library: ${CurrentUserUtils.email}` });
@@ -49,11 +50,13 @@ export class CurrentUserUtils {
             const workspaces = Docs.Create.TreeDocument([], { title: "Workspaces", height: 100 });
             workspaces.excludeFromLibrary = true;
             workspaces.workspaceLibrary = true;
+            workspaces.boxShadow = "0 0";
             doc.workspaces = workspaces;
         }
         if (doc.recentlyClosed === undefined) {
             const recentlyClosed = Docs.Create.TreeDocument([], { title: "Recently Closed", height: 75 });
             recentlyClosed.excludeFromLibrary = true;
+            recentlyClosed.boxShadow = "0 0";
             doc.recentlyClosed = recentlyClosed;
         }
         if (doc.sidebar === undefined) {
@@ -62,6 +65,8 @@ export class CurrentUserUtils {
             sidebar.gridGap = 5;
             sidebar.xMargin = 5;
             sidebar.yMargin = 5;
+            Doc.GetProto(sidebar).backgroundColor = "lightGray";
+            sidebar.boxShadow = "1 1 3";
             doc.sidebar = sidebar;
         }
 
-- 
cgit v1.2.3-70-g09d2

