From 233893698083cbcfcf39ddad8b57049aeb1ba842 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 13 Sep 2019 14:18:55 -0400
Subject: refactored how ruleProvider's work.   overloaded custom template  for
 creating metadata fields

---
 src/client/views/collections/CollectionSchemaView.tsx | 1 +
 1 file changed, 1 insertion(+)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9d83aa6c1..dca1d7c1d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -995,6 +995,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         Document={this.props.Document}
                         fitToBox={this.props.fitToBox}
                         onClick={this.props.onClick}
+                        ruleProvider={undefined}
                         showOverlays={this.props.showOverlays}
                         addDocument={this.props.addDocument}
                         removeDocument={this.props.removeDocument}
-- 
cgit v1.2.3-70-g09d2


From dd7679295b84ceba49b8d581bb64f97cc1a86fbb Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 13 Sep 2019 17:30:02 -0400
Subject: more rule provider fixes

---
 src/client/views/DocumentDecorations.tsx                        | 2 +-
 src/client/views/InkingControl.tsx                              | 8 +++++++-
 src/client/views/collections/CollectionSchemaCells.tsx          | 1 +
 src/client/views/collections/CollectionSchemaView.tsx           | 5 ++++-
 src/client/views/collections/CollectionStackingView.tsx         | 1 +
 src/client/views/collections/CollectionTreeView.tsx             | 3 +++
 src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 +-
 src/client/views/nodes/DocumentView.tsx                         | 2 +-
 src/client/views/nodes/FormattedTextBox.tsx                     | 2 ++
 src/client/views/nodes/KeyValuePair.tsx                         | 1 +
 10 files changed, 22 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ebdf2a749..ac103b2ea 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -848,7 +848,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         let templates: Map<Template, boolean> = new Map();
         Array.from(Object.values(Templates.TemplateList)).map(template => {
             let checked = false;
-            SelectionManager.SelectedDocuments().map(doc => checked = checked || (doc.props.Document["show" + template.Name] !== undefined));
+            SelectionManager.SelectedDocuments().map(doc => checked = checked || (doc.layoutDoc["show" + template.Name] !== undefined));
             templates.set(template, checked);
         });
 
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 86d0fc0be..94cc1f06c 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -51,7 +51,13 @@ export class InkingControl extends React.Component {
             let oldColors = selected.map(view => {
                 let targetDoc = view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document);
                 let oldColor = StrCast(targetDoc.backgroundColor);
-                if (view.props.ContainingCollectionView && view.props.ContainingCollectionView.props.Document.colorPalette) {
+                if (view.props.ContainingCollectionView) {
+                    if (!view.props.ContainingCollectionView.props.Document.colorPalette) {
+                        let defaultPalette = ["rg14,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)",
+                            "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",];
+                        let colorPalette = Cast(view.props.ContainingCollectionView.props.Document.colorPalette, listSpec("string"));
+                        if (!colorPalette) view.props.ContainingCollectionView.props.Document.colorPalette = new List<string>(defaultPalette);
+                    }
                     let cp = Cast(view.props.ContainingCollectionView.props.Document.colorPalette, listSpec("string")) as string[];
                     let closest = 0;
                     let dist = 10000000;
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index c59107b53..17a3f4f7c 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -149,6 +149,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             DataDoc: this.props.rowProps.original,
             fieldKey: this.props.rowProps.column.id as string,
             fieldExt: "",
+            ruleProvider: undefined,
             ContainingCollectionView: this.props.CollectionView,
             isSelected: returnFalse,
             select: emptyFunction,
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index dca1d7c1d..1a84f94c8 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -32,6 +32,7 @@ import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, Collection
 import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC";
 import { ComputedField, ScriptField } from "../../../new_fields/ScriptField";
 import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { DocumentType } from "../../documents/DocumentTypes";
 
 
 library.add(faCog, faPlus, faSortUp, faSortDown);
@@ -161,6 +162,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 DataDocument={this.previewDocument !== this.props.DataDoc ? this.props.DataDoc : undefined}
                 childDocs={this.childDocs}
                 renderDepth={this.props.renderDepth}
+                ruleProvider={this.props.Document.isRuleProvider && layoutDoc && layoutDoc.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider}
                 width={this.previewWidth}
                 height={this.previewHeight}
                 getTransform={this.getPreviewTransform}
@@ -901,6 +903,7 @@ interface CollectionSchemaPreviewProps {
     fitToBox?: boolean;
     width: () => number;
     height: () => number;
+    ruleProvider: Doc | undefined;
     showOverlays?: (doc: Doc) => { title?: string, caption?: string };
     CollectionView?: CollectionView | CollectionPDFView | CollectionVideoView;
     onClick?: ScriptField;
@@ -995,7 +998,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         Document={this.props.Document}
                         fitToBox={this.props.fitToBox}
                         onClick={this.props.onClick}
-                        ruleProvider={undefined}
+                        ruleProvider={this.props.ruleProvider}
                         showOverlays={this.props.showOverlays}
                         addDocument={this.props.addDocument}
                         removeDocument={this.props.removeDocument}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 91e10b0ac..89cccedff 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -144,6 +144,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             DataDocument={dataDoc}
             showOverlays={this.overlays}
             renderDepth={this.props.renderDepth}
+            ruleProvider={this.props.Document.isRuleProvider && layoutDoc.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider}
             fitToBox={this.props.fitToBox}
             onClick={layoutDoc.isTemplate ? this.onClickHandler : this.onChildClickHandler}
             width={width}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index f5bb76966..b1e063997 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -37,6 +37,7 @@ export interface TreeViewProps {
     containingCollection: Doc;
     renderDepth: number;
     deleteDoc: (doc: Doc) => boolean;
+    ruleProvider: Doc | undefined;
     moveDocument: DragManager.MoveFunction;
     dropAction: "alias" | "copy" | undefined;
     addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void;
@@ -324,6 +325,7 @@ class TreeView extends React.Component<TreeViewProps> {
                     DataDocument={this.resolvedDataDoc}
                     renderDepth={this.props.renderDepth}
                     showOverlays={this.noOverlays}
+                    ruleProvider={this.props.document.isRuleProvider && layoutDoc.type !== DocumentType.TEXT ? this.props.document : this.props.ruleProvider}
                     fitToBox={this.boundsOfCollectionDocument !== undefined}
                     width={this.docWidth}
                     height={this.docHeight}
@@ -491,6 +493,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 dataDoc={pair.data}
                 containingCollection={containingCollection}
                 treeViewId={treeViewId}
+                ruleProvider={containingCollection.isRuleProvider && pair.layout.type !== DocumentType.TEXT ? containingCollection : containingCollection.ruleProvider as Doc}
                 key={child[Id]}
                 indentDocument={indent}
                 renderDepth={renderDepth}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index e46e8cb88..cc5e887b2 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -287,7 +287,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             let palette = Array.from(Cast(this.props.container.props.Document.colorPalette, listSpec("string")) as string[]);
             let usedPaletted = new Map<string, number>();
             [...this.props.activeDocuments(), this.props.container.props.Document].map(child => {
-                let bg = StrCast(child.backgroundColor);
+                let bg = StrCast(child.layout instanceof Doc ? child.layout.backgroundColor : child.backgroundColor);
                 if (palette.indexOf(bg) !== -1) {
                     palette.splice(palette.indexOf(bg), 1);
                     if (usedPaletted.get(bg)) usedPaletted.set(bg, usedPaletted.get(bg)! + 1);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cc04c5a9f..591a507eb 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -811,7 +811,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
         let backgroundColor = this.layoutDoc.isBackground || (clusterCol && !colorSet) ?
             this.props.backgroundColor(this.layoutDoc) || StrCast(this.layoutDoc.backgroundColor) :
-            ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc);
+            ruleColor ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc);
         let foregroundColor = StrCast(this.layoutDoc.color);
         var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%";
         var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index a0dc054cf..ffb829825 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -285,6 +285,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         } else if (de.data instanceof DragManager.DocumentDragData) {
             const draggedDoc = de.data.draggedDocuments.length && de.data.draggedDocuments[0];
             if (draggedDoc && draggedDoc.type === DocumentType.TEXT) {
+                // let m = Doc.MakeDelegate(draggedDoc);  // under construction
+                // m.layout = m.layout.replace(/fieldKey={})
                 this.props.Document.layout = draggedDoc.layout instanceof Doc ? draggedDoc.layout : draggedDoc;
                 draggedDoc.isTemplate = true;
                 e.stopPropagation();
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index a27dbd83d..7e0f3735d 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -55,6 +55,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             Document: this.props.doc,
             DataDoc: this.props.doc,
             ContainingCollectionView: undefined,
+            ruleProvider: undefined,
             fieldKey: this.props.keyName,
             fieldExt: "",
             isSelected: returnFalse,
-- 
cgit v1.2.3-70-g09d2


From 827cee4d7ac4f1e761b141097d20671e7873bea8 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 15 Sep 2019 01:14:21 -0400
Subject: changed moveDocument to move the draggedDoc -- its up to the caller
 to add the droppedDoc if it wants to. cleaned up some old code related to
 passing dataDoc along with doc's to drag and other functinos

---
 src/client/util/DragManager.ts                     | 16 ++++-----
 src/client/views/DocumentDecorations.tsx           | 20 +++++------
 src/client/views/MainOverlayTextBox.tsx            |  2 +-
 src/client/views/TemplateMenu.tsx                  |  2 +-
 .../views/collections/CollectionBaseView.tsx       | 13 ++++---
 .../views/collections/CollectionDockingView.tsx    | 14 +++-----
 .../views/collections/CollectionSchemaCells.tsx    |  3 +-
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../CollectionStackingViewFieldColumn.tsx          |  2 +-
 src/client/views/collections/CollectionSubView.tsx |  8 +++--
 src/client/views/collections/CollectionView.tsx    |  3 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx | 40 +++++++---------------
 src/client/views/linking/LinkMenuGroup.tsx         |  2 +-
 src/client/views/nodes/DocumentView.tsx            | 35 ++++++-------------
 src/client/views/nodes/DragBox.tsx                 |  2 +-
 src/client/views/pdf/Page.tsx                      |  2 +-
 src/client/views/search/SearchItem.tsx             |  2 +-
 18 files changed, 67 insertions(+), 103 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4c9c9c17c..252accefa 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -32,7 +32,7 @@ export function SetupDrag(
         document.removeEventListener("pointermove", onRowMove);
         document.removeEventListener('pointerup', onRowUp);
         let doc = await docFunc();
-        var dragData = new DragManager.DocumentDragData([doc], [undefined]);
+        var dragData = new DragManager.DocumentDragData([doc]);
         dragData.dropAction = dropAction;
         dragData.moveDocument = moveFunc;
         dragData.options = options;
@@ -76,7 +76,7 @@ export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: num
     if (draggeddoc) {
         let moddrag = await Cast(draggeddoc.annotationOn, Doc);
         let dragdocs = moddrag ? [moddrag] : [draggeddoc];
-        let dragData = new DragManager.DocumentDragData(dragdocs, dragdocs);
+        let dragData = new DragManager.DocumentDragData(dragdocs);
         dragData.moveDocument = moveLinkedDocument;
         DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, {
             handlers: {
@@ -107,7 +107,7 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n
             if (doc) moddrag.push(doc);
         }
         let dragdocs = moddrag.length ? moddrag : draggedDocs;
-        let dragData = new DragManager.DocumentDragData(dragdocs, dragdocs);
+        let dragData = new DragManager.DocumentDragData(dragdocs);
         dragData.moveDocument = moveLinkedDocument;
         DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, {
             handlers: {
@@ -201,15 +201,13 @@ export namespace DragManager {
 
     export type MoveFunction = (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
     export class DocumentDragData {
-        constructor(dragDoc: Doc[], dragDataDocs: (Doc | undefined)[]) {
+        constructor(dragDoc: Doc[]) {
             this.draggedDocuments = dragDoc;
-            this.draggedDataDocs = dragDataDocs;
             this.droppedDocuments = dragDoc;
             this.xOffset = 0;
             this.yOffset = 0;
         }
         draggedDocuments: Doc[];
-        draggedDataDocs: (Doc | undefined)[];
         droppedDocuments: Doc[];
         xOffset: number;
         yOffset: number;
@@ -253,7 +251,7 @@ export namespace DragManager {
     }
 
     export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize?: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) {
-        let dragData = new DragManager.DocumentDragData([], [undefined]);
+        let dragData = new DragManager.DocumentDragData([]);
         runInAction(() => StartDragFunctions.map(func => func()));
         StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag :
             (dropData: { [id: string]: any }) => {
@@ -363,8 +361,6 @@ export namespace DragManager {
 
         const docs: Doc[] =
             dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnnotationDragData ? [dragData.dragDocument] : [];
-        const datadocs: (Doc | undefined)[] =
-            dragData instanceof DocumentDragData ? dragData.draggedDataDocs : dragData instanceof AnnotationDragData ? [dragData.dragDocument] : [];
         let dragElements = eles.map(ele => {
             const w = ele.offsetWidth,
                 h = ele.offsetHeight;
@@ -449,7 +445,7 @@ export namespace DragManager {
                     pageY: e.pageY,
                     preventDefault: emptyFunction,
                     button: 0
-                }, docs, datadocs);
+                }, docs);
             }
             //TODO: Why can't we use e.movementX and e.movementY?
             let moveX = e.pageX - lastX;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ac103b2ea..ac1f51688 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -253,7 +253,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 ? dv.props.DataDoc : dv.props.Document));
+        let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
         dragData.xOffset = xoff;
         dragData.yOffset = yoff;
         dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument;
@@ -358,15 +358,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             if (this._iconDoc && selectedDocs.length === 1 && this._removeIcon) {
                 selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc);
             }
-            if (!this._removeIcon) {
-                if (selectedDocs.length === 1) {
-                    this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].toggleMinimized());
-                } else if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD &&
-                    Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) {
-                    let docViews = SelectionManager.ViewsSortedVertically();
-                    let topDocView = docViews[0];
-                    topDocView.props.Document.subBulletDocs = new List<Doc>(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!));
-                }
+            if (!this._removeIcon && selectedDocs.length === 1) { // if you click on the top-left button when just 1 doc is selected, then collapse it.  not sure why we don't do it for multiple selections
+                this.getIconDoc(selectedDocs[0]).then(async icon => {
+                    let minimizedDoc = await Cast(selectedDocs[0].props.Document.minimizedDoc, Doc);
+                    if (minimizedDoc) {
+                        let scrpt = selectedDocs[0].props.ScreenToLocalTransform().scale(selectedDocs[0].props.ContentScaling()).inverse().transformPoint(
+                            NumCast(minimizedDoc.x) - NumCast(selectedDocs[0].Document.x), NumCast(minimizedDoc.y) - NumCast(selectedDocs[0].Document.y));
+                        selectedDocs[0].collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs));
+                    }
+                });
             }
             this._removeIcon = false;
         }
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 71fb2707d..cd8423a12 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -102,7 +102,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
         if ((e.movementX > 1 || e.movementY > 1) && FormattedTextBox.InputBoxOverlay) {
             document.removeEventListener("pointermove", this.textBoxMove);
             document.removeEventListener('pointerup', this.textBoxUp);
-            let dragData = new DragManager.DocumentDragData([FormattedTextBox.InputBoxOverlay.props.Document], [FormattedTextBox.InputBoxOverlay.props.DataDoc]);
+            let dragData = new DragManager.DocumentDragData([FormattedTextBox.InputBoxOverlay.props.Document]);
             const [left, top] = this._textXf().inverse().transformPoint(0, 0);
             dragData.xOffset = e.clientX - left;
             dragData.yOffset = e.clientY - top;
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index af3fcaa24..d57a72dad 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -67,7 +67,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
             setTimeout(() => {
                 let newDocView = DocumentManager.Instance.getDocumentView(topDoc);
                 if (newDocView) {
-                    let de = new DragManager.DocumentDragData([topDoc], [undefined]);
+                    let de = new DragManager.DocumentDragData([topDoc]);
                     de.moveDocument = topDocView.props.moveDocument;
                     let xf = newDocView.ContentDiv!.getBoundingClientRect();
                     DragManager.StartDocumentDrag([newDocView.ContentDiv!], de, ex, ey, {
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index b7036b3ff..a54718e9e 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -141,17 +141,16 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         return false;
     }
 
+    // this is called with the document that was dragged and the collection to move it into.
+    // if the target collection is the same as this collection, then the move will be allowed.
+    // otherwise, the document being moved must be able to be removed from its container before
+    // moving it into the target.  
     @action.bound
     moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean {
-        let self = this;
-        let targetDataDoc = this.props.Document;
-        if (Doc.AreProtosEqual(targetDataDoc, targetCollection)) {
+        if (Doc.AreProtosEqual(this.props.Document, targetCollection)) {
             return true;
         }
-        if (this.removeDocument(doc)) {
-            return addDocument(doc);
-        }
-        return false;
+        return this.removeDocument(doc) ? addDocument(doc) : false;
     }
 
     render() {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 166fa0811..bf55dba31 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -66,15 +66,15 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     }
     hack: boolean = false;
     undohack: any = null;
-    public StartOtherDrag(e: any, dragDocs: Doc[], dragDataDocs: (Doc | undefined)[] = []) {
+    public StartOtherDrag(e: any, dragDocs: Doc[]) {
         let config: any;
         if (dragDocs.length === 1) {
-            config = CollectionDockingView.makeDocumentConfig(dragDocs[0], dragDataDocs[0]);
+            config = CollectionDockingView.makeDocumentConfig(dragDocs[0], undefined);
         } else {
             config = {
                 type: 'row',
                 content: dragDocs.map((doc, i) => {
-                    CollectionDockingView.makeDocumentConfig(doc, dragDataDocs[i]);
+                    CollectionDockingView.makeDocumentConfig(doc, undefined);
                 })
             };
         }
@@ -84,12 +84,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             dragSource.destroy();
         });
         dragSource._dragListener.onMouseDown(e);
-        // dragSource.destroy();
-        // this.hack = true;
-        // this.undohack = UndoManager.StartBatch("goldenDrag");
-        // dragDocs.map((dragDoc, i) =>
-        //     this.AddRightSplit(dragDoc, dragDataDocs[i], true).contentItems[0].tab._dragListener.
-        //         onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 }));
     }
 
     @action
@@ -412,7 +406,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                     e => {
                         e.preventDefault();
                         e.stopPropagation();
-                        DragManager.StartDocumentDrag([dragSpan], new DragManager.DocumentDragData([doc], [dataDoc]), e.clientX, e.clientY, {
+                        DragManager.StartDocumentDrag([dragSpan], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, {
                             handlers: { dragComplete: emptyFunction },
                             hideSource: false
                         });
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 17a3f4f7c..3452e8702 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -172,7 +172,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         let onItemDown = (e: React.PointerEvent) => {
             if (fieldIsDoc) {
                 SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
-                    this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
+                    this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument,
+                    this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
             }
         };
         let onPointerEnter = (e: React.PointerEvent): void => {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 1a84f94c8..25d3bd128 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -14,7 +14,7 @@ import { listSpec } from "../../../new_fields/Schema";
 import { Docs, DocumentOptions } from "../../documents/Documents";
 import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { Gateway } from "../../northstar/manager/Gateway";
-import { SetupDrag, DragManager } from "../../util/DragManager";
+import { DragManager } from "../../util/DragManager";
 import { CompileScript, ts, Transformer } from "../../util/Scripting";
 import { Transform } from "../../util/Transform";
 import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss';
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 185bec7a2..34f2652ff 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -183,7 +183,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             if (compiled.compiled) {
                 let scriptField = new ScriptField(compiled);
                 alias.viewSpecScript = scriptField;
-                let dragData = new DragManager.DocumentDragData([alias], [alias.proto]);
+                let dragData = new DragManager.DocumentDragData([alias]);
                 DragManager.StartDocumentDrag([this._headerRef.current!], dragData, e.clientX, e.clientY);
             }
 
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 270916522..bc994cffd 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -126,9 +126,11 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 if (de.data.dropAction || de.data.userDropAction) {
                     added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false);
                 } 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.Document, this.props.addDocument) || added, false);
+                    let movedDocs = de.data.draggedDocuments;// de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments;
+                    // note that it's possible the drag function might create a drop document that's not the same as the
+                    // original dragged document.  So we explicitly call addDocument() with a droppedDocument and 
+                    added = movedDocs.reduce((added: boolean, d, i) =>
+                        de.data.moveDocument(d, this.props.Document, (doc: Doc) => this.props.addDocument(de.data.droppedDocuments[i])) || added, false);
                 } else {
                     added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false);
                 }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index bce4eb427..548f663ec 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -95,8 +95,9 @@ export class CollectionView extends React.Component<FieldViewProps> {
             }
             subItems.push({ description: "Schema", event: () => this.props.Document.viewType = CollectionViewType.Schema, icon: "th-list" });
             subItems.push({ description: "Treeview", event: () => this.props.Document.viewType = CollectionViewType.Tree, icon: "tree" });
+            subItems.push({ description: "Stacking", event: () => this.props.Document.viewType = CollectionViewType.Stacking, icon: "ellipsis-v" });
             subItems.push({
-                description: "Stacking", event: () => {
+                description: "Stacking (AutoHeight)", event: () => {
                     this.props.Document.viewType = CollectionViewType.Stacking;
                     this.props.Document.autoHeight = true
                 }, icon: "ellipsis-v"
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ad91eb007..f2ca645a7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -381,7 +381,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             SelectionManager.DeselectAll();
             prevSelected.map(dv => SelectionManager.SelectDoc(dv, true));
 
-            let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined));
+            let de = new DragManager.DocumentDragData(eles);
             de.moveDocument = this.props.moveDocument;
             const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0);
             const [xoff, yoff] = this.getTransform().transformDirection(e.x - left, e.y - top);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index cc5e887b2..5cab6f8e0 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -315,7 +315,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             dataExtensionField.ink = inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined;
             this.marqueeInkDelete(inkData);
 
-            if (e.key === "s") {
+            if (e.key === "s" || e.key === "S") {
                 selected.map(d => {
                     this.props.removeDocument(d);
                     d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
@@ -324,35 +324,19 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     return d;
                 });
                 newCollection.chromeStatus = "disabled";
-                let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
-                newCollection.proto!.summaryDoc = summary;
-                selected = [newCollection];
-                newCollection.x = bounds.left + bounds.width;
-                summary.proto!.subBulletDocs = new List<Doc>(selected);
-                let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" });
-                container.viewType = CollectionViewType.Stacking;
-                container.autoHeight = true;
-                this.props.addLiveTextDocument(container);
-                // });
-            } else if (e.key === "S") {
-                selected.map(d => {
-                    this.props.removeDocument(d);
-                    d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
-                    d.y = NumCast(d.y) - bounds.top - bounds.height / 2;
-                    d.page = -1;
-                    return d;
-                });
-                newCollection.chromeStatus = "disabled";
-                let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
+                let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
+                summary.proto!.maximizeLocation = "inTab";  // or "inPlace", or "onRight"
                 newCollection.proto!.summaryDoc = summary;
-                selected = [newCollection];
                 newCollection.x = bounds.left + bounds.width;
-                //this.props.addDocument(newCollection, false);
-                summary.proto!.summarizedDocs = new List<Doc>(selected);
-                summary.proto!.maximizeLocation = "inTab";  // or "inPlace", or "onRight"
-                summary.autoHeight = true;
-
-                this.props.addLiveTextDocument(summary);
+                if (e.key === "s") { // summary is wrapped in an expand/collapse container that also contains the summarized documents in a free form view.
+                    let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" });
+                    container.viewType = CollectionViewType.Stacking;
+                    container.autoHeight = true;
+                    this.props.addLiveTextDocument(container);
+                } else if (e.key === "S") { // the summary stands alone, but is linked to a collection of the summarized documents - set the OnCLick behavior to link follow to access them
+                    summary.proto!.summarizedDocs = new List<Doc>([newCollection]);
+                    this.props.addLiveTextDocument(summary);
+                }
             }
             else {
                 this.props.addDocument(newCollection, false);
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index b6a24b0c8..d711ac284 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -57,7 +57,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
                     let opp = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
                     if (opp) return opp;
                 }) as Doc[];
-                let dragData = new DragManager.DocumentDragData(draggedDocs, draggedDocs.map(d => undefined));
+                let dragData = new DragManager.DocumentDragData(draggedDocs);
 
                 DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, {
                     handlers: {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e95f484a4..17bf02448 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -138,7 +138,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     private _downY: number = 0;
     private _lastTap: number = 0;
     private _doubleTap = false;
-    private _hitExpander = false;
     private _hitTemplateDrag = false;
     private _mainCont = React.createRef<HTMLDivElement>();
     private _dropDisposer?: DragManager.DragDropDisposer;
@@ -221,20 +220,19 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     get dataDoc() {
-        if (this.props.DataDoc === undefined && (this.props.Document.layout instanceof Doc || this.props.Document instanceof Promise)) {
-            // if there is no dataDoc (ie, we're not rendering a temlplate layout), but this document
-            // has a template layout document, then we will render the template layout but use 
-            // this document as the data document for the layout.
-            return this.props.Document;
-        }
+        // bcz: don't think we need this, but left it in in case strange behavior pops up.  DocumentContentsView has this functionality
+        // if (this.props.DataDoc === undefined && (this.props.Document.layout instanceof Doc || this.props.Document instanceof Promise)) {
+        //     // if there is no dataDoc (ie, we're not rendering a temlplate layout), but this document
+        //     // has a template layout document, then we will render the template layout but use 
+        //     // this document as the data document for the layout.
+        //     return this.props.Document;
+        // }
         return this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined;
     }
-    startDragging(x: number, y: number, dropAction: dropActionType, dragSubBullets: boolean, applyAsTemplate?: boolean) {
+    startDragging(x: number, y: number, dropAction: dropActionType, applyAsTemplate?: boolean) {
         if (this._mainCont.current) {
-            let allConnected = [this.props.Document, ...(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);
+            let dragData = new DragManager.DocumentDragData([this.props.Document]);
             const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
             dragData.dropAction = dropAction;
             dragData.xOffset = xoff;
@@ -249,14 +247,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             });
         }
     }
-    toggleMinimized = async () => {
-        let minimizedDoc = await Cast(this.props.Document.minimizedDoc, Doc);
-        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));
-        }
-    }
 
     static _undoBatch?: UndoManager.Batch = undefined;
     @action
@@ -315,15 +305,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             SelectionManager.SelectDoc(this, e.ctrlKey);
             let isExpander = (e.target as any).id === "isExpander";
             if (BoolCast(this.props.Document.isButton) || this.props.Document.type === DocumentType.BUTTON || isExpander) {
-                let subBulletDocs = await DocListCastAsync(this.props.Document.subBulletDocs);
                 let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs);
                 let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs);
                 let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document);
                 let expandedDocs: Doc[] = [];
-                expandedDocs = subBulletDocs ? [...subBulletDocs, ...expandedDocs] : expandedDocs;
                 expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs;
                 expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs;
-                // let expandedDocs = [...(subBulletDocs ? subBulletDocs : []), ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),];
+                // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),];
                 if (expandedDocs.length) {   // bcz: need a better way to associate behaviors with click events on widget-documents
                     SelectionManager.DeselectAll();
                     let maxLocation = StrCast(this.props.Document.maximizeLocation, "inPlace");
@@ -394,7 +382,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (e.nativeEvent.cancelBubble) return;
         this._downX = e.clientX;
         this._downY = e.clientY;
-        this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0;
         this._hitTemplateDrag = false;
         for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) {
             if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") {
@@ -416,7 +403,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 if (!e.altKey && !this.topMost && e.buttons === 1 && !BoolCast(this.props.Document.lockedPosition)) {
                     document.removeEventListener("pointermove", this.onPointerMove);
                     document.removeEventListener("pointerup", this.onPointerUp);
-                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitExpander, this._hitTemplateDrag);
+                    this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag);
                 }
             }
             e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx
index 1f2c88086..067d47de4 100644
--- a/src/client/views/nodes/DragBox.tsx
+++ b/src/client/views/nodes/DragBox.tsx
@@ -55,7 +55,7 @@ export class DragBox extends DocComponent<FieldViewProps, DragDocument>(DragDocu
             let doc = res !== undefined && res.success ?
                 res.result as Doc :
                 Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" });
-            doc && DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc], [undefined]), e.clientX, e.clientY);
+            doc && DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY);
         }
         e.stopPropagation();
         e.preventDefault();
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 856e883e7..533247170 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -137,7 +137,7 @@ export default class Page extends React.Component<IPageProps> {
         view.nativeWidth = this.props.Document.nativeWidth;
         view.startY = marquee.top + this.props.getScrollFromPage(this.props.page);
         view.width = this.props.Document[WidthSym]();
-        DragManager.StartDocumentDrag([], new DragManager.DocumentDragData([view], [undefined]), 0, 0);
+        DragManager.StartDocumentDrag([], new DragManager.DocumentDragData([view]), 0, 0);
     }
 
     @action
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index cd3dd912c..510672788 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -270,7 +270,7 @@ export class SearchItem extends React.Component<SearchItemProps> {
     onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {
         e.stopPropagation();
         const doc = Doc.IsPrototype(this.props.doc) ? Doc.MakeDelegate(this.props.doc) : this.props.doc;
-        DragManager.StartDocumentDrag([e.currentTarget], new DragManager.DocumentDragData([doc], []), e.clientX, e.clientY, {
+        DragManager.StartDocumentDrag([e.currentTarget], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, {
             handlers: { dragComplete: emptyFunction },
             hideSource: false,
         });
-- 
cgit v1.2.3-70-g09d2


From 088a16c9589e640e814d9120fecc0003ab9d594e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 18 Sep 2019 09:48:15 -0400
Subject: cleaned up some CompileScript code

---
 src/client/documents/Documents.ts                  |  6 ++--
 src/client/util/DragManager.ts                     | 10 +------
 .../views/collections/CollectionSchemaView.tsx     |  7 ++---
 .../CollectionStackingViewFieldColumn.tsx          | 10 ++-----
 .../views/collections/CollectionViewChromes.tsx    | 17 ++++-------
 .../collections/collectionFreeForm/MarqueeView.tsx | 21 +++++---------
 src/client/views/nodes/DocumentView.tsx            | 15 ++--------
 src/client/views/nodes/IconBox.tsx                 |  5 ++--
 src/client/views/nodes/ImageBox.tsx                |  5 +---
 src/client/views/nodes/PDFBox.tsx                  |  6 ++--
 src/client/views/nodes/VideoBox.tsx                | 14 +--------
 src/new_fields/Doc.ts                              |  9 ++----
 src/new_fields/ScriptField.ts                      | 33 ++++++++++++++++++----
 13 files changed, 58 insertions(+), 100 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 206e2c4f1..99707db19 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -663,10 +663,8 @@ export namespace DocUtils {
 
             LinkManager.Instance.addLink(linkDocProto);
 
-            let script = `return links(this);`;
-            let computed = CompileScript(script, { params: { this: "Doc" }, typecheck: false });
-            computed.compiled && (Doc.GetProto(source).links = new ComputedField(computed));
-            computed.compiled && (Doc.GetProto(target).links = new ComputedField(computed));
+            Doc.GetProto(source).links = ComputedField.MakeFunction("links(this)");
+            Doc.GetProto(target).links = ComputedField.MakeFunction("links(this)");
         }, "make link");
         return linkDocProto;
     }
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index cb55e1bc6..bd7051993 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -256,15 +256,7 @@ export namespace DragManager {
         StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag :
             (dropData: { [id: string]: any }) => {
                 let bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: title });
-                let compiled = CompileScript(script, {
-                    params: { doc: Doc.name },
-                    typecheck: false,
-                    editable: true
-                });
-                if (compiled.compiled) {
-                    let scriptField = new ScriptField(compiled);
-                    bd.onClick = scriptField;
-                }
+                bd.onClick = ScriptField.MakeScript(script);
                 params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc)));
                 initialize && initialize(bd);
                 bd.buttonParams = new List<string>(params);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 25d3bd128..5d09ade32 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -946,13 +946,10 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         if (de.data instanceof DragManager.DocumentDragData) {
-            let docDrag = de.data;
-            let computed = CompileScript("return this.image_data[0]", { params: { this: "Doc" } });
             this.props.childDocs && this.props.childDocs.map(otherdoc => {
-                let doc = docDrag.draggedDocuments[0];
                 let target = Doc.GetProto(otherdoc);
-                target.layout = target.detailedLayout = Doc.MakeDelegate(doc);
-                computed.compiled && (target.miniLayout = new ComputedField(computed));
+                target.layout = target.detailedLayout = Doc.MakeDelegate(de.data.draggedDocuments[0]);
+                target.miniLayout = ComputedField.MakeFunction("this.image_data[0]");
             });
             e.stopPropagation();
         }
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 34f2652ff..b3b7b40dd 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -178,13 +178,9 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             let key = StrCast(this.props.parent.props.Document.sectionFilter);
             let value = this.getValue(this._heading);
             value = typeof value === "string" ? `"${value}"` : value;
-            let script = `return doc.${key} === ${value}`;
-            let compiled = CompileScript(script, { params: { doc: Doc.name } });
-            if (compiled.compiled) {
-                let scriptField = new ScriptField(compiled);
-                alias.viewSpecScript = scriptField;
-                let dragData = new DragManager.DocumentDragData([alias]);
-                DragManager.StartDocumentDrag([this._headerRef.current!], dragData, e.clientX, e.clientY);
+            alias.viewSpecScript = ScriptField.MakeFunction(`doc.${key} === ${value}`, { doc: Doc.name });
+            if (alias.viewSpecScript) {
+                DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY);
             }
 
             e.stopPropagation();
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index c897af17e..7510b86a0 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -215,14 +215,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
             }
         }
         let fullScript = dateRestrictionScript.length || keyRestrictionScript.length ? dateRestrictionScript.length ?
-            `return ${dateRestrictionScript} ${keyRestrictionScript.length ? "&&" : ""} (${keyRestrictionScript})` :
-            `return (${keyRestrictionScript}) ${dateRestrictionScript.length ? "&&" : ""} ${dateRestrictionScript}` :
-            "return true";
+            `${dateRestrictionScript} ${keyRestrictionScript.length ? "&&" : ""} (${keyRestrictionScript})` :
+            `(${keyRestrictionScript}) ${dateRestrictionScript.length ? "&&" : ""} ${dateRestrictionScript}` :
+            "true";
 
-        let compiled = CompileScript(fullScript, { params: { doc: Doc.name }, typecheck: false });
-        if (compiled.compiled) {
-            this.props.CollectionView.props.Document.viewSpecScript = new ScriptField(compiled);
-        }
+        this.props.CollectionView.props.Document.viewSpecScript = ScriptField.MakeFunction(fullScript, { doc: Doc.name });
     }
 
     @action
@@ -283,11 +280,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
 
     @action.bound
     clearFilter = () => {
-        let compiled = CompileScript("return true", { params: { doc: Doc.name }, typecheck: false });
-        if (compiled.compiled) {
-            this.props.CollectionView.props.Document.viewSpecScript = new ScriptField(compiled);
-        }
-
+        this.props.CollectionView.props.Document.viewSpecScript = ScriptField.MakeFunction("true", { doc: Doc.name });
         this._keyRestrictions = [];
         this.addKeyRestrictions([]);
     }
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 8decebe0d..479e98840 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,30 +1,24 @@
-import * as htmlToImage from "html-to-image";
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, FieldResult, DocListCast } from "../../../../new_fields/Doc";
-import { Id } from "../../../../new_fields/FieldSymbols";
+import { Doc, DocListCast } from "../../../../new_fields/Doc";
 import { InkField, StrokeData } from "../../../../new_fields/InkField";
 import { List } from "../../../../new_fields/List";
+import { listSpec } from "../../../../new_fields/Schema";
+import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField";
+import { ComputedField } from "../../../../new_fields/ScriptField";
 import { Cast, NumCast, StrCast } from "../../../../new_fields/Types";
+import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
 import { Utils } from "../../../../Utils";
-import { DocServer } from "../../../DocServer";
 import { Docs } from "../../../documents/Documents";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
 import { InkingCanvas } from "../../InkingCanvas";
 import { PreviewCursor } from "../../PreviewCursor";
-import { Templates } from "../../Templates";
 import { CollectionViewType } from "../CollectionBaseView";
 import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
 import React = require("react");
-import { SchemaHeaderField, RandomPastel } from "../../../../new_fields/SchemaHeaderField";
-import { string } from "prop-types";
-import { listSpec } from "../../../../new_fields/Schema";
-import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
-import { CompileScript } from "../../../util/Scripting";
-import { ComputedField } from "../../../../new_fields/ScriptField";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -327,11 +321,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 });
                 newCollection.chromeStatus = "disabled";
                 let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
-                Doc.GetProto(newCollection).summaryDoc = summary;
                 Doc.GetProto(summary).summarizedDocs = new List<Doc>([newCollection]);
                 newCollection.x = bounds.left + bounds.width;
-                let computed = CompileScript(`return summaryTitle(this);`, { params: { this: "Doc" }, typecheck: false });
-                computed.compiled && (Doc.GetProto(newCollection).title = new ComputedField(computed));
+                Doc.GetProto(newCollection).summaryDoc = summary;
+                Doc.GetProto(newCollection).title = ComputedField.MakeFunction(`summaryTitle(this);`);
                 if (e.key === "s") { // summary is wrapped in an expand/collapse container that also contains the summarized documents in a free form view.
                     let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" });
                     container.viewType = CollectionViewType.Stacking;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 152dc3ddd..16f8275c7 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -40,7 +40,7 @@ import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import { FormattedTextBox } from './FormattedTextBox';
 import React = require("react");
-import { CompileScript, Scripting } from '../../util/Scripting';
+import { Scripting } from '../../util/Scripting';
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 library.add(fa.faTrash);
@@ -559,18 +559,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         let existingOnClick = ContextMenu.Instance.findByDescription("OnClick...");
         let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
         onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
-        onClicks.push({
-            description: "Toggle Detail", event: () => {
-                let compiled = CompileScript("toggleDetail(this)", {
-                    params: { this: "Doc" },
-                    typecheck: false,
-                    editable: true,
-                });
-                if (compiled.compiled) {
-                    this.Document.onClick = new ScriptField(compiled);
-                }
-            }, icon: "window-restore"
-        });
+        onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript("toggleDetail(this)"), icon: "window-restore" });
         onClicks.push({ description: this.layoutDoc.ignoreClick ? "Select" : "Do Nothing", event: () => this.layoutDoc.ignoreClick = !this.layoutDoc.ignoreClick, icon: this.layoutDoc.ignoreClick ? "unlock" : "lock" });
         onClicks.push({ description: this.Document.isButton || this.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.makeBtnClicked, icon: "concierge-bell" });
         onClicks.push({ description: "Edit onClick Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", obj.x, obj.y) });
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
index 92cb5a9c9..63a504d1a 100644
--- a/src/client/views/nodes/IconBox.tsx
+++ b/src/client/views/nodes/IconBox.tsx
@@ -12,7 +12,7 @@ import { IconField } from "../../../new_fields/IconField";
 import { ContextMenu } from "../ContextMenu";
 import Measure from "react-measure";
 import { MINIMIZED_ICON_SIZE } from "../../views/globalCssVariables.scss";
-import { Scripting, CompileScript } from "../../util/Scripting";
+import { Scripting } from "../../util/Scripting";
 import { ComputedField } from "../../../new_fields/ScriptField";
 
 
@@ -45,8 +45,7 @@ export class IconBox extends React.Component<FieldViewProps> {
     }
 
     public static AutomaticTitle(doc: Doc) {
-        let computed = CompileScript(`return iconTitle(this);`, { params: { this: "Doc" }, typecheck: false });
-        computed.compiled && (Doc.GetProto(doc).title = new ComputedField(computed));
+        Doc.GetProto(doc).title = ComputedField.MakeFunction('iconTitle(this);');
     }
 
     public static DocumentIcon(layout: string) {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 42307ee02..bbcc296e6 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -17,7 +17,6 @@ import { Utils } from '../../../Utils';
 import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices';
 import { Docs } from '../../documents/Documents';
 import { DragManager } from '../../util/DragManager';
-import { CompileScript } from '../../util/Scripting';
 import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from "../../views/ContextMenu";
 import { ContextMenuProps } from '../ContextMenuItem';
@@ -244,9 +243,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
             results.tags.map((tag: Tag) => {
                 tagsList.push(tag.name);
                 let sanitized = tag.name.replace(" ", "_");
-                let script = `return (${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`;
-                let computed = CompileScript(script, { params: { this: "Doc" } });
-                computed.compiled && (tagDoc[sanitized] = new ComputedField(computed));
+                tagDoc[sanitized] = ComputedField.MakeFunction(`(${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`);
             });
             this.extensionDoc.generatedTags = tagsList;
             tagDoc.title = "Generated Tags Doc";
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 31e8f122b..64b84ba55 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -10,7 +10,6 @@ import { ScriptField } from '../../../new_fields/ScriptField';
 import { BoolCast, Cast, NumCast } from "../../../new_fields/Types";
 import { PdfField } from "../../../new_fields/URLField";
 import { KeyCodes } from '../../northstar/utils/KeyCodes';
-import { CompileScript } from '../../util/Scripting';
 import { DocComponent } from "../DocComponent";
 import { InkingControl } from "../InkingControl";
 import { PDFViewer } from "../pdf/PDFViewer";
@@ -104,9 +103,8 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     private applyFilter = () => {
         let scriptText = this._scriptValue.length > 0 ? this._scriptValue :
             this._keyValue.length > 0 && this._valueValue.length > 0 ?
-                `return this.${this._keyValue} === ${this._valueValue}` : "return true";
-        let script = CompileScript(scriptText, { params: { this: Doc.name } });
-        script.compiled && (this.props.Document.filterScript = new ScriptField(script));
+                `this.${this._keyValue} === ${this._valueValue}` : "true";
+        this.props.Document.filterScript = ScriptField.MakeFunction(scriptText);
     }
 
     scrollTo = (y: number) => {
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index a696f255d..aa6be56bb 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -20,7 +20,6 @@ import { pageSchema } from "./ImageBox";
 import "./VideoBox.scss";
 import { library } from "@fortawesome/fontawesome-svg-core";
 import { faVideo } from "@fortawesome/free-solid-svg-icons";
-import { CompileScript } from "../../util/Scripting";
 import { Doc } from "../../../new_fields/Doc";
 import { ScriptField } from "../../../new_fields/ScriptField";
 var path = require('path');
@@ -116,18 +115,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
                 x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
                 width: 150, height: 50, title: NumCast(this.props.Document.curPage).toString()
             });
-            const script = CompileScript(`(self as any).curPage = ${NumCast(this.props.Document.curPage)}`, {
-                params: { this: Doc.name },
-                capturedVariables: { self: this.props.Document },
-                typecheck: false,
-                editable: true,
-            });
-            if (script.compiled) {
-                b.onClick = new ScriptField(script);
-                this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.addDocument && this.props.ContainingCollectionView.props.addDocument(b, false);
-            } else {
-                console.log(script.errors.map(error => error.messageText).join("\n"));
-            }
+            b.onClick = ScriptField.MakeScript(`this.curPage = ${NumCast(this.props.Document.curPage)}`);
         } else {
             //convert to desired file format
             var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png'
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index ffa9a4e98..98b3d824e 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -2,7 +2,7 @@ import { observable, ObservableMap, runInAction, action } from "mobx";
 import { alias, map, serializable } from "serializr";
 import { DocServer } from "../client/DocServer";
 import { DocumentType } from "../client/documents/DocumentTypes";
-import { CompileScript, Scripting, scriptingGlobal } from "../client/util/Scripting";
+import { Scripting, scriptingGlobal } from "../client/util/Scripting";
 import { afterDocDeserialize, autoObject, Deserializable, SerializationHelper } from "../client/util/SerializationHelper";
 import { Copy, HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, Update } from "./FieldSymbols";
 import { List } from "./List";
@@ -426,12 +426,7 @@ export namespace Doc {
             alias.layout = Doc.MakeAlias(alias.layout);
         }
         let aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1;
-        let script = `return renameAlias(self, ${aliasNumber})`;
-        //let script = "StrCast(self.title).replace(/\\([0-9]*\\)/, \"\") + `(${n})`";
-        let compiled = CompileScript(script, { params: { this: "Doc" }, capturedVariables: { self: doc }, typecheck: false });
-        if (compiled.compiled) {
-            alias.title = new ComputedField(compiled);
-        }
+        alias.title = ComputedField.MakeFunction(`renameAlias(this, ${aliasNumber})`);
         return alias;
     }
 
diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts
index 83fb52d07..8f10766df 100644
--- a/src/new_fields/ScriptField.ts
+++ b/src/new_fields/ScriptField.ts
@@ -1,5 +1,5 @@
 import { ObjectField } from "./ObjectField";
-import { CompiledScript, CompileScript, scriptingGlobal } from "../client/util/Scripting";
+import { CompiledScript, CompileScript, scriptingGlobal, ScriptOptions } from "../client/util/Scripting";
 import { Copy, ToScriptString, Parent, SelfProxy } from "./FieldSymbols";
 import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr";
 import { Deserializable, autoObject } from "../client/util/SerializationHelper";
@@ -101,6 +101,24 @@ export class ScriptField extends ObjectField {
     [ToScriptString]() {
         return "script field";
     }
+    public static CompileScript(script: string, params: object = {}, addReturn = false) {
+        let compiled = CompileScript(script, {
+            params: { this: Doc.name, ...params },
+            typecheck: false,
+            editable: true,
+            addReturn: addReturn
+        });
+        return compiled;
+    }
+    public static MakeFunction(script: string, params: object = {}) {
+        let compiled = ScriptField.CompileScript(script, params, true);
+        return compiled.compiled ? new ScriptField(compiled) : undefined;
+    }
+
+    public static MakeScript(script: string, params: object = {}) {
+        let compiled = ScriptField.CompileScript(script, params, false);
+        return compiled.compiled ? new ScriptField(compiled) : undefined;
+    }
 }
 
 @scriptingGlobal
@@ -109,11 +127,16 @@ export class ComputedField extends ScriptField {
     //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc
     value = computedFn((doc: Doc) => {
         const val = this.script.run({ this: doc });
-        if (val.success) {
-            return val.result;
-        }
-        return undefined;
+        return val.success ? val.result : undefined;
     });
+    public static MakeScript(script: string, params: object = {}, ) {
+        let compiled = ScriptField.CompileScript(script, params, false);
+        return compiled.compiled ? new ComputedField(compiled) : undefined;
+    }
+    public static MakeFunction(script: string, params: object = {}) {
+        let compiled = ScriptField.CompileScript(script, params, true);
+        return compiled.compiled ? new ComputedField(compiled) : undefined;
+    }
 }
 
 export namespace ComputedField {
-- 
cgit v1.2.3-70-g09d2


From 25ea85f7cf2c7f6109eb740ffc111325a39fb745 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 18 Sep 2019 22:20:12 -0400
Subject: a bunch more template cleanup.  no more miniLayout and
 detailedLayout.  just layoutNative and layoutCustom

---
 src/client/views/DocumentDecorations.tsx           | 15 +++--
 src/client/views/GlobalKeyHandler.ts               |  3 -
 .../views/collections/CollectionBaseView.tsx       |  1 -
 .../views/collections/CollectionSchemaView.tsx     |  6 +-
 .../views/collections/CollectionStackingView.tsx   |  6 --
 src/client/views/collections/CollectionSubView.tsx | 16 ++++-
 .../views/collections/CollectionTreeView.tsx       |  4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 26 --------
 src/client/views/nodes/DocumentView.tsx            | 19 +++---
 src/new_fields/Doc.ts                              | 74 ++++++----------------
 10 files changed, 56 insertions(+), 114 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 12bd84684..b730f88a4 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -24,7 +24,7 @@ import './DocumentDecorations.scss';
 import { LinkMenu } from "./linking/LinkMenu";
 import { MetadataEntryMenu } from './MetadataEntryMenu';
 import { PositionDocument } from './nodes/CollectionFreeFormDocumentView';
-import { DocumentView } from "./nodes/DocumentView";
+import { DocumentView, swapViews } from "./nodes/DocumentView";
 import { FieldView } from "./nodes/FieldView";
 import { FormattedTextBox, GoogleRef } from "./nodes/FormattedTextBox";
 import { IconBox } from "./nodes/IconBox";
@@ -155,16 +155,18 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 if (containerView) {
                     let docTemplate = containerView.props.Document;
                     let metaKey = text.startsWith(">>") ? text.slice(2, text.length) : text.slice(1, text.length);
-                    let proto = Doc.GetProto(docTemplate);
                     if (metaKey !== containerView.props.fieldKey && containerView.props.DataDoc) {
                         const fd = fieldTemplate.data;
                         fd instanceof ObjectField && (Doc.GetProto(containerView.props.DataDoc)[metaKey] = ObjectField.MakeCopy(fd));
                     }
                     fieldTemplate.title = metaKey;
-                    Doc.MakeMetadataFieldTemplate(fieldTemplate, proto);
+                    Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate));
                     if (text.startsWith(">>")) {
-                        proto.detailedLayout = proto.layout;
-                        proto.miniLayout = ImageBox.LayoutString(metaKey);
+                        let layoutNative = Doc.MakeTitled("layoutNative");
+                        Doc.GetProto(docTemplate).layoutNative = layoutNative;
+                        swapViews(fieldTemplate, "", "layoutNative", layoutNative);
+                        layoutNative.layout = StrCast(fieldTemplateView.props.Document.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`);
+                        layoutNative.backgroundLayout = StrCast(fieldTemplateView.props.Document.backgroundLayout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`);
                     }
                 }
             }
@@ -845,8 +847,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
         let templates: Map<Template, boolean> = new Map();
         Array.from(Object.values(Templates.TemplateList)).map(template =>
-            templates.set(template, SelectionManager.SelectedDocuments().reduce((checked, doc) => checked || (doc.
-                Document["show" + template.Name] ? true : false), false)));
+            templates.set(template, SelectionManager.SelectedDocuments().reduce((checked, doc) => checked || (doc.props.Document["show" + template.Name] ? true : false), false)));
 
         bounds.x = Math.max(0, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
         bounds.y = Math.max(0, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight;
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 59229418d..ef5d76ce8 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -88,9 +88,6 @@ export default class KeyManager {
                     });
                 }, "delete");
                 break;
-            case "enter":
-                SelectionManager.SelectedDocuments().map(selected => Doc.ToggleDetailLayout(selected.props.Document));
-                break;
         }
 
         return {
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index e4e798608..fdb2f0dc9 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -12,7 +12,6 @@ import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
 import './CollectionBaseView.scss';
 import { DateField } from '../../../new_fields/DateField';
-import { DocumentType } from '../../documents/DocumentTypes';
 
 export enum CollectionViewType {
     Invalid,
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 5d09ade32..4d2b8e1c1 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -948,8 +948,10 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
         if (de.data instanceof DragManager.DocumentDragData) {
             this.props.childDocs && this.props.childDocs.map(otherdoc => {
                 let target = Doc.GetProto(otherdoc);
-                target.layout = target.detailedLayout = Doc.MakeDelegate(de.data.draggedDocuments[0]);
-                target.miniLayout = ComputedField.MakeFunction("this.image_data[0]");
+                let layoutNative = Doc.MakeTitled("layoutNative");
+                layoutNative.layout = ComputedField.MakeFunction("this.image_data[0]");
+                target.layoutNative = layoutNative;
+                target.layoutCUstom = target.layout = Doc.MakeDelegate(de.data.draggedDocuments[0]);
             });
             e.stopPropagation();
         }
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 14a9dc9d9..ccf131797 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -29,7 +29,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
     _heightDisposer?: IReactionDisposer;
-    _childLayoutDisposer?: IReactionDisposer;
     _sectionFilterDisposer?: IReactionDisposer;
     _docXfs: any[] = [];
     _columnStart: number = 0;
@@ -87,10 +86,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     componentDidMount() {
-        this._childLayoutDisposer = reaction(() => [this.childDocs, Cast(this.props.Document.childLayout, Doc)],
-            async (args) => args[1] instanceof Doc &&
-                this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc), undefined)));
-
         // is there any reason this needs to exist? -syip.  yes, it handles autoHeight for stacking views (masonry isn't yet supported).
         this._heightDisposer = reaction(() => {
             if (this.isStackingView && BoolCast(this.props.Document.autoHeight)) {
@@ -115,7 +110,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         );
     }
     componentWillUnmount() {
-        this._childLayoutDisposer && this._childLayoutDisposer();
         this._heightDisposer && this._heightDisposer();
         this._sectionFilterDisposer && this._sectionFilterDisposer();
     }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index d13c69ecf..001560167 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,4 +1,4 @@
-import { action, computed } from "mobx";
+import { action, computed, IReactionDisposer, reaction } from "mobx";
 import * as rp from 'request-promise';
 import CursorField from "../../../new_fields/CursorField";
 import { Doc, DocListCast } from "../../../new_fields/Doc";
@@ -50,6 +50,18 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
+        _childLayoutDisposer?: IReactionDisposer;
+
+        componentDidMount() {
+            this._childLayoutDisposer = reaction(() => [this.childDocs, Cast(this.props.Document.childLayout, Doc)],
+                async (args) => args[1] instanceof Doc &&
+                    this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc))));
+
+        }
+        componentWillUnmount() {
+            this._childLayoutDisposer && this._childLayoutDisposer();
+        }
+
         @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); }
 
 
@@ -119,7 +131,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             if (de.data instanceof DragManager.DocumentDragData && !de.data.applyAsTemplate) {
                 if (de.mods === "AltKey" && de.data.draggedDocuments.length) {
                     this.childDocs.map(doc =>
-                        Doc.ApplyTemplateTo(de.data.draggedDocuments[0], doc, undefined)
+                        Doc.ApplyTemplateTo(de.data.draggedDocuments[0], doc)
                     );
                     e.stopPropagation();
                     return true;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index fed833261..b4026a810 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -178,7 +178,7 @@ class TreeView extends React.Component<TreeViewProps> {
         SetValue={undoBatch((value: string) => (Doc.GetProto(this.dataDoc)[key] = value) ? true : true)}
         OnFillDown={undoBatch((value: string) => {
             Doc.GetProto(this.dataDoc)[key] = value;
-            let doc = this.props.document.detailedLayout instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.document.detailedLayout)) : undefined;
+            let doc = this.props.document.layoutCustom instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.document.layoutCustom)) : undefined;
             if (!doc) doc = Docs.Create.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);
@@ -613,7 +613,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                     SetValue={undoBatch((value: string) => (Doc.GetProto(this.resolvedDataDoc).title = value) ? true : true)}
                     OnFillDown={undoBatch((value: string) => {
                         Doc.GetProto(this.props.Document).title = value;
-                        let doc = this.props.Document.detailedLayout instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.Document.detailedLayout)) : undefined;
+                        let doc = this.props.Document.layoutCustom instanceof Doc ? Doc.ApplyTemplate(Doc.GetProto(this.props.Document.layoutCustom)) : undefined;
                         if (!doc) doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) });
                         TreeView.loadId = doc[Id];
                         Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true, false, false, false);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index baf907634..c9e78cee6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -186,32 +186,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private _inkKey = "ink"; // the document key used to store ink annotation strokes
     private get _pwidth() { return this.props.PanelWidth(); }
     private get _pheight() { return this.props.PanelHeight(); }
-    private _childLayoutDisposer?: IReactionDisposer;
-    private _childDisposer?: IReactionDisposer;
-
-    componentDidMount() {
-        this._childDisposer = reaction(() => this.childDocs,
-            async (childDocs) => {
-                let childLayout = Cast(this.props.Document.childLayout, Doc) as Doc;
-                childLayout && childDocs.map(async doc => {
-                    if (!Doc.AreProtosEqual(childLayout, (await doc).layout as Doc)) {
-                        Doc.ApplyTemplateTo(childLayout, doc, undefined);
-                    }
-                });
-            });
-        this._childLayoutDisposer = reaction(() => Cast(this.props.Document.childLayout, Doc),
-            async (childLayout) => {
-                this.childDocs.map(async doc => {
-                    if (!Doc.AreProtosEqual(childLayout as Doc, (await doc).layout as Doc)) {
-                        Doc.ApplyTemplateTo(childLayout as Doc, doc, undefined);
-                    }
-                });
-            });
-    }
-    componentWillUnmount() {
-        this._childDisposer && this._childDisposer();
-        this._childLayoutDisposer && this._childLayoutDisposer();
-    }
 
     get parentScaling() {
         return (this.props as any).ContentScaling && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 90dbe4c86..d4e396752 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -220,9 +220,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (this._doubleTap && this.props.renderDepth) {
             e.stopPropagation();
             let fullScreenAlias = Doc.MakeAlias(this.props.Document);
-            Doc.UseDetailLayout(fullScreenAlias);
-            fullScreenAlias.showCaption = "caption";
-            this.props.addDocTab(fullScreenAlias, this.props.DataDoc, "inTab");
+            let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc));
+            if (layoutNative && fullScreenAlias.layout === layoutNative.layout) {
+                await swapViews(fullScreenAlias, "layoutCustom", "layoutNative");
+            }
+            this.props.addDocTab(fullScreenAlias, undefined, "inTab");
             SelectionManager.DeselectAll();
             Doc.UnBrushDoc(this.props.Document);
         }
@@ -392,7 +394,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             DocUtils.MakeLink(sourceDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Link from ${StrCast(sourceDoc.title)}`);
         }
         if (de.data instanceof DragManager.DocumentDragData && de.data.applyAsTemplate) {
-            Doc.ApplyTemplateTo(de.data.draggedDocuments[0], this.props.Document, this.props.DataDoc);
+            Doc.ApplyTemplateTo(de.data.draggedDocuments[0], this.props.Document);
             e.stopPropagation();
         }
         if (de.data instanceof DragManager.LinkDragData) {
@@ -528,9 +530,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         layoutItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" });
         layoutItems.push({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" });
         layoutItems.push({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" });
-        if (this.props.Document.detailedLayout && !this.Document.isTemplate) {
-            layoutItems.push({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" });
-        }
         if (this.Document.type !== DocumentType.COL && this.Document.type !== DocumentType.TEMPLATE) {
             layoutItems.push({ description: "Use Custom Layout", event: this.makeCustomViewClicked, icon: "concierge-bell" });
         } else if (this.props.Document.layoutNative) {
@@ -728,8 +727,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 }
 
-let swapViews = async (doc: any, newLayoutField: any, oldLayoutField: any) => {
-    let oldLayoutExt = await Cast(doc[oldLayoutField], Doc);
+export async function swapViews(doc: Doc, newLayoutField: string, oldLayoutField: string, oldLayout?: Doc) {
+    let oldLayoutExt = oldLayout || await Cast(doc[oldLayoutField], Doc);
     if (oldLayoutExt) {
         oldLayoutExt.autoHeight = doc.autoHeight;
         oldLayoutExt.width = doc.width;
@@ -737,6 +736,7 @@ let swapViews = async (doc: any, newLayoutField: any, oldLayoutField: any) => {
         oldLayoutExt.nativeWidth = doc.nativeWidth;
         oldLayoutExt.nativeHeight = doc.nativeHeight;
         oldLayoutExt.ignoreAspect = doc.ignoreAspect;
+        oldLayoutExt.backgroundLayout = doc.backgroundLayout;
         oldLayoutExt.type = doc.type;
         oldLayoutExt.layout = doc.layout;
     }
@@ -749,6 +749,7 @@ let swapViews = async (doc: any, newLayoutField: any, oldLayoutField: any) => {
         doc.nativeWidth = newLayoutExt.nativeWidth;
         doc.nativeHeight = newLayoutExt.nativeHeight;
         doc.ignoreAspect = newLayoutExt.ignoreAspect;
+        doc.backgroundLayout = newLayoutExt.backgroundLayout;
         doc.type = newLayoutExt.type;
         doc.layout = await newLayoutExt.layout;
     }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index af7775d94..0859cf41a 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -544,22 +544,9 @@ export namespace Doc {
 
     let _applyCount: number = 0;
     export function ApplyTemplate(templateDoc: Doc) {
-        if (!templateDoc) return undefined;
-        let datadoc = new Doc();
-        let otherdoc = Doc.MakeDelegate(datadoc);
-        otherdoc.width = templateDoc[WidthSym]();
-        otherdoc.height = templateDoc[HeightSym]();
-        otherdoc.title = templateDoc.title + "(..." + _applyCount++ + ")";
-        otherdoc.layout = Doc.MakeDelegate(templateDoc);
-        otherdoc.miniLayout = StrCast(templateDoc.miniLayout);
-        otherdoc.detailedLayout = otherdoc.layout;
-        otherdoc.type = DocumentType.TEMPLATE;
-        !templateDoc.nativeWidth && (otherdoc.nativeWidth = 0);
-        !templateDoc.nativeHeight && (otherdoc.nativeHeight = 0);
-        !templateDoc.nativeWidth && (otherdoc.ignoreAspect = true);
-        return otherdoc;
-    }
-    export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetData?: Doc) {
+        return !templateDoc ? undefined : ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), templateDoc.title + "(..." + _applyCount++ + ")");
+    }
+    export function ApplyTemplateTo(templateDoc: Doc, target: Doc, titleTarget: string | undefined = undefined) {
         if (!templateDoc) {
             target.layout = undefined;
             target.nativeWidth = undefined;
@@ -568,25 +555,24 @@ export namespace Doc {
             target.type = undefined;
             return;
         }
-        let temp = Doc.MakeDelegate(templateDoc);
-        target.nativeWidth = Doc.GetProto(target).nativeWidth = undefined;
-        target.nativeHeight = Doc.GetProto(target).nativeHeight = undefined;
-        !templateDoc.nativeWidth && (target.nativeWidth = 0);
-        !templateDoc.nativeHeight && (target.nativeHeight = 0);
-        !templateDoc.nativeHeight && (target.ignoreAspect = true);
+
+        let layoutCustom = Doc.MakeTitled("layoutCustom");
+        let layoutCustomLayout = Doc.MakeDelegate(templateDoc);
+
+        titleTarget && (target.title = titleTarget);
+        target.type = DocumentType.TEMPLATE;
         target.width = templateDoc.width;
         target.height = templateDoc.height;
+        target.nativeWidth = templateDoc.nativeWidth ? templateDoc.nativeWidth : 0;
+        target.nativeHeight = templateDoc.nativeHeight ? templateDoc.nativeHeight : 0;
+        target.ignoreAspect = templateDoc.nativeWidth ? true : false;
         target.onClick = templateDoc.onClick instanceof ObjectField && templateDoc.onClick[Copy]();
-        target.type = DocumentType.TEMPLATE;
-        if (targetData && targetData.layout === target) {
-            targetData.layout = temp;
-            targetData.miniLayout = StrCast(templateDoc.miniLayout);
-            targetData.detailedLayout = targetData.layout;
-        } else {
-            target.layout = temp;
-            target.miniLayout = StrCast(templateDoc.miniLayout);
-            target.detailedLayout = target.layout;
-        }
+        target.layout = layoutCustomLayout;
+        target.backgroundLayout = layoutCustomLayout.backgroundLayout;
+
+        target.layoutNative = Cast(templateDoc.layoutNative, Doc) as Doc;
+        target.layoutCustom = layoutCustom;
+        return target;
     }
 
     export function MakeMetadataFieldTemplate(fieldTemplate: Doc, templateDataDoc: Doc, suppressTitle: boolean = false) {
@@ -628,30 +614,6 @@ export namespace Doc {
         }), 0);
     }
 
-    export function ToggleDetailLayout(d: Doc) {
-        runInAction(async () => {
-            let miniLayout = await PromiseValue(d.miniLayout);
-            let detailLayout = await PromiseValue(d.detailedLayout);
-            d.layout !== miniLayout ? miniLayout && (d.layout = d.miniLayout) : detailLayout && (d.layout = detailLayout);
-            if (d.layout === detailLayout) d.nativeWidth = d.nativeHeight = 0;
-            if (StrCast(d.layout) !== "") d.nativeWidth = d.nativeHeight = undefined;
-        });
-    }
-    export function UseDetailLayout(d: Doc) {
-        runInAction(async () => {
-            let detailLayout = await d.detailedLayout;
-            if (detailLayout) {
-                d.layout = detailLayout;
-                d.nativeWidth = d.nativeHeight = undefined;
-                if (detailLayout instanceof Doc) {
-                    let delegDetailLayout = Doc.MakeDelegate(detailLayout);
-                    d.layout = delegDetailLayout;
-                    delegDetailLayout.layout = await delegDetailLayout.detailedLayout;
-                }
-            }
-        });
-    }
-
     export function isBrushedHighlightedDegree(doc: Doc) {
         if (Doc.IsHighlighted(doc)) {
             return 3;
-- 
cgit v1.2.3-70-g09d2


From be5456616a7813572b9fdc9637d4009e7283a46a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 19 Sep 2019 00:11:23 -0400
Subject: added ContainingCollectionDoc to props that get passed around.

---
 src/client/documents/Documents.ts                  |   2 +-
 .../util/Import & Export/DirectoryImportBox.tsx    |   5 +-
 src/client/util/TooltipTextMenu.tsx                |   4 +-
 src/client/views/DocumentDecorations.tsx           |  11 +-
 src/client/views/InkingControl.tsx                 |  20 +--
 src/client/views/MainOverlayTextBox.tsx            |   6 +-
 src/client/views/MainView.tsx                      |   2 +
 src/client/views/OverlayView.tsx                   |   1 +
 .../views/collections/CollectionDockingView.tsx    |   1 +
 .../views/collections/CollectionSchemaCells.tsx    |   1 +
 .../CollectionSchemaMovableTableHOC.tsx            |   8 +-
 .../views/collections/CollectionSchemaView.tsx     |   3 +
 .../CollectionFreeFormLinksView.tsx                |   6 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   2 +
 src/client/views/linking/LinkFollowBox.tsx         |  30 ++--
 src/client/views/nodes/DocumentView.tsx            | 164 ++++++++++-----------
 src/client/views/nodes/FieldView.tsx               |   1 +
 src/client/views/nodes/KeyValuePair.tsx            |   1 +
 src/client/views/nodes/PDFBox.tsx                  |   2 +-
 .../views/presentationview/PresentationElement.tsx |   1 +
 src/client/views/search/FilterBox.tsx              |   6 +-
 src/client/views/search/SearchItem.tsx             |   1 +
 22 files changed, 136 insertions(+), 142 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 99707db19..2fa0d2dcb 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -640,7 +640,7 @@ export namespace DocUtils {
     export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", sourceContext?: Doc, id?: string, anchored1?: boolean) {
         if (LinkManager.Instance.doesLinkExist(source, target)) return undefined;
         let sv = DocumentManager.Instance.getDocumentView(source);
-        if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return;
+        if (sv && sv.props.ContainingCollectionDoc === target) return;
         if (target === CurrentUserUtils.UserDocument) return undefined;
 
         let linkDocProto = new Doc(id, true);
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 75b0b52a7..dc6a0cb7a 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx	
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx	
@@ -134,11 +134,10 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps>
             x: NumCast(doc.x),
             y: NumCast(doc.y) + offset
         };
-        let parent = this.props.ContainingCollectionView;
-        if (parent) {
+        if (this.props.ContainingCollectionDoc) {
             let importContainer = Docs.Create.StackingDocument(docs, options);
             importContainer.singleColumn = false;
-            Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer);
+            Doc.AddDocToList(Doc.GetProto(this.props.ContainingCollectionDoc), "data", importContainer);
             !this.persistent && this.props.removeDocument && this.props.removeDocument(doc);
             DocumentManager.Instance.jumpToDocument(importContainer, true);
 
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 5764af282..aa096dd64 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -310,8 +310,8 @@ export class TooltipTextMenu {
                             dragComplete: action(() => {
                                 let linkDoc = dragData.linkDocument;
                                 let proto = Doc.GetProto(linkDoc);
-                                if (proto && docView && docView.props.ContainingCollectionView) {
-                                    proto.sourceContext = docView.props.ContainingCollectionView.props.Document;
+                                if (proto && docView) {
+                                    proto.sourceContext = docView.props.ContainingCollectionDoc;
                                 }
                                 linkDoc instanceof Doc && this.makeLink(Utils.prepend("/doc/" + linkDoc[Id]), ctrlKey ? "onRight" : "inTab");
                             }),
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b730f88a4..ad38d16aa 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -152,8 +152,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 SelectionManager.DeselectAll();
                 let fieldTemplate = fieldTemplateView.props.Document;
                 let containerView = fieldTemplateView.props.ContainingCollectionView;
-                if (containerView) {
-                    let docTemplate = containerView.props.Document;
+                let docTemplate = fieldTemplateView.props.ContainingCollectionDoc;
+                if (containerView && docTemplate) {
                     let metaKey = text.startsWith(">>") ? text.slice(2, text.length) : text.slice(1, text.length);
                     if (metaKey !== containerView.props.fieldKey && containerView.props.DataDoc) {
                         const fd = fieldTemplate.data;
@@ -431,8 +431,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         dist = dist < 3 ? 0 : dist;
         let usingRule = false;
         SelectionManager.SelectedDocuments().map(dv => {
-            let cv = dv.props.ContainingCollectionView;
-            let ruleProvider = cv && cv.props.ruleProvider;
+            let ruleProvider = dv.props.ruleProvider;
             let heading = NumCast(dv.props.Document.heading);
             ruleProvider && heading && (Doc.GetProto(ruleProvider)["ruleRounding_" + heading] = `${Math.min(100, dist)}%`);
             usingRule = usingRule || (ruleProvider && heading ? true : false);
@@ -502,7 +501,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             document.removeEventListener("pointermove", this.onLinkerButtonMoved);
             document.removeEventListener("pointerup", this.onLinkerButtonUp);
             let selDoc = SelectionManager.SelectedDocuments()[0];
-            let container = selDoc.props.ContainingCollectionView ? selDoc.props.ContainingCollectionView.props.Document.proto : undefined;
+            let container = selDoc.props.ContainingCollectionDoc ? selDoc.props.ContainingCollectionDoc.proto : undefined;
             let dragData = new DragManager.LinkDragData(selDoc.props.Document, container ? [container] : []);
             FormattedTextBox.InputBoxOverlay = undefined;
             this._linkDrag = UndoManager.StartBatch("Drag Link");
@@ -847,7 +846,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
         let templates: Map<Template, boolean> = new Map();
         Array.from(Object.values(Templates.TemplateList)).map(template =>
-            templates.set(template, SelectionManager.SelectedDocuments().reduce((checked, doc) => checked || (doc.props.Document["show" + template.Name] ? true : false), false)));
+            templates.set(template, SelectionManager.SelectedDocuments().reduce((checked, doc) => checked || (doc.props.Document["show" + template.Name] ? true : false), false as boolean)));
 
         bounds.x = Math.max(0, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
         bounds.y = Math.max(0, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight;
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 57dad5e6b..a10df0e75 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -52,16 +52,16 @@ export class InkingControl extends React.Component {
                 let targetDoc = view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document);
                 let oldColor = StrCast(targetDoc.backgroundColor);
                 let matchedColor = this._selectedColor;
-                const cv = view.props.ContainingCollectionView;
-                let ruleProvider: Doc | undefined;
-                if (cv) {
-                    if (!cv.props.Document.colorPalette) {
-                        let defaultPalette = ["rg14,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)",
+                const cvd = view.props.ContainingCollectionDoc;
+                let ruleProvider = view.props.ruleProvider;
+                if (cvd) {
+                    if (!cvd.colorPalette) {
+                        let defaultPalette = ["rg(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)",
                             "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",];
-                        let colorPalette = Cast(cv.props.Document.colorPalette, listSpec("string"));
-                        if (!colorPalette) cv.props.Document.colorPalette = new List<string>(defaultPalette);
+                        let colorPalette = Cast(cvd.colorPalette, listSpec("string"));
+                        if (!colorPalette) cvd.colorPalette = new List<string>(defaultPalette);
                     }
-                    let cp = Cast(cv.props.Document.colorPalette, listSpec("string")) as string[];
+                    let cp = Cast(cvd.colorPalette, listSpec("string")) as string[];
                     let closest = 0;
                     let dist = 10000000;
                     let ccol = Utils.fromRGBAstr(StrCast(targetDoc.backgroundColor));
@@ -74,9 +74,9 @@ export class InkingControl extends React.Component {
                         }
                     }
                     cp[closest] = "rgba(" + color.rgb.r + "," + color.rgb.g + "," + color.rgb.b + "," + color.rgb.a + ")";
-                    cv.props.Document.colorPalette = new List(cp);
+                    cvd.colorPalette = new List(cp);
                     matchedColor = cp[closest];
-                    ruleProvider = (view.props.Document.heading && cv && cv.props.ruleProvider) ? cv.props.ruleProvider : undefined;
+                    ruleProvider = (view.props.Document.heading && ruleProvider) ? ruleProvider : undefined;
                     ruleProvider && ((Doc.GetProto(ruleProvider)["ruleColor_" + NumCast(view.props.Document.heading)] = Utils.toRGBAstr(color.rgb)));
                 }
                 !ruleProvider && (targetDoc.backgroundColor = matchedColor);
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 8e72d236c..ac1b437af 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -142,9 +142,9 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
                                 DataDoc={FormattedTextBox.InputBoxOverlay.props.DataDoc}
                                 onClick={undefined}
                                 ruleProvider={this._textBox ? this._textBox.props.ruleProvider : undefined}
-                                ChromeHeight={this.ChromeHeight}
-                                isSelected={returnTrue} select={emptyFunction} renderDepth={0}
-                                ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne}
+                                ChromeHeight={this.ChromeHeight} isSelected={returnTrue} select={emptyFunction} renderDepth={0}
+                                ContainingCollectionDoc={undefined} ContainingCollectionView={undefined}
+                                whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne}
                                 ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction}
                                 pinToPres={returnZero} addDocTab={this.addDocTab} outer_div={(tooltip: HTMLElement) => { this._tooltip = tooltip; this.updateTooltip(); }} />
                         </div>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 2cec1c052..8b0caf9a6 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -335,6 +335,7 @@ export class MainView extends React.Component {
                             whenActiveChanged={emptyFunction}
                             bringToFront={emptyFunction}
                             ContainingCollectionView={undefined}
+                            ContainingCollectionDoc={undefined}
                             zoomToScale={emptyFunction}
                             getScale={returnOne}
                         />}
@@ -399,6 +400,7 @@ export class MainView extends React.Component {
             whenActiveChanged={emptyFunction}
             bringToFront={emptyFunction}
             ContainingCollectionView={undefined}
+            ContainingCollectionDoc={undefined}
             zoomToScale={emptyFunction}
             getScale={returnOne}>
         </DocumentView>;
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 15faea3cd..8124ce653 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -189,6 +189,7 @@ export class OverlayView extends React.Component {
                     addDocTab={emptyFunction}
                     pinToPres={emptyFunction}
                     ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
                     zoomToScale={emptyFunction}
                     getScale={returnOne} />
             </div>;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 55ba3a314..cab085d9b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -639,6 +639,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
             addDocTab={this.addDocTab}
             pinToPres={this.PinDoc}
             ContainingCollectionView={undefined}
+            ContainingCollectionDoc={undefined}
             zoomToScale={emptyFunction}
             getScale={returnOne} />;
     }
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 3452e8702..059967a7d 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -151,6 +151,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             fieldExt: "",
             ruleProvider: undefined,
             ContainingCollectionView: this.props.CollectionView,
+            ContainingCollectionDoc: this.props.CollectionView.props.Document,
             isSelected: returnFalse,
             select: emptyFunction,
             renderDepth: this.props.renderDepth + 1,
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index ec40043cc..39abc41ec 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -201,12 +201,8 @@ export class MovableRow extends React.Component<MovableRowProps> {
     @action
     move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => {
         let targetView = DocumentManager.Instance.getDocumentView(target);
-        if (targetView) {
-            let targetContainingColl = targetView.props.ContainingCollectionView; //.props.ContainingCollectionView.props.Document;
-            if (targetContainingColl) {
-                let targetContCollDoc = targetContainingColl.props.Document;
-                return doc !== target && doc !== targetContCollDoc && this.props.removeDoc(doc) && addDoc(doc);
-            }
+        if (targetView && targetView.props.ContainingCollectionDoc) {
+            return doc !== target && doc !== targetView.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc);
         }
         return doc !== target && this.props.removeDoc(doc) && addDoc(doc);
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4d2b8e1c1..a742054d0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -196,6 +196,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 childDocs={this.childDocs}
                 CollectionView={this.props.CollectionView}
                 ContainingCollectionView={this.props.ContainingCollectionView}
+                ContainingCollectionDoc={this.props.ContainingCollectionDoc}
                 fieldKey={this.props.fieldKey}
                 renderDepth={this.props.renderDepth}
                 moveDocument={this.props.moveDocument}
@@ -247,6 +248,7 @@ export interface SchemaTableProps {
     childDocs?: Doc[];
     CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
+    ContainingCollectionDoc: Opt<Doc>;
     fieldKey: string;
     renderDepth: number;
     deleteDocument: (document: Doc) => boolean;
@@ -1004,6 +1006,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         moveDocument={this.props.moveDocument}
                         whenActiveChanged={this.props.whenActiveChanged}
                         ContainingCollectionView={this.props.CollectionView}
+                        ContainingCollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
                         addDocTab={this.props.addDocTab}
                         pinToPres={this.props.pinToPres}
                         parentActive={this.props.active}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index a25627dd1..a81f5315a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -79,15 +79,15 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
         if (containerDoc) {
             equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.proto!);
         }
-        if (view.props.ContainingCollectionView) {
-            let collid = view.props.ContainingCollectionView.props.Document[Id];
+        if (view.props.ContainingCollectionDoc) {
+            let collid = view.props.ContainingCollectionDoc[Id];
             DocListCast(this.props.Document[this.props.fieldKey]).
                 filter(child =>
                     child[Id] === collid).map(view =>
                         DocumentManager.Instance.getDocumentViews(view).map(view =>
                             equalViews.push(view)));
         }
-        return equalViews.filter(sv => sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document);
+        return equalViews.filter(sv => sv.props.ContainingCollectionDoc === this.props.Document);
     }
 
     @computed
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c9e78cee6..ad77e0428 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -659,6 +659,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             PanelHeight: childLayout[HeightSym],
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
+            ContainingCollectionDoc: this.props.CollectionView.props.Document,
             focus: this.focusDocument,
             backgroundColor: this.getClusterColor,
             parentActive: this.props.active,
@@ -685,6 +686,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             PanelHeight: layoutDoc[HeightSym],
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
+            ContainingCollectionDoc: this.props.CollectionView.props.Document,
             focus: this.focusDocument,
             backgroundColor: returnEmptyString,
             parentActive: this.props.active,
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index b1c6c367f..d7cb2585e 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -85,11 +85,10 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     }
 
     async resetPan() {
-        if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionView) {
-            let colDoc = this.sourceView.props.ContainingCollectionView.props.Document;
-            runInAction(() => { this.canPan = false; });
-            if (colDoc.viewType && colDoc.viewType === CollectionViewType.Freeform) {
-                let docs = Cast(colDoc.data, listSpec(Doc), []);
+        if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
+            runInAction(() => this.canPan = false);
+            if (this.sourceView.props.ContainingCollectionDoc.viewType === CollectionViewType.Freeform) {
+                let docs = Cast(this.sourceView.props.ContainingCollectionDoc.data, listSpec(Doc), []);
                 let aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(LinkFollowBox.destinationDoc));
 
                 aliases.forEach(alias => {
@@ -371,9 +370,9 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         this.shouldUseOnlyParentContext = (this.selectedMode === FollowModes.INPLACE || this.selectedMode === FollowModes.PAN);
 
         if (this.shouldUseOnlyParentContext) {
-            if (this.sourceView && this.sourceView.props.ContainingCollectionView) {
-                this.selectedContext = this.sourceView.props.ContainingCollectionView.props.Document;
-                this.selectedContextString = (StrCast(this.sourceView.props.ContainingCollectionView.props.Document.title));
+            if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
+                this.selectedContext = this.sourceView.props.ContainingCollectionDoc;
+                this.selectedContextString = (StrCast(this.sourceView.props.ContainingCollectionDoc.title));
             }
         }
     }
@@ -394,9 +393,8 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     @computed
     get canOpenInPlace() {
-        if (this.sourceView && this.sourceView.props.ContainingCollectionView) {
-            let colView = this.sourceView.props.ContainingCollectionView;
-            let colDoc = colView.props.Document;
+        if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
+            let colDoc = this.sourceView.props.ContainingCollectionDoc;
             if (colDoc.viewType && colDoc.viewType === CollectionViewType.Freeform) return true;
         }
         return false;
@@ -457,17 +455,15 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     @computed
     get parentName() {
-        if (this.sourceView && this.sourceView.props.ContainingCollectionView) {
-            let colView = this.sourceView.props.ContainingCollectionView;
-            return colView.props.Document.title;
+        if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
+            return this.sourceView.props.ContainingCollectionDoc.title;
         }
     }
 
     @computed
     get parentID(): string {
-        if (this.sourceView && this.sourceView.props.ContainingCollectionView) {
-            let colView = this.sourceView.props.ContainingCollectionView;
-            return StrCast(colView.props.Document[Id]);
+        if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
+            return StrCast(this.sourceView.props.ContainingCollectionDoc[Id]);
         }
         return "col";
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d4e396752..39bba2eb2 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -67,6 +67,7 @@ library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCom
 
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
+    ContainingCollectionDoc: Opt<Doc>;
     Document: Doc;
     DataDoc?: Doc;
     fitToBox?: boolean;
@@ -208,88 +209,83 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     onClick = async (e: React.MouseEvent) => {
-        if (e.nativeEvent.cancelBubble) return; // || SelectionManager.IsSelected(this)) -- bcz: needed because EditableView may stopPropagation which won't apparently stop this event from firing.
-        if (this.onClickHandler && this.onClickHandler.script) {
+        if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
+            (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
             e.stopPropagation();
-            this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document });
             e.preventDefault();
-            return;
+            if (this._doubleTap && this.props.renderDepth) {
+                let fullScreenAlias = Doc.MakeAlias(this.props.Document);
+                let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc));
+                if (layoutNative && fullScreenAlias.layout === layoutNative.layout) {
+                    await swapViews(fullScreenAlias, "layoutCustom", "layoutNative");
+                }
+                this.props.addDocTab(fullScreenAlias, undefined, "inTab");
+                SelectionManager.DeselectAll();
+                Doc.UnBrushDoc(this.props.Document);
+            } else if (this.onClickHandler && this.onClickHandler.script) {
+                this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document });
+            } else if (this.Document.isButton) {
+                SelectionManager.SelectDoc(this, e.ctrlKey); // don't think this should happen if a button action is actually triggered.
+                this.buttonClick(e.altKey, e.ctrlKey);
+            } else SelectionManager.SelectDoc(this, e.ctrlKey);
         }
-        let altKey = e.altKey;
-        let ctrlKey = e.ctrlKey;
-        if (this._doubleTap && this.props.renderDepth) {
-            e.stopPropagation();
-            let fullScreenAlias = Doc.MakeAlias(this.props.Document);
-            let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc));
-            if (layoutNative && fullScreenAlias.layout === layoutNative.layout) {
-                await swapViews(fullScreenAlias, "layoutCustom", "layoutNative");
-            }
-            this.props.addDocTab(fullScreenAlias, undefined, "inTab");
+    }
+
+    buttonClick = async (altKey: boolean, ctrlKey: boolean) => {
+        let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs);
+        let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs);
+        let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document);
+        let expandedDocs: Doc[] = [];
+        expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs;
+        expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs;
+        // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),];
+        if (expandedDocs.length) {
             SelectionManager.DeselectAll();
-            Doc.UnBrushDoc(this.props.Document);
-        }
-        else if (!this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
-            (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
-                Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
-            e.stopPropagation();
-            SelectionManager.SelectDoc(this, e.ctrlKey);
-            if (this.Document.isButton || this.Document.type === DocumentType.BUTTON) {
-                let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs);
-                let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs);
-                let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document);
-                let expandedDocs: Doc[] = [];
-                expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs;
-                expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs;
-                // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),];
-                if (expandedDocs.length) {
-                    SelectionManager.DeselectAll();
-                    let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace");
-                    let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target);
-                    if (altKey || ctrlKey) {
-                        maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace"));
-                        if (!maxLocation || maxLocation === "inPlace") {
-                            let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
-                            let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false);
-                            expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false);
-                            let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
-                            if (!hasView) {
-                                this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(getDispDoc(maxDoc), false));
-                            }
-                            expandedDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized);
-                        }
-                    }
-                    if (maxLocation && maxLocation !== "inPlace" && CollectionDockingView.Instance) {
-                        let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data);
-                        if (dataDocs) {
-                            expandedDocs.forEach(maxDoc =>
-                                (!CollectionDockingView.Instance.CloseRightSplit(Doc.GetProto(maxDoc)) &&
-                                    this.props.addDocTab(getDispDoc(maxDoc), undefined, maxLocation)));
-                        }
-                    } else {
-                        let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2);
-                        this.collapseTargetsToPoint(scrpt, expandedDocs);
+            let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace");
+            let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target);
+            if (altKey || ctrlKey) {
+                maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace"));
+                if (!maxLocation || maxLocation === "inPlace") {
+                    let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
+                    let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false);
+                    expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false);
+                    let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
+                    if (!hasView) {
+                        this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(getDispDoc(maxDoc), false));
                     }
+                    expandedDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized);
                 }
-                else if (linkedDocs.length) {
-                    SelectionManager.DeselectAll();
-                    let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document) && !d.anchor1anchored);
-                    let firstUnshown = first.filter(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0);
-                    if (firstUnshown.length) first = [firstUnshown[0]];
-                    let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]];
-
-                    // @TODO: shouldn't always follow target context
-                    let linkedFwdContextDocs = [first.length ? await (first[0].targetContext) as Doc : undefined, undefined];
-                    let linkedFwdPage = [first.length ? NumCast(first[0].anchor2Page, undefined) : undefined, undefined];
-
-                    if (!linkedFwdDocs.some(l => l instanceof Promise)) {
-                        let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab");
-                        let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
-                        DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false,
-                            // open up target if it's not already in view ... by zooming into the button document first and setting flag to reset zoom afterwards
-                            doc => this.props.focus(this.props.Document, true, 1, () => { this.props.addDocTab(doc, undefined, maxLocation); return true; }),
-                            linkedFwdPage[altKey ? 1 : 0], targetContext);
-                    }
+            }
+            if (maxLocation && maxLocation !== "inPlace" && CollectionDockingView.Instance) {
+                let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data);
+                if (dataDocs) {
+                    expandedDocs.forEach(maxDoc =>
+                        (!CollectionDockingView.Instance.CloseRightSplit(Doc.GetProto(maxDoc)) &&
+                            this.props.addDocTab(getDispDoc(maxDoc), undefined, maxLocation)));
                 }
+            } else {
+                let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2);
+                this.collapseTargetsToPoint(scrpt, expandedDocs);
+            }
+        }
+        else if (linkedDocs.length) {
+            SelectionManager.DeselectAll();
+            let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document) && !d.anchor1anchored);
+            let firstUnshown = first.filter(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0);
+            if (firstUnshown.length) first = [firstUnshown[0]];
+            let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]];
+
+            // @TODO: shouldn't always follow target context
+            let linkedFwdContextDocs = [first.length ? await (first[0].targetContext) as Doc : undefined, undefined];
+            let linkedFwdPage = [first.length ? NumCast(first[0].anchor2Page, undefined) : undefined, undefined];
+
+            if (!linkedFwdDocs.some(l => l instanceof Promise)) {
+                let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab");
+                let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionDoc) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
+                DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false,
+                    // open up target if it's not already in view ... by zooming into the button document first and setting flag to reset zoom afterwards
+                    doc => this.props.focus(this.props.Document, true, 1, () => { this.props.addDocTab(doc, undefined, maxLocation); return true; }),
+                    linkedFwdPage[altKey ? 1 : 0], targetContext);
             }
         }
     }
@@ -387,25 +383,21 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             let targetDoc = this.props.Document;
             let annotations = await DocListCastAsync(sourceDoc.annotations);
             sourceDoc.linkedToDoc = true;
-            de.data.targetContext = this.props.ContainingCollectionView!.props.Document;
+            de.data.targetContext = this.props.ContainingCollectionDoc;
             targetDoc.targetContext = de.data.targetContext;
             annotations && annotations.forEach(anno => anno.target = targetDoc);
 
-            DocUtils.MakeLink(sourceDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Link from ${StrCast(sourceDoc.title)}`);
+            DocUtils.MakeLink(sourceDoc, targetDoc, this.props.ContainingCollectionDoc, `Link from ${StrCast(sourceDoc.title)}`);
         }
         if (de.data instanceof DragManager.DocumentDragData && de.data.applyAsTemplate) {
             Doc.ApplyTemplateTo(de.data.draggedDocuments[0], this.props.Document);
             e.stopPropagation();
         }
         if (de.data instanceof DragManager.LinkDragData) {
-            let sourceDoc = de.data.linkSourceDocument;
-            let destDoc = this.props.Document;
-
             e.stopPropagation();
             // 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);
-            de.data.droppedDocuments.push(destDoc);
-            de.data.linkDocument = DocUtils.MakeLink(sourceDoc, destDoc, this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document);
+            de.data.linkDocument = DocUtils.MakeLink(de.data.linkSourceDocument, this.props.Document, this.props.ContainingCollectionDoc);
         }
     }
 
@@ -436,7 +428,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @undoBatch
     @action
     makeIntoPortal = async () => {
-        let anchors = await Promise.all(DocListCast(this.props.Document.links).map(async (d: Doc) => await Cast(d.anchor2, Doc)));
+        let anchors = await Promise.all(DocListCast(this.props.Document.links).map(async (d: Doc) => Cast(d.anchor2, Doc)));
         if (!anchors.find(anchor2 => anchor2 && anchor2.title === this.Document.title + ".portal" ? true : false)) {
             let portalID = (this.Document.title + ".portal").replace(/^-/, "").replace(/\([0-9]*\)$/, "");
             DocServer.GetRefField(portalID).then(existingPortal => {
@@ -512,7 +504,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         onClicks.push({ description: "Edit onClick Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", obj.x, obj.y) });
         onClicks.push({
             description: "Edit onClick Foreach Doc Script", icon: "edit", event: (obj: any) => {
-                this.props.Document.collectionContext = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document;
+                this.props.Document.collectionContext = this.props.ContainingCollectionDoc;
                 ScriptBox.EditButtonScript("Foreach Collection Doc (d) => ", this.props.Document, "onClick", obj.x, obj.y, "docList(this.collectionContext.data).map(d => {", "});\n");
             }
         });
@@ -637,7 +629,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined;
         const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined;
         const colorSet = this.Document.backgroundColor !== this.Document.defaultBackgroundColor;
-        const clusterCol = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground;
+        const clusterCol = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.clusterOverridesDefaultBackground;
         const backgroundColor = this.Document.isBackground || (clusterCol && !colorSet) ?
             this.props.backgroundColor(this.Document) || StrCast(this.Document.backgroundColor) :
             ruleColor && !colorSet ? ruleColor : StrCast(this.Document.backgroundColor) || this.props.backgroundColor(this.Document);
@@ -753,7 +745,7 @@ export async function swapViews(doc: Doc, newLayoutField: string, oldLayoutField
         doc.type = newLayoutExt.type;
         doc.layout = await newLayoutExt.layout;
     }
-};
+}
 
 Scripting.addGlobal(function toggleDetail(doc: any) {
     let native = typeof doc.layout === "string";
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 943d181d6..faf11e9be 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -30,6 +30,7 @@ export interface FieldViewProps {
     leaveNativeSize?: boolean;
     fitToBox?: boolean;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
+    ContainingCollectionDoc: Opt<Doc>;
     ruleProvider: Doc | undefined;
     Document: Doc;
     DataDoc?: Doc;
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 7e0f3735d..c7e0f51d7 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -55,6 +55,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             Document: this.props.doc,
             DataDoc: this.props.doc,
             ContainingCollectionView: undefined,
+            ContainingCollectionDoc: undefined,
             ruleProvider: undefined,
             fieldKey: this.props.keyName,
             fieldExt: "",
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 64b84ba55..c8534ed0d 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -31,7 +31,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     @observable private _alt = false;
     @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>;
 
-    @computed get containingCollectionDocument() { return this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; }
+    @computed get containingCollectionDocument() { return this.props.ContainingCollectionDoc; }
     @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
 
 
diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx
index 7be44faf6..126d62c52 100644
--- a/src/client/views/presentationview/PresentationElement.tsx
+++ b/src/client/views/presentationview/PresentationElement.tsx
@@ -366,6 +366,7 @@ export default class PresentationElement extends React.Component<PresentationEle
                     zoomToScale={emptyFunction}
                     getScale={returnOne}
                     ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
                     ContentScaling={scale}
                 />
                 <div style={{
diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx
index c13d1d276..da733d64b 100644
--- a/src/client/views/search/FilterBox.tsx
+++ b/src/client/views/search/FilterBox.tsx
@@ -195,11 +195,9 @@ export class FilterBox extends React.Component {
                     collections.push(element.props.Document);
                 }
             }
-            //gets the selected doc's containing view
-            let containingView = element.props.ContainingCollectionView;
             //makes sure collections aren't added more than once
-            if (containingView && !collections.includes(containingView.props.Document)) {
-                collections.push(containingView.props.Document);
+            if (element.props.ContainingCollectionDoc && !collections.includes(element.props.ContainingCollectionDoc)) {
+                collections.push(element.props.ContainingCollectionDoc);
             }
         });
 
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 510672788..b2e886d95 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -180,6 +180,7 @@ export class SearchItem extends React.Component<SearchItemProps> {
                     zoomToScale={emptyFunction}
                     getScale={returnOne}
                     ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
                     ContentScaling={scale}
                 />
             </div>;
-- 
cgit v1.2.3-70-g09d2


From 2cdca63ac039a7c66a9c93acb35fe51467269e64 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 19 Sep 2019 11:29:11 -0400
Subject: switche calls to COllectionDockingView... to addDocTabs.  fixed
 following links to navigate/restore properly.

---
 src/client/util/DocumentManager.ts                 | 15 ++--
 src/client/util/TooltipTextMenu.tsx                |  8 +-
 src/client/views/GlobalKeyHandler.ts               |  4 +-
 src/client/views/MainOverlayTextBox.tsx            |  4 +-
 src/client/views/MainView.tsx                      | 10 ++-
 src/client/views/OverlayView.tsx                   |  2 +-
 .../views/collections/CollectionBaseView.tsx       |  4 +-
 .../views/collections/CollectionDockingView.tsx    | 85 ++++++++++++----------
 .../views/collections/CollectionSchemaCells.tsx    |  2 +-
 .../views/collections/CollectionSchemaView.tsx     |  4 +-
 .../views/collections/CollectionTreeView.tsx       |  8 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 17 +++--
 src/client/views/linking/LinkFollowBox.tsx         | 16 ++--
 src/client/views/linking/LinkMenu.tsx              |  2 +-
 src/client/views/linking/LinkMenuGroup.tsx         | 24 +++---
 src/client/views/linking/LinkMenuItem.tsx          |  2 +-
 src/client/views/nodes/DocumentView.tsx            | 24 ++----
 src/client/views/nodes/FieldView.tsx               |  2 +-
 src/client/views/nodes/KeyValueBox.tsx             |  2 +-
 src/client/views/nodes/KeyValuePair.tsx            |  7 +-
 src/client/views/pdf/Annotation.tsx                |  8 +-
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 src/client/views/search/SearchItem.tsx             |  4 +-
 23 files changed, 127 insertions(+), 129 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ec731da84..65ab32539 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -10,6 +10,7 @@ import { DocumentView } from '../views/nodes/DocumentView';
 import { LinkManager } from './LinkManager';
 import { undoBatch, UndoManager } from './UndoManager';
 import { Scripting } from './Scripting';
+import { emptyFunction } from '../../Utils';
 
 
 export class DocumentManager {
@@ -146,6 +147,7 @@ export class DocumentManager {
             if (!contextDoc) {
                 let docs = docContext ? await DocListCastAsync(docContext.data) : undefined;
                 let found = false;
+                // bcz: this just searches within the context for the target -- perhaps it should recursively search through all children?
                 docs && docs.map(d => found = found || Doc.AreProtosEqual(d, docDelegate));
                 if (docContext && found) {
                     let targetContextView: DocumentView | null;
@@ -154,16 +156,19 @@ export class DocumentManager {
                         docContext.panTransformType = "Ease";
                         targetContextView.props.focus(docDelegate, willZoom);
                     } else {
-                        (dockFunc || CollectionDockingView.Instance.AddRightSplit)(docContext, undefined);
+                        (dockFunc || CollectionDockingView.AddRightSplit)(docContext, undefined);
                         setTimeout(() => {
-                            this.jumpToDocument(docDelegate, willZoom, forceDockFunc, dockFunc, linkPage);
-                        }, 10);
+                            let dv = DocumentManager.Instance.getDocumentView(docContext);
+                            dv && this.jumpToDocument(docDelegate, willZoom, forceDockFunc,
+                                doc => dv!.props.focus(dv!.props.Document, true, 1, () => dv!.props.addDocTab(doc, undefined, "inPlace")),
+                                linkPage);
+                        }, 1050);
                     }
                 } else {
                     const actualDoc = Doc.MakeAlias(docDelegate);
                     Doc.BrushDoc(actualDoc);
                     if (linkPage !== undefined) actualDoc.curPage = linkPage;
-                    (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc, undefined);
+                    (dockFunc || CollectionDockingView.AddRightSplit)(actualDoc, undefined);
                 }
             } else {
                 let contextView: DocumentView | null;
@@ -172,7 +177,7 @@ export class DocumentManager {
                     contextDoc.panTransformType = "Ease";
                     contextView.props.focus(docDelegate, willZoom);
                 } else {
-                    (dockFunc || CollectionDockingView.Instance.AddRightSplit)(contextDoc, undefined);
+                    (dockFunc || CollectionDockingView.AddRightSplit)(contextDoc, undefined);
                     setTimeout(() => {
                         this.jumpToDocument(docDelegate, willZoom, forceDockFunc, dockFunc, linkPage);
                     }, 10);
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index aa096dd64..b6de048e4 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -58,10 +58,6 @@ export class TooltipTextMenu {
 
     private _collapsed: boolean = false;
 
-    @observable
-    private _storedMarks: Mark<any>[] | null | undefined;
-
-
     constructor(view: EditorView, editorProps: FieldViewProps & FormattedTextBoxProps) {
         this.view = view;
         this.editorProps = editorProps;
@@ -84,8 +80,6 @@ export class TooltipTextMenu {
 
         this.dragElement(dragger);
 
-        this._storedMarks = this.view.state.storedMarks;
-
         // this.createCollapse();
         // if (this._collapseBtn) {
         //     this.tooltip.appendChild(this._collapseBtn.render(this.view).dom);
@@ -280,7 +274,7 @@ export class TooltipTextMenu {
                                 if (DocumentManager.Instance.getDocumentView(f)) {
                                     DocumentManager.Instance.getDocumentView(f)!.props.focus(f, false);
                                 }
-                                else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f, undefined);
+                                else this.editorProps.addDocTab(f, undefined, "onRight");
                             }
                         }));
                     }
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index ef5d76ce8..2fa03e969 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -141,7 +141,7 @@ export default class KeyManager {
                         return { stopPropagation: false, preventDefault: false };
                     }
                 }
-                MainView.Instance.mainFreeform && CollectionDockingView.Instance.AddRightSplit(MainView.Instance.mainFreeform, undefined);
+                MainView.Instance.mainFreeform && CollectionDockingView.AddRightSplit(MainView.Instance.mainFreeform, undefined);
                 break;
             case "arrowleft":
                 if (document.activeElement) {
@@ -149,7 +149,7 @@ export default class KeyManager {
                         return { stopPropagation: false, preventDefault: false };
                     }
                 }
-                MainView.Instance.mainFreeform && CollectionDockingView.Instance.CloseRightSplit(MainView.Instance.mainFreeform);
+                MainView.Instance.mainFreeform && CollectionDockingView.CloseRightSplit(MainView.Instance.mainFreeform);
                 break;
             case "backspace":
                 if (document.activeElement) {
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index ac1b437af..f32fb584a 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -119,9 +119,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
     }
 
     addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => {
-        if (true) { // location === "onRight") { need to figure out stack to add "inTab"
-            CollectionDockingView.Instance.AddRightSplit(doc, dataDoc);
-        }
+        this._textBox && this._textBox.props.addDocTab(doc, dataDoc, location);
     }
     render() {
         this.TextDoc; this.TextDataDoc;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8b0caf9a6..097040b6c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -288,6 +288,7 @@ export class MainView extends React.Component {
                 }
             }
         }, 100);
+        return true;
     }
 
     onDrop = (e: React.DragEvent<HTMLDivElement>) => {
@@ -319,7 +320,7 @@ export class MainView extends React.Component {
                         <DocumentView Document={mainCont}
                             DataDoc={undefined}
                             addDocument={undefined}
-                            addDocTab={emptyFunction}
+                            addDocTab={this.addDocTabFunc}
                             pinToPres={emptyFunction}
                             onClick={undefined}
                             ruleProvider={undefined}
@@ -368,11 +369,14 @@ export class MainView extends React.Component {
         document.removeEventListener("pointerup", this.onPointerUp);
     }
     flyoutWidthFunc = () => this.flyoutWidth;
-    addDocTabFunc = (doc: Doc) => {
+    addDocTabFunc = (doc: Doc, data: Opt<Doc>, where: string) => {
+        if (where === "close")
+            return CollectionDockingView.CloseRightSplit(doc);
         if (doc.dockingConfig) {
             this.openWorkspace(doc);
+            return true;
         } else {
-            CollectionDockingView.Instance.AddRightSplit(doc, undefined);
+            return CollectionDockingView.AddRightSplit(doc, undefined);
         }
     }
     @computed
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 8124ce653..45e0a3562 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -186,7 +186,7 @@ export class OverlayView extends React.Component {
                     whenActiveChanged={emptyFunction}
                     focus={emptyFunction}
                     backgroundColor={returnEmptyString}
-                    addDocTab={emptyFunction}
+                    addDocTab={returnFalse}
                     pinToPres={emptyFunction}
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index fdb2f0dc9..0399371ff 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -103,7 +103,6 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         if (this.props.fieldExt) { // bcz: fieldExt !== undefined means this is an overlay layer
             Doc.GetProto(doc).annotationOn = this.props.Document;
         }
-        allowDuplicates = true;
         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));
@@ -126,7 +125,8 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         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 && Doc.AreProtosEqual(v, doc)) ? i : p, -1);
+        let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1);
+        index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1);
         PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn =>
             annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined));
 
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index cab085d9b..277fa0066 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,36 +1,35 @@
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faFile } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, Lambda, observable, reaction, trace, computed } from "mobx";
+import { action, computed, Lambda, observable, reaction } from "mobx";
 import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
 import * as GoldenLayout from "../../../client/goldenLayout";
+import { DateField } from '../../../new_fields/DateField';
 import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc";
 import { Id } from '../../../new_fields/FieldSymbols';
+import { List } from '../../../new_fields/List';
 import { FieldId } from "../../../new_fields/RefField";
 import { listSpec } from "../../../new_fields/Schema";
-import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
-import { emptyFunction, returnTrue, Utils, returnOne, returnEmptyString } from "../../../Utils";
+import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
+import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
+import { Docs } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragLinksAsDocuments, DragManager } from "../../util/DragManager";
 import { SelectionManager } from '../../util/SelectionManager';
 import { Transform } from '../../util/Transform';
-import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { undoBatch } from "../../util/UndoManager";
+import { MainView } from '../MainView';
 import { DocumentView } from "../nodes/DocumentView";
 import "./CollectionDockingView.scss";
 import { SubCollectionViewProps } from "./CollectionSubView";
 import { ParentDocSelector } from './ParentDocumentSelector';
 import React = require("react");
-import { MainView } from '../MainView';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faFile, faUnlockAlt } from '@fortawesome/free-solid-svg-icons';
-import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
-import { Docs } from '../../documents/Documents';
-import { DateField } from '../../../new_fields/DateField';
-import { List } from '../../../new_fields/List';
-import { DocumentType } from '../../documents/DocumentTypes';
 library.add(faFile);
 
 @observer
@@ -59,7 +58,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
 
     constructor(props: SubCollectionViewProps) {
         super(props);
-        if (props.addDocTab === emptyFunction) CollectionDockingView.Instance = this;
+        !CollectionDockingView.Instance && (CollectionDockingView.Instance = this);
         //Why is this here?
         (window as any).React = React;
         (window as any).ReactDOM = ReactDOM;
@@ -121,21 +120,25 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
 
     @undoBatch
     @action
-    public CloseRightSplit = (document: Doc): boolean => {
+    public static CloseRightSplit(document: Doc): boolean {
+        if (!CollectionDockingView.Instance) return false;
+        let instance = CollectionDockingView.Instance;
         let retVal = false;
-        if (this._goldenLayout.root.contentItems[0].isRow) {
-            retVal = Array.from(this._goldenLayout.root.contentItems[0].contentItems).some((child: any) => {
+        if (instance._goldenLayout.root.contentItems[0].isRow) {
+            retVal = Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => {
                 if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" &&
+                    DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId) &&
                     Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)!.Document, document)) {
                     child.contentItems[0].remove();
-                    this.layoutChanged(document);
+                    instance.layoutChanged(document);
                     return true;
                 } else {
                     Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => {
-                        if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) {
+                        if (DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId) &&
+                            Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) {
                             child.contentItems[j].remove();
                             child.config.activeItemIndex = Math.max(child.contentItems.length - 1, 0);
-                            let docs = Cast(this.props.Document.data, listSpec(Doc));
+                            let docs = Cast(instance.props.Document.data, listSpec(Doc));
                             docs && docs.indexOf(document) !== -1 && docs.splice(docs.indexOf(document), 1);
                             return true;
                         }
@@ -146,7 +149,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             });
         }
         if (retVal) {
-            this.stateChanged();
+            instance.stateChanged();
         }
         return retVal;
     }
@@ -173,8 +176,10 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     //
     @undoBatch
     @action
-    public AddRightSplit = (document: Doc, dataDoc: Doc | undefined, minimize: boolean = false) => {
-        let docs = Cast(this.props.Document.data, listSpec(Doc));
+    public static AddRightSplit(document: Doc, dataDoc: Doc | undefined, minimize: boolean = false) {
+        if (!CollectionDockingView.Instance) return false;
+        let instance = CollectionDockingView.Instance;
+        let docs = Cast(instance.props.Document.data, listSpec(Doc));
         if (docs) {
             docs.push(document);
         }
@@ -183,15 +188,15 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             content: [CollectionDockingView.makeDocumentConfig(document, dataDoc)]
         };
 
-        var newContentItem = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
+        var newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
 
-        if (this._goldenLayout.root.contentItems.length === 0) {
-            this._goldenLayout.root.addChild(newContentItem);
-        } else if (this._goldenLayout.root.contentItems[0].isRow) {
-            this._goldenLayout.root.contentItems[0].addChild(newContentItem);
+        if (instance._goldenLayout.root.contentItems.length === 0) {
+            instance._goldenLayout.root.addChild(newContentItem);
+        } else if (instance._goldenLayout.root.contentItems[0].isRow) {
+            instance._goldenLayout.root.contentItems[0].addChild(newContentItem);
         } else {
-            var collayout = this._goldenLayout.root.contentItems[0];
-            var newRow = collayout.layoutManager.createContentItem({ type: "row" }, this._goldenLayout);
+            var collayout = instance._goldenLayout.root.contentItems[0];
+            var newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
             collayout.parent.replaceChild(collayout, newRow);
 
             newRow.addChild(newContentItem, undefined, true);
@@ -206,9 +211,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             // newContentItem.config.height = 10;
         }
         newContentItem.callDownwards('_$init');
-        this.layoutChanged();
-
-        return newContentItem;
+        instance.layoutChanged();
+        return true;
     }
 
     @undoBatch
@@ -238,6 +242,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             stack.addChild(docContentConfig, undefined);
         }
         this.layoutChanged();
+        return true;
     }
 
     setupGoldenLayout() {
@@ -416,7 +421,10 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                             hideSource: false
                         });
                     }}><FontAwesomeIcon icon="file" size="lg" /></span>, dragSpan);
-                ReactDOM.render(<ParentDocSelector Document={doc} addDocTab={doc => CollectionDockingView.Instance.AddTab(stack, doc, dataDoc)} />, upDiv);
+                ReactDOM.render(<ParentDocSelector Document={doc} addDocTab={(doc, data, where) => {
+                    where === "onRight" ? CollectionDockingView.AddRightSplit(doc, dataDoc) : CollectionDockingView.Instance.AddTab(stack, doc, dataDoc);
+                    return true;
+                }} />, upDiv);
                 tab.reactComponents = [dragSpan, upDiv];
                 tab.element.append(dragSpan);
                 tab.element.append(upDiv);
@@ -604,15 +612,16 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     }
     get previewPanelCenteringOffset() { return this.nativeWidth() && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth()) / 2 : 0; }
 
-    addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => {
+    addDocTab = (doc: Doc, dataDoc: Opt<Doc>, location: string) => {
         if (doc.dockingConfig) {
             MainView.Instance.openWorkspace(doc);
+            return true;
         } else if (location === "onRight") {
-            CollectionDockingView.Instance.AddRightSplit(doc, dataDoc);
+            return CollectionDockingView.AddRightSplit(doc, dataDoc);
         } else if (location === "close") {
-            CollectionDockingView.Instance.CloseRightSplit(doc);
+            return CollectionDockingView.CloseRightSplit(doc);
         } else {
-            CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc);
+            return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc);
         }
     }
     @computed get docView() {
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 059967a7d..0306d415c 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -39,7 +39,7 @@ export interface CellProps {
     Document: Doc;
     fieldKey: string;
     renderDepth: number;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
     isFocused: boolean;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a742054d0..7bd2a1971 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -256,7 +256,7 @@ export interface SchemaTableProps {
     ScreenToLocalTransform: () => Transform;
     active: () => boolean;
     onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined) => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     isSelected: () => boolean;
     isFocused: (document: Doc) => boolean;
@@ -915,7 +915,7 @@ interface CollectionSchemaPreviewProps {
     removeDocument: (document: Doc) => boolean;
     active: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     setPreviewScript: (script: string) => void;
     previewScript?: string;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b4026a810..08d87c7b2 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -40,7 +40,7 @@ export interface TreeViewProps {
     ruleProvider: Doc | undefined;
     moveDocument: DragManager.MoveFunction;
     dropAction: "alias" | "copy" | undefined;
-    addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     panelWidth: () => number;
     panelHeight: () => number;
@@ -414,7 +414,7 @@ class TreeView extends React.Component<TreeViewProps> {
         remove: ((doc: Doc) => boolean),
         move: DragManager.MoveFunction,
         dropAction: dropActionType,
-        addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void,
+        addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean,
         pinToPres: (document: Doc) => void,
         screenToLocalXf: () => Transform,
         outerXf: () => { translateX: number, translateY: number },
@@ -562,8 +562,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
     outerXf = () => Utils.GetScreenTransform(this._mainEle!);
     onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {});
     openNotifsCol = () => {
-        if (CollectionTreeView.NotifsCol && CollectionDockingView.Instance) {
-            CollectionDockingView.Instance.AddRightSplit(CollectionTreeView.NotifsCol, undefined);
+        if (CollectionTreeView.NotifsCol) {
+            this.props.addDocTab(CollectionTreeView.NotifsCol, undefined, "onRight");
         }
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ad77e0428..7383c5551 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -508,14 +508,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     });
                 }
 
-                let panelDim = this.props.ScreenToLocalTransform().transformDirection(this._pwidth / this.zoomScaling(),
-                    this._pheight / this.zoomScaling());
-                let panelwidth = panelDim[0];
-                let panelheight = panelDim[1];
-                if (ranges[0][0] - dx > (this.panX() + panelwidth / 2)) x = ranges[0][1] + panelwidth / 2;
-                if (ranges[0][1] - dx < (this.panX() - panelwidth / 2)) x = ranges[0][0] - panelwidth / 2;
-                if (ranges[1][0] - dy > (this.panY() + panelheight / 2)) y = ranges[1][1] + panelheight / 2;
-                if (ranges[1][1] - dy < (this.panY() - panelheight / 2)) y = ranges[1][0] - panelheight / 2;
+                let cscale = this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.scale) : 1;
+                let panelDim = this.props.ScreenToLocalTransform().transformDirection(this._pwidth / this.zoomScaling() * cscale,
+                    this._pheight / this.zoomScaling() * cscale);
+                if (ranges[0][0] - dx > (this.panX() + panelDim[0] / 2)) x = ranges[0][1] + panelDim[0] / 2;
+                if (ranges[0][1] - dx < (this.panX() - panelDim[0] / 2)) x = ranges[0][0] - panelDim[0] / 2;
+                if (ranges[1][0] - dy > (this.panY() + panelDim[1] / 2)) y = ranges[1][1] + panelDim[1] / 2;
+                if (ranges[1][1] - dy < (this.panY() - panelDim[1] / 2)) y = ranges[1][0] - panelDim[1] / 2;
             }
             this.setPan(x - dx, y - dy);
             this._lastX = e.pageX;
@@ -613,8 +612,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         if (willZoom) {
             this.setScaleToZoom(doc, scale);
         }
+        console.log("Focused " + this.Document.title + " " + s);
         afterFocus && setTimeout(() => {
             if (afterFocus && afterFocus()) {
+                console.log("UnFocused " + this.Document.title + " " + s);
                 this.Document.panX = px;
                 this.Document.panY = py;
                 this.Document.scale = s;
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index d7cb2585e..81b0249dd 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -2,7 +2,7 @@ import { observable, computed, action, runInAction, reaction, IReactionDisposer
 import React = require("react");
 import { observer } from "mobx-react";
 import { FieldViewProps, FieldView } from "../nodes/FieldView";
-import { Doc, DocListCastAsync } from "../../../new_fields/Doc";
+import { Doc, DocListCastAsync, Opt } from "../../../new_fields/Doc";
 import { undoBatch } from "../../util/UndoManager";
 import { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types";
 import { CollectionViewType } from "../collections/CollectionBaseView";
@@ -195,9 +195,9 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     }
 
-    _addDocTab: (undefined | ((doc: Doc, dataDoc: Doc | undefined, where: string) => void));
+    _addDocTab: (undefined | ((doc: Doc, dataDoc: Opt<Doc>, where: string) => boolean));
 
-    setAddDocTab = (addFunc: (doc: Doc, dataDoc: Doc | undefined, where: string) => void) => {
+    setAddDocTab = (addFunc: (doc: Doc, dataDoc: Opt<Doc>, where: string) => boolean) => {
         this._addDocTab = addFunc;
     }
 
@@ -211,7 +211,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
                 options.context.panX = newPanX;
                 options.context.panY = newPanY;
             }
-            CollectionDockingView.Instance.AddRightSplit(options.context, undefined);
+            (this._addDocTab || this.props.addDocTab)(options.context, undefined, "onRight");
 
             if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom });
 
@@ -224,7 +224,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     openLinkRight = () => {
         if (LinkFollowBox.destinationDoc) {
             let alias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
-            CollectionDockingView.Instance.AddRightSplit(alias, undefined);
+            (this._addDocTab || this.props.addDocTab)(alias, undefined, "onRight");
             this.highlightDoc();
             SelectionManager.DeselectAll();
         }
@@ -244,7 +244,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             let sourceContext = await Cast(proto.sourceContext, Doc);
             const shouldZoom = options ? options.shouldZoom : false;
 
-            let dockingFunc = (document: Doc) => { this._addDocTab && this._addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
+            let dockingFunc = (document: Doc) => { (this._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
 
             if (LinkFollowBox.destinationDoc === LinkFollowBox.linkDoc.anchor2 && targetContext) {
                 DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext);
@@ -271,7 +271,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         if (LinkFollowBox.destinationDoc) {
             let fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
             // this.prosp.addDocTab is empty -- use the link source's addDocTab 
-            this._addDocTab && this._addDocTab(fullScreenAlias, undefined, "inTab");
+            (this._addDocTab || this.props.addDocTab)(fullScreenAlias, undefined, "inTab");
 
             this.highlightDoc();
             SelectionManager.DeselectAll();
@@ -288,7 +288,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
                 options.context.panX = newPanX;
                 options.context.panY = newPanY;
             }
-            this._addDocTab && this._addDocTab(options.context, undefined, "inTab");
+            (this._addDocTab || this.props.addDocTab)(options.context, undefined, "inTab");
             if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom });
 
             this.highlightDoc();
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 842ce45b1..27af873b5 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -16,7 +16,7 @@ library.add(faTrash);
 interface Props {
     docView: DocumentView;
     changeFlyout: () => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
 }
 
 @observer
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index d711ac284..1891919ce 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -1,27 +1,25 @@
-import { action, observable } from "mobx";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action } from "mobx";
 import { observer } from "mobx-react";
-import { DocumentView } from "../nodes/DocumentView";
-import { LinkMenuItem } from "./LinkMenuItem";
-import { LinkEditor } from "./LinkEditor";
-import './LinkMenu.scss';
-import React = require("react");
-import { Doc, DocListCast } from "../../../new_fields/Doc";
+import { Doc } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
-import { LinkManager } from "../../util/LinkManager";
-import { DragLinksAsDocuments, DragManager, SetupDrag } from "../../util/DragManager";
+import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 import { emptyFunction } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { DragManager, SetupDrag } from "../../util/DragManager";
+import { LinkManager } from "../../util/LinkManager";
 import { UndoManager } from "../../util/UndoManager";
-import { StrCast } from "../../../new_fields/Types";
-import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
+import { DocumentView } from "../nodes/DocumentView";
+import './LinkMenu.scss';
+import { LinkMenuItem } from "./LinkMenuItem";
+import React = require("react");
 
 interface LinkMenuGroupProps {
     sourceDoc: Doc;
     group: Doc[];
     groupType: string;
     showEditor: (linkDoc: Doc) => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     docView: DocumentView;
 
 }
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 19a0023e9..82fe3df23 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -21,7 +21,7 @@ interface LinkMenuItemProps {
     sourceDoc: Doc;
     destinationDoc: Doc;
     showEditor: (linkDoc: Doc) => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
 }
 
 @observer
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4a37457c0..50691fd38 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -86,7 +86,7 @@ export interface DocumentViewProps {
     parentActive: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
     bringToFront: (doc: Doc, sendToBack?: boolean) => void;
-    addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void;
     zoomToScale: (scale: number) => void;
@@ -242,23 +242,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (expandedDocs.length) {
             SelectionManager.DeselectAll();
             let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace");
-            if (altKey || ctrlKey) {
-                maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" ? "inTab" : "inPlace"));
-                if (maxLocation === "inPlace") {
-                    let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
-                    let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false);
-                    expandedDocs.forEach(maxDoc => maxDoc.isMinimized = false);
-                    let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
-                    !hasView && expandedDocs.forEach(async maxDoc => this.props.addDocument && this.props.addDocument(maxDoc, false));
-                    expandedDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized);
-                }
-            }
-            if (maxLocation !== "inPlace" && CollectionDockingView.Instance) {
-                expandedDocs.forEach(maxDoc =>
-                    (!CollectionDockingView.Instance.CloseRightSplit(maxDoc) && this.props.addDocTab(maxDoc, undefined, maxLocation)));
-            } else {
+            maxLocation = this.Document.maximizeLocation = (!ctrlKey ? !altKey ? maxLocation : (maxLocation !== "inPlace" ? "inPlace" : "onRight") : (maxLocation !== "inPlace" ? "inPlace" : "inTab"));
+            if (maxLocation === "inPlace") {
+                expandedDocs.forEach(maxDoc => this.props.addDocument && this.props.addDocument(maxDoc, false));
                 let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2);
                 this.collapseTargetsToPoint(scrpt, expandedDocs);
+            } else {
+                expandedDocs.forEach(maxDoc => (!this.props.addDocTab(maxDoc, undefined, "close") && this.props.addDocTab(maxDoc, undefined, maxLocation)));
             }
         }
         else if (linkedDocs.length) {
@@ -277,7 +267,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionDoc) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
                 DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false,
                     // open up target if it's not already in view ... by zooming into the button document first and setting flag to reset zoom afterwards
-                    doc => this.props.focus(this.props.Document, true, 1, () => { this.props.addDocTab(doc, undefined, maxLocation); return true; }),
+                    doc => this.props.focus(this.props.Document, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)),
                     linkedFwdPage[altKey ? 1 : 0], targetContext);
             }
         }
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index faf11e9be..49fc2263d 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -39,7 +39,7 @@ export interface FieldViewProps {
     select: (isCtrlPressed: boolean) => void;
     renderDepth: number;
     addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     removeDocument?: (document: Doc) => boolean;
     moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index ee70942de..8fcd44f46 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -124,7 +124,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         let i = 0;
         const self = this;
         for (let key of Object.keys(ids).slice().sort()) {
-            rows.push(<KeyValuePair doc={realDoc} ref={(function () {
+            rows.push(<KeyValuePair doc={realDoc} addDocTab={this.props.addDocTab} ref={(function () {
                 let oldEl: KeyValuePair | undefined;
                 return (el: KeyValuePair) => {
                     if (oldEl) self.rows.splice(self.rows.indexOf(oldEl), 1);
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index c7e0f51d7..1fed4c8bb 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -1,7 +1,7 @@
 import { action, observable } from 'mobx';
 import { observer } from "mobx-react";
 import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
-import { Doc, Field } from '../../../new_fields/Doc';
+import { Doc, Field, Opt } from '../../../new_fields/Doc';
 import { emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
 import { Transform } from '../../util/Transform';
@@ -22,6 +22,7 @@ export interface KeyValuePairProps {
     keyName: string;
     doc: Doc;
     keyWidth: number;
+    addDocTab: (doc: Doc, data: Opt<Doc>, where: string) => boolean;
 }
 @observer
 export class KeyValuePair extends React.Component<KeyValuePairProps> {
@@ -45,7 +46,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
         if (value instanceof Doc) {
             e.stopPropagation();
             e.preventDefault();
-            ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.Create.KVPDocument(value, { width: 300, height: 300 }); CollectionDockingView.Instance.AddRightSplit(kvp, undefined); }, icon: "layer-group" });
+            ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" });
             ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
         }
     }
@@ -68,7 +69,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             focus: emptyFunction,
             PanelWidth: returnZero,
             PanelHeight: returnZero,
-            addDocTab: returnZero,
+            addDocTab: returnFalse,
             pinToPres: returnZero,
             ContentScaling: returnOne
         };
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 34e3b0931..a9fa883c8 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -1,20 +1,18 @@
 import React = require("react");
 import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc";
+import { Doc, DocListCast, HeightSym, WidthSym, Opt } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { DocumentManager } from "../../util/DocumentManager";
 import PDFMenu from "./PDFMenu";
 import "./Annotation.scss";
-import { scale } from "./PDFViewer";
-import { PresBox } from "../nodes/PresBox";
 
 interface IAnnotationProps {
     anno: Doc;
     fieldExtensionDoc: Doc;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Opt<Doc>, where: string) => boolean;
     pinToPres: (document: Doc) => void;
 }
 
@@ -31,7 +29,7 @@ interface IRegionAnnotationProps {
     width: number;
     height: number;
     fieldExtensionDoc: Doc;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     document: Doc;
 }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index c508935f2..19ef713c2 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -35,7 +35,7 @@ interface IViewerProps {
     scrollTo: (y: number) => void;
     active: () => boolean;
     setPanY?: (n: number) => void;
-    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean;
 }
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index b2e886d95..96eefacc2 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -76,7 +76,7 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> {
                 col.panX = newPanX;
                 col.panY = newPanY;
             }
-            CollectionDockingView.Instance.AddRightSplit(col, undefined);
+            CollectionDockingView.AddRightSplit(col, undefined);
         };
     }
     render() {
@@ -110,7 +110,7 @@ export class LinkContextMenu extends React.Component<LinkMenuProps> {
 
     unHighlightDoc = (doc: Doc) => () => Doc.UnBrushDoc(doc);
 
-    getOnClick = (col: Doc) => () => CollectionDockingView.Instance.AddRightSplit(col, undefined);
+    getOnClick = (col: Doc) => () => CollectionDockingView.AddRightSplit(col, undefined);
 
     render() {
         return (
-- 
cgit v1.2.3-70-g09d2


From f4b628c2a6810c1af51508685f12287a300d6e6f Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 25 Sep 2019 22:26:54 -0400
Subject: all pdf annotations work?

---
 src/client/documents/Documents.ts                  |   7 +-
 src/client/views/DocumentButtonBar.tsx             |   5 +-
 src/client/views/MainView.tsx                      |   7 +-
 src/client/views/TemplateMenu.tsx                  |   4 +-
 .../views/collections/CollectionDockingView.tsx    |   6 +-
 .../views/collections/CollectionSchemaCells.tsx    |   6 +-
 .../views/collections/CollectionSchemaView.tsx     |   4 +-
 .../views/collections/CollectionStackingView.tsx   |   8 +-
 .../CollectionStackingViewFieldColumn.tsx          |   6 +-
 src/client/views/collections/CollectionSubView.tsx |   5 +-
 .../CollectionFreeFormLayoutEngines.tsx            |   4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  18 +--
 .../collections/collectionFreeForm/MarqueeView.tsx |  13 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   6 +-
 src/client/views/nodes/DocumentView.tsx            |   3 +-
 src/client/views/nodes/FormattedTextBox.tsx        |   6 +-
 src/client/views/nodes/PDFBox.scss                 |   3 +
 src/client/views/nodes/PDFBox.tsx                  |  20 ++--
 src/client/views/pdf/PDFViewer.scss                |   5 +-
 src/client/views/pdf/PDFViewer.tsx                 | 132 +++++++++++++--------
 20 files changed, 159 insertions(+), 109 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ea7a3a8b6..392dca373 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -95,12 +95,13 @@ export namespace Docs {
 
     export namespace Prototypes {
 
-        type LayoutSource = { LayoutString: () => string };
+        type LayoutSource = { LayoutString: (ext?: string) => string };
         type CollectionLayoutSource = { LayoutString: (fieldStr: string, fieldExt?: string) => string };
         type CollectionViewType = [CollectionLayoutSource, string, string?];
         type PrototypeTemplate = {
             layout: {
                 view: LayoutSource,
+                ext?: string, // optional extension field for layout source
                 collectionView?: CollectionViewType
             },
             options?: Partial<DocumentOptions>
@@ -144,7 +145,7 @@ export namespace Docs {
                 options: { height: 32 }
             }],
             [DocumentType.PDF, {
-                layout: { view: PDFBox },
+                layout: { view: PDFBox, ext: anno },
                 options: { nativeWidth: 1200, curPage: 1 }
             }],
             [DocumentType.ICON, {
@@ -254,7 +255,7 @@ export namespace Docs {
             // synthesize the default options, the type and title from computed values and
             // whatever options pertain to this specific prototype
             let options = { title: title, type: type, baseProto: true, ...defaultOptions, ...(template.options || {}) };
-            let primary = layout.view.LayoutString();
+            let primary = layout.view.LayoutString(layout.ext);
             let collectionView = layout.collectionView;
             if (collectionView) {
                 options.layout = collectionView[0].LayoutString(collectionView[1], collectionView[2]);
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index b482e3298..9ca54f738 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -23,6 +23,7 @@ import React = require("react");
 import { DocumentView } from './nodes/DocumentView';
 import { ParentDocSelector } from './collections/ParentDocumentSelector';
 import { CollectionDockingView } from './collections/CollectionDockingView';
+import { DocumentDecorations } from './DocumentDecorations';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -225,7 +226,7 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[],
         return (
             <div className={"linkButtonWrapper"}>
                 <div title={`${published ? "Push" : "Publish"} to Google Docs`} className="linkButton-linker" onClick={() => {
-                    DocumentDecorations.hasPushedHack = false;
+                    DocumentButtonBar.hasPushedHack = false;
                     this.targetDoc[Pushes] = NumCast(this.targetDoc[Pushes]) + 1;
                 }}>
                     <FontAwesomeIcon className="documentdecorations-icon" icon={icon} size={published ? "sm" : "xs"} />
@@ -259,7 +260,7 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[],
                             window.open(`https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`);
                         } else {
                             this.clearPullColor();
-                            DocumentDecorations.hasPulledHack = false;
+                            DocumentButtonBar.hasPulledHack = false;
                             this.targetDoc[Pulls] = NumCast(this.targetDoc[Pulls]) + 1;
                             dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
                         }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 003919866..244b217ed 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -230,7 +230,7 @@ export class MainView extends React.Component {
         } else {
             DocServer.GetRefField(CurrentUserUtils.MainDocId).then(field => {
                 field instanceof Doc ? this.openWorkspace(field) :
-                    this.createNewWorkspace(CurrentUserUtils.MainDocId)
+                    this.createNewWorkspace(CurrentUserUtils.MainDocId);
             });
         }
     }
@@ -371,8 +371,9 @@ export class MainView extends React.Component {
     }
     flyoutWidthFunc = () => this.flyoutWidth;
     addDocTabFunc = (doc: Doc, data: Opt<Doc>, where: string) => {
-        if (where === "close")
+        if (where === "close") {
             return CollectionDockingView.CloseRightSplit(doc);
+        }
         if (doc.dockingConfig) {
             this.openWorkspace(doc);
             return true;
@@ -564,7 +565,7 @@ export class MainView extends React.Component {
         let next = () => PresBox.CurrentPresentation.next();
         let back = () => PresBox.CurrentPresentation.back();
         let startOrResetPres = () => PresBox.CurrentPresentation.startOrResetPres();
-        let closePresMode = action(() => { PresBox.CurrentPresentation.presMode = false; this.addDocTabFunc(PresBox.CurrentPresentation.props.Document); });
+        let closePresMode = action(() => { PresBox.CurrentPresentation.presMode = false; this.addDocTabFunc(PresBox.CurrentPresentation.props.Document, undefined, "onRight"); });
         return !PresBox.CurrentPresentation || !PresBox.CurrentPresentation.presMode ? (null) : <PresModeMenu next={next} back={back} presStatus={PresBox.CurrentPresentation.presStatus} startOrResetPres={startOrResetPres} closePresMode={closePresMode} > </PresModeMenu>;
     }
 
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index e4ef8313d..9e5e62e03 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -117,13 +117,13 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
     @action
     toggleChrome = (): void => {
         this.props.docs.map(dv => {
-            let layout = dv.Document.layout instanceof Doc ? dv.Document.layout as Doc : dv.Document;
+            let layout = dv.Document.layout instanceof Doc ? dv.Document.layout : dv.Document;
             layout.chromeStatus = (layout.chromeStatus !== "disabled" ? "disabled" : "enabled");
         });
     }
 
     render() {
-        let layout = this.props.docs[0].Document.layout instanceof Doc ? this.props.docs[0].Document.layout as Doc : this.props.docs[0].Document;
+        let layout = this.props.docs[0].Document.layout instanceof Doc ? this.props.docs[0].Document.layout : this.props.docs[0].Document;
         let templateMenu: Array<JSX.Element> = [];
         this.props.templates.forEach((checked, template) =>
             templateMenu.push(<TemplateToggle key={template.Name} template={template} checked={checked} toggle={this.toggleTemplate} />));
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e5d652648..2d9faee6b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -603,9 +603,11 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
 
     contentScaling = () => {
         if (this._document!.type === DocumentType.PDF) {
-            if (this._panelHeight / NumCast(this._document!.nativeHeight) > this._panelWidth / NumCast(this._document!.nativeWidth))
+            if (this._panelHeight / NumCast(this._document!.nativeHeight) > this._panelWidth / NumCast(this._document!.nativeWidth)) {
                 return this._panelWidth / NumCast(this._document!.nativeWidth);
-            else return this._panelHeight / NumCast(this._document!.nativeHeight);
+            } else {
+                return this._panelHeight / NumCast(this._document!.nativeHeight);
+            }
         }
         const nativeH = this.nativeHeight();
         const nativeW = this.nativeWidth();
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 4dac27e60..179e44266 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -34,7 +34,7 @@ export interface CellProps {
     row: number;
     col: number;
     rowProps: CellInfo;
-    CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
+    CollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     ContainingCollection: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Doc;
     fieldKey: string;
@@ -151,7 +151,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             fieldExt: "",
             ruleProvider: undefined,
             ContainingCollectionView: this.props.CollectionView,
-            ContainingCollectionDoc: this.props.CollectionView.props.Document,
+            ContainingCollectionDoc: this.props.CollectionView && this.props.CollectionView.props.Document,
             isSelected: returnFalse,
             select: emptyFunction,
             renderDepth: this.props.renderDepth + 1,
@@ -301,7 +301,7 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
     render() {
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = (e: React.PointerEvent) => {
-            (!this.props.CollectionView.props.isSelected() ? undefined :
+            (!this.props.CollectionView || !this.props.CollectionView.props.isSelected() ? undefined :
                 SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
         };
         return (
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7bd2a1971..8d931f812 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -246,7 +246,7 @@ export interface SchemaTableProps {
     PanelHeight: () => number;
     PanelWidth: () => number;
     childDocs?: Doc[];
-    CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
+    CollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     ContainingCollectionDoc: Opt<Doc>;
     fieldKey: string;
@@ -804,7 +804,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         csv.substring(0, csv.length - 1);
         let dbName = StrCast(this.props.Document.title);
         let res = await Gateway.Instance.PostSchema(csv, dbName);
-        if (self.props.CollectionView.props.addDocument) {
+        if (self.props.CollectionView && self.props.CollectionView.props.addDocument) {
             let schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document });
             if (schemaDoc) {
                 //self.props.CollectionView.props.addDocument(schemaDoc, false);
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index ccf131797..597f3f745 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -42,7 +42,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); }
     @computed get isStackingView() { return BoolCast(this.props.Document.singleColumn, true); }
     @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; }
-    @computed get showAddAGroup() { return (this.sectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')); }
+    @computed get showAddAGroup() { return (this.sectionFilter && this.props.ContainingCollectionDoc && (this.props.ContainingCollectionDoc.chromeStatus !== 'view-mode' && this.props.ContainingCollectionDoc.chromeStatus !== 'disabled')); }
     @computed get columnWidth() {
         return Math.min(this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin,
             this.isStackingView ? Number.MAX_VALUE : NumCast(this.props.Document.columnWidth, 250));
@@ -347,7 +347,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     onToggle = (checked: Boolean) => {
-        this.props.CollectionView.props.Document.chromeStatus = checked ? "collapsed" : "view-mode";
+        this.props.ContainingCollectionDoc && (this.props.ContainingCollectionDoc.chromeStatus = checked ? "collapsed" : "view-mode");
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
@@ -391,10 +391,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                         style={{ width: this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
                     </div>}
-                {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? <Switch
+                {this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.chromeStatus !== 'disabled' ? <Switch
                     onChange={this.onToggle}
                     onClick={this.onToggle}
-                    defaultChecked={this.props.CollectionView.props.Document.chromeStatus !== 'view-mode'}
+                    defaultChecked={this.props.ContainingCollectionDoc.chromeStatus !== 'view-mode'}
                     checkedChildren="edit"
                     unCheckedChildren="view"
                 /> : null}
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index b3b7b40dd..240adf428 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -266,7 +266,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 style={{
                     width: (style.columnWidth) /
                         ((uniqueHeadings.length +
-                            ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)
+                            ((this.props.parent.props.ContainingCollectionDoc && this.props.parent.props.ContainingCollectionDoc.chromeStatus !== 'view-mode' && this.props.parent.props.ContainingCollectionDoc.chromeStatus !== 'disabled') ? 1 : 0)) || 1)
                 }}>
                 {/* the default bucket (no key value) has a tooltip that describes what it is.
                     Further, it does not have a color and cannot be deleted. */}
@@ -297,7 +297,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             </div> : (null);
         for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `;
         return (
-            <div className="collectionStackingViewFieldColumn" key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
+            <div className="collectionStackingViewFieldColumn" key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((this.props.parent.props.ContainingCollectionDoc && this.props.parent.props.ContainingCollectionDoc.chromeStatus !== 'view-mode' && this.props.parent.props.ContainingCollectionDoc.chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
@@ -315,7 +315,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                     {this.children(this.props.docList)}
                     {singleColumn ? (null) : this.props.parent.columnDragger}
                 </div>
-                {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+                {(this.props.parent.props.ContainingCollectionDoc && this.props.parent.props.ContainingCollectionDoc.chromeStatus !== 'view-mode' && this.props.parent.props.ContainingCollectionDoc.chromeStatus !== 'disabled') ?
                     <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
                         style={{ width: style.columnWidth / style.numGroupColumns }}>
                         <EditableView {...newEditableViewProps} />
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 774e6b1b9..ce80526b2 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,7 +1,7 @@
 import { action, computed, IReactionDisposer, reaction } from "mobx";
 import * as rp from 'request-promise';
 import CursorField from "../../../new_fields/CursorField";
-import { Doc, DocListCast } from "../../../new_fields/Doc";
+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";
@@ -30,10 +30,11 @@ export interface CollectionViewProps extends FieldViewProps {
     PanelWidth: () => number;
     PanelHeight: () => number;
     chromeCollapsed: boolean;
+    setPreviewCursor?: (func: (x: number, y: number) => void) => void;
 }
 
 export interface SubCollectionViewProps extends CollectionViewProps {
-    CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
+    CollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     ruleProvider: Doc | undefined;
 }
 
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 21855b168..6135f3e45 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -90,9 +90,7 @@ export function computePivotLayout(pivotDoc: Doc, childDocs: Doc[], childPairs:
         layoutPoolData.set(pair, { transition: "transform 1s", ...pos });
     });
     return { map: layoutPoolData, elements: viewDefsToJSX(groupNames) };
-};
-
-
+}
 
 export function AddCustomFreeFormLayout(doc: Doc, dataKey: string): () => void {
     return () => {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 45c021c5f..075914e29 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -50,7 +50,7 @@ export const panZoomSchema = createSchema({
     useClusters: "boolean",
     isRuleProvider: "boolean",
     fitToBox: "boolean",
-    panTransformType: "string"
+    panTransformType: "string",
 });
 
 type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof documentSchema, typeof positionSchema, typeof pageSchema]>;
@@ -61,6 +61,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private _lastX: number = 0;
     private _lastY: number = 0;
     private _clusterDistance: number = 75;
+    private _hitCluster = false;
     @observable _clusterSets: (Doc[])[] = [];
 
     @computed get fitToContent() { return (this.props.fitToBox || this.Document.fitToBox) && !this.isAnnotationOverlay; }
@@ -265,7 +266,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         return clusterColor;
     }
 
-    _hitCluster = false;
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         this._hitCluster = this.props.Document.useClusters ? this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY)) !== -1 : false;
@@ -286,7 +286,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     @action
     onPointerMove = (e: PointerEvent): void => {
-        if (!e.cancelBubble && this.props.layoutKey) {
+        if (!e.cancelBubble && !this.isAnnotationOverlay) {
             if (this._hitCluster && this.tryDragCluster(e)) {
                 e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
                 e.preventDefault();
@@ -451,7 +451,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             PanelHeight: childLayout[HeightSym],
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
-            ContainingCollectionDoc: this.props.CollectionView.props.Document,
+            ContainingCollectionDoc: this.props.ContainingCollectionDoc,
             focus: this.focusDocument,
             backgroundColor: this.getClusterColor,
             parentActive: this.props.active,
@@ -478,7 +478,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             PanelHeight: layoutDoc[HeightSym],
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
-            ContainingCollectionDoc: this.props.CollectionView.props.Document,
+            ContainingCollectionDoc: this.props.ContainingCollectionDoc,
             focus: this.focusDocument,
             backgroundColor: returnEmptyString,
             parentActive: this.props.active,
@@ -699,10 +699,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         // otherwise, they are stored in fieldKey.  All annotations to this document are stored in the extension document
         Doc.UpdateDocumentExtensionForField(this.props.DataDoc || this.props.Document, this.props.fieldKey);
         return (
-            <div className={"collectionfreeformview-container"} style={{ height: this.props.layoutKey ? "100%" : this.props.PanelHeight() }} ref={this.createDropTarget} onWheel={this.onPointerWheel}
+            <div className={"collectionfreeformview-container"} style={{ pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined, height: this.isAnnotationOverlay ? "100%" : this.props.PanelHeight() }} ref={this.createDropTarget} onWheel={this.onPointerWheel}
                 onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} 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}
+                    addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox} setPreviewCursor={this.props.setPreviewCursor}
                     getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} isAnnotationOverlay={this.isAnnotationOverlay}>
                     <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
                         easing={this.easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
@@ -725,7 +725,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 class CollectionFreeFormOverlayView extends React.Component<DocumentViewProps & { isSelected: () => boolean }> {
     render() {
         return <DocumentContentsView {...this.props} layoutKey={"overlayLayout"}
-            renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />
+            renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />;
     }
 }
 
@@ -734,7 +734,7 @@ class CollectionFreeFormBackgroundView extends React.Component<DocumentViewProps
     render() {
         return !this.props.Document.backgroundLayout ? (null) :
             (<DocumentContentsView {...this.props} layoutKey={"backgroundLayout"}
-                renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />)
+                renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />);
     }
 }
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index c85c3e55b..689a55ec4 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -31,6 +31,7 @@ interface MarqueeViewProps {
     addLiveTextDocument: (doc: Doc) => void;
     isSelected: () => boolean;
     isAnnotationOverlay: boolean;
+    setPreviewCursor?: (func: (x: number, y: number) => void) => void;
 }
 
 @observer
@@ -44,6 +45,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     @observable _visible: boolean = false;
     _commandExecuted = false;
 
+    componentDidMount() {
+        this.props.setPreviewCursor && this.props.setPreviewCursor(this.setPreviewCursor);
+    }
+
     @action
     cleanupInteractions = (all: boolean = false) => {
         if (all) {
@@ -203,11 +208,17 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         }
     }
 
+    setPreviewCursor = (x: number, y: number) => {
+        this._downX = x;
+        this._downY = y;
+        PreviewCursor.Show(x, y, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument);
+    }
+
     @action
     onClick = (e: React.MouseEvent): void => {
         if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
             Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
-            PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument);
+            this.setPreviewCursor(e.clientX, e.clientY);
             // let the DocumentView stopPropagation of this event when it selects this document
         } else {  // why do we get a click event when the cursor have moved a big distance?
             // let's cut it off here so no one else has to deal with it.
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index bcb26b4c4..cd183a984 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -12,7 +12,7 @@ import { Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
 import { random } from "animejs";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
-    dataProvider?: (doc: Doc, dataDoc?: Doc) => { x: number, y: number, width: number, height: number, z: number, transition?: string } | undefined
+    dataProvider?: (doc: Doc, dataDoc?: Doc) => { x: number, y: number, width: number, height: number, z: number, transition?: string } | undefined;
     x?: number;
     y?: number;
     width?: number;
@@ -99,8 +99,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
 
     @observable _animPos: number[] | undefined = undefined;
 
-    finalPanelWidh = () => { return this.dataProvider ? this.dataProvider.width : this.panelWidth(); }
-    finalPanelHeight = () => { return this.dataProvider ? this.dataProvider.height : this.panelHeight(); }
+    finalPanelWidh = () => this.dataProvider ? this.dataProvider.width : this.panelWidth();
+    finalPanelHeight = () => this.dataProvider ? this.dataProvider.height : this.panelHeight();
 
     render() {
         trace();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e89fddd25..759c064b4 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -264,7 +264,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (e.cancelBubble && this.active) {
             document.removeEventListener("pointermove", this.onPointerMove);
         }
-        else if (!e.cancelBubble && this.active) {
+        else if (!e.cancelBubble && (SelectionManager.IsSelected(this) ||
+            this.props.parentActive())) {
             if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
                 if (!e.altKey && !this.topMost && e.buttons === 1 && !BoolCast(this.Document.lockedPosition)) {
                     document.removeEventListener("pointermove", this.onPointerMove);
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 47b64e260..923dd1544 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -153,7 +153,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                         }
                     });
                     return { frag: Fragment.fromArray(nodes), start: start };
-                }
+                };
                 let findLinkNode = (node: Node, editor: EditorView) => {
                     if (!node.isText) {
                         const content = findLinkFrag(node.content, editor);
@@ -162,7 +162,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                     const marks = [...node.marks];
                     const linkIndex = marks.findIndex(mark => mark.type === editor.state.schema.marks.link);
                     return linkIndex !== -1 && scrollToLinkID === marks[linkIndex].attrs.href.replace(/.*\/doc\//, "") ? node : undefined;
-                }
+                };
 
                 let start = -1;
 
@@ -748,7 +748,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                     let ref = editorView.domAtPos(editorView.state.selection.from);
                     let refNode = ref.node as any;
                     while (refNode && !("getBoundingClientRect" in refNode)) refNode = refNode.parentElement;
-                    let r1 = refNode && (refNode as any).getBoundingClientRect();
+                    let r1 = refNode && refNode.getBoundingClientRect();
                     let r3 = self._ref.current!.getBoundingClientRect();
                     r1 && (self._ref.current!.scrollTop += (r1.top - r3.top) * self.props.ScreenToLocalTransform().Scale);
                     return true;
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index b7ff84d4a..2147292d6 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -16,6 +16,9 @@
             user-select: none; 
         }
     }
+    .collectionFreeFormView-none {
+        pointer-events: none;
+    }
 }
 
 .pdfBox-cont-interactive {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index e00635408..69e438d4f 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,5 +1,5 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction, runInAction, untracked } from 'mobx';
 import { observer } from "mobx-react";
 import * as Pdfjs from "pdfjs-dist";
 import "pdfjs-dist/web/pdf_viewer.css";
@@ -25,7 +25,7 @@ const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
 
 @observer
 export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) {
-    public static LayoutString() { return FieldView.LayoutString(PDFBox); }
+    public static LayoutString(fieldExt?: string) { return FieldView.LayoutString(PDFBox, "data", fieldExt); }
     private _reactionDisposer?: IReactionDisposer;
     private _keyValue: string = "";
     private _valueValue: string = "";
@@ -73,24 +73,24 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     }
 
     public GetPage() {
-        return this._pdfViewer!._pdfViewer.currentPageNumber;
+        return this._pdfViewer!.pdfViewer.currentPageNumber;
     }
 
     @action
     public BackPage() {
-        this._pdfViewer!._pdfViewer.scrollPageIntoView({ pageNumber: Math.max(1, this.GetPage() - 1) });
+        this._pdfViewer!.pdfViewer.scrollPageIntoView({ pageNumber: Math.max(1, this.GetPage() - 1) });
         this.props.Document.curPage = this.GetPage();
     }
 
     @action
     public GotoPage = (p: number) => {
-        this._pdfViewer!._pdfViewer.scrollPageIntoView(p);
+        this._pdfViewer!.pdfViewer.scrollPageIntoView(p);
         this.props.Document.curPage = this.GetPage();
     }
 
     @action
     public ForwardPage() {
-        this._pdfViewer!._pdfViewer.scrollPageIntoView({ pageNumber: Math.min(this._pdfViewer!._pdfViewer.pagesCount, this.GetPage() + 1) });
+        this._pdfViewer!.pdfViewer.scrollPageIntoView({ pageNumber: Math.min(this._pdfViewer!.pdfViewer.pagesCount, this.GetPage() + 1) });
         this.props.Document.curPage = this.GetPage();
     }
 
@@ -153,7 +153,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
                     <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="sm" />
                 </button>
                 <button className="pdfBox-overlayButton-iconCont" key="back" title="Page Back"
-                    onPointerDown={(e) => { e.stopPropagation() }}
+                    onPointerDown={(e) => e.stopPropagation()}
                     onClick={() => this.BackPage()}
                     style={{ left: 20, top: 5, height: "30px", position: "absolute", pointerEvents: "all", display: this.props.active() ? "flex" : "none" }}>
                     <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-left"} size="sm" />
@@ -211,7 +211,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
 
     render() {
         const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
-        let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : "");
+        let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.props.isSelected() ? "" : "-interactive");
         return (!(pdfUrl instanceof PdfField) || !this._pdf ?
             <div>{`pdf, ${this.dataDoc[this.props.fieldKey]}, not found`}</div> :
             <div className={classname} onWheel={(e: React.WheelEvent) => e.stopPropagation()} onPointerDown={(e: React.PointerEvent) => {
@@ -221,11 +221,13 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
                 }
             }}>
                 <PDFViewer {...this.props} pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded}
-                    setPdfViewer={this.setPdfViewer}
+                    setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView}
+                    renderDepth={this.props.renderDepth}
                     Document={this.props.Document} DataDoc={this.dataDoc}
                     addDocTab={this.props.addDocTab} GoToPage={this.GotoPage}
                     pinToPres={this.props.pinToPres} addDocument={this.props.addDocument}
                     ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                    isSelected={this.props.isSelected}
                     fieldKey={this.props.fieldKey} fieldExtensionDoc={this.extensionDoc} />
                 {this.settingsPanel()}
             </div>);
diff --git a/src/client/views/pdf/PDFViewer.scss b/src/client/views/pdf/PDFViewer.scss
index a561be94d..4ec2118ee 100644
--- a/src/client/views/pdf/PDFViewer.scss
+++ b/src/client/views/pdf/PDFViewer.scss
@@ -18,9 +18,8 @@
     .page {
         position: relative;
     }
-
-    .pdfViewer-text {
-        transform-origin: top left;
+    .collectionfreeformview-container {
+        pointer-events: none;
     }
 
     .pdfViewer-dragAnnotationBox {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index ea5e00d73..783495e5a 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -1,29 +1,29 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
 import { observer } from "mobx-react";
 import * as Pdfjs from "pdfjs-dist";
 import "pdfjs-dist/web/pdf_viewer.css";
 import { Dictionary } from "typescript-collections";
-import { Doc, DocListCast, FieldResult, WidthSym } from "../../../new_fields/Doc";
+import { Doc, DocListCast, FieldResult, WidthSym, Opt } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
+import { listSpec } from "../../../new_fields/Schema";
 import { ScriptField } from "../../../new_fields/ScriptField";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { numberRange } from "../../../Utils";
+import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { numberRange, emptyFunction, returnOne } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { Docs, DocUtils } from "../../documents/Documents";
-import { KeyCodes } from "../../northstar/utils/KeyCodes";
 import { DragManager } from "../../util/DragManager";
 import { CompiledScript, CompileScript } from "../../util/Scripting";
+import { Transform } from "../../util/Transform";
+import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
 import Annotation from "./Annotation";
 import PDFMenu from "./PDFMenu";
 import "./PDFViewer.scss";
 import React = require("react");
-import requestPromise = require("request-promise");
-import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
+import { CollectionPDFView } from "../collections/CollectionPDFView";
+import { CollectionVideoView } from "../collections/CollectionVideoView";
 import { CollectionView } from "../collections/CollectionView";
-import { listSpec } from "../../../new_fields/Schema";
-import { Transform } from "../../util/Transform";
+import { SelectionManager } from "../../util/SelectionManager";
 const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer");
 
 interface IViewerProps {
@@ -33,6 +33,9 @@ interface IViewerProps {
     DataDoc?: Doc;
     fieldExtensionDoc: Doc;
     fieldKey: string;
+    fieldExt: string;
+    renderDepth: number;
+    isSelected: () => boolean;
     loaded: (nw: number, nh: number, np: number) => void;
     scrollTo: (y: number) => void;
     active: () => boolean;
@@ -42,7 +45,7 @@ interface IViewerProps {
     addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean;
     setPdfViewer: (view: PDFViewer) => void;
     ScreenToLocalTransform: () => Transform;
-
+    ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
 }
 
 /**
@@ -60,18 +63,22 @@ export class PDFViewer extends React.Component<IViewerProps> {
     @observable private _marqueeWidth: number = 0;
     @observable private _marqueeHeight: number = 0;
 
+    public pdfViewer: any;
+    private _isChildActive = false;
+    private _setPreviewCursor: undefined | ((x: number, y: number) => void);
     private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
     private _reactionDisposer?: IReactionDisposer;
     private _annotationReactionDisposer?: IReactionDisposer;
     private _filterReactionDisposer?: IReactionDisposer;
     private _viewer: React.RefObject<HTMLDivElement> = React.createRef();
     private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
-    public _pdfViewer: any;
     private _selectionText: string = "";
     private _marquee: React.RefObject<HTMLDivElement> = React.createRef();
     private _marqueeing: boolean = false;
-    private _startY: number = 0;
     private _startX: number = 0;
+    private _startY: number = 0;
+    private _downX: number = 0;
+    private _downY: number = 0;
 
     @computed get allAnnotations() {
         return DocListCast(this.props.fieldExtensionDoc.annotations).filter(
@@ -157,22 +164,22 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
     @action
     setupPdfJsViewer = () => {
-        document.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = 1);
+        document.addEventListener("pagesinit", () => this.pdfViewer.currentScaleValue = 1);
         document.addEventListener("pagerendered", () => console.log("rendered"));
         var pdfLinkService = new PDFJSViewer.PDFLinkService();
         let pdfFindController = new PDFJSViewer.PDFFindController({
             linkService: pdfLinkService,
         });
-        this._pdfViewer = new PDFJSViewer.PDFViewer({
+        this.pdfViewer = new PDFJSViewer.PDFViewer({
             container: this._mainCont.current,
             viewer: this._viewer.current,
             linkService: pdfLinkService,
             findController: pdfFindController,
             renderer: "svg"
         });
-        pdfLinkService.setViewer(this._pdfViewer);
+        pdfLinkService.setViewer(this.pdfViewer);
         pdfLinkService.setDocument(this.props.pdf, null);
-        this._pdfViewer.setDocument(this.props.pdf);
+        this.pdfViewer.setDocument(this.props.pdf);
     }
 
     @action
@@ -195,7 +202,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
             annoDocs.push(annoDoc);
             annoDoc.isButton = true;
             anno.remove();
-            this.props.addDocument && this.props.addDocument(annoDoc, false);
+            // this.props.addDocument && this.props.addDocument(annoDoc, false);
             mainAnnoDoc = annoDoc;
             mainAnnoDocProto.y = annoDoc.y;
             mainAnnoDocProto = Doc.GetProto(annoDoc);
@@ -305,8 +312,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
     @action
     search = (searchString: string) => {
-        if (this._pdfViewer._pageViewsReady) {
-            this._pdfViewer.findController.executeCommand('findagain', {
+        if (this.pdfViewer._pageViewsReady) {
+            this.pdfViewer.findController.executeCommand('findagain', {
                 caseSensitive: false,
                 findPrevious: undefined,
                 highlightAll: true,
@@ -316,7 +323,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         }
         else if (this._mainCont.current) {
             let executeFind = () => {
-                this._pdfViewer.findController.executeCommand('find', {
+                this.pdfViewer.findController.executeCommand('find', {
                     caseSensitive: false,
                     findPrevious: undefined,
                     highlightAll: true,
@@ -333,7 +340,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
     onPointerDown = (e: React.PointerEvent): void => {
         // if alt+left click, drag and annotate
         if (NumCast(this.props.Document.scale, 1) !== 1) return;
-        if (!e.altKey && e.button === 0) {
+        this._marqueeing = false;
+        if (!e.altKey && e.button === 0 && this.active()) {
             PDFMenu.Instance.StartDrag = this.startDrag;
             PDFMenu.Instance.Highlight = this.highlight;
             PDFMenu.Instance.Snippet = this.createSnippet;
@@ -346,6 +354,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
                 }
             }
             else {
+                this._downX = e.clientX;
+                this._downY = e.clientY;
                 // set marquee x and y positions to the spatially transformed position
                 if (this._mainCont.current) {
                     let boundingRect = this._mainCont.current.getBoundingClientRect();
@@ -356,15 +366,15 @@ export class PDFViewer extends React.Component<IViewerProps> {
                 this._marquee.current && (this._marquee.current.style.opacity = "0.2");
                 this.receiveAnnotations([], -1);
             }
-            document.removeEventListener("pointermove", this.onSelectStart);
-            document.addEventListener("pointermove", this.onSelectStart);
+            document.removeEventListener("pointermove", this.onSelectMove);
+            document.addEventListener("pointermove", this.onSelectMove);
             document.removeEventListener("pointerup", this.onSelectEnd);
             document.addEventListener("pointerup", this.onSelectEnd);
         }
     }
 
     @action
-    onSelectStart = (e: PointerEvent): void => {
+    onSelectMove = (e: PointerEvent): void => {
         if (this._marqueeing && this._mainCont.current) {
             // transform positions and find the width and height to set the marquee to
             let boundingRect = this._mainCont.current.getBoundingClientRect();
@@ -419,7 +429,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
     @action
     onSelectEnd = (e: PointerEvent): void => {
         if (this._marqueeing) {
-            this._marqueeing = false;
             if (this._marqueeWidth > 10 || this._marqueeHeight > 10) {
                 if (this._marquee.current) { // make a copy of the marquee
                     let copy = document.createElement("div");
@@ -444,23 +453,23 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
             this._marqueeHeight = this._marqueeWidth = 0;
         }
-        // else {
-        //     let sel = window.getSelection();
-        //     if (sel && sel.type === "Range") {
-        //         let selRange = sel.getRangeAt(0);
-        //         this.createTextAnnotation(sel, selRange);
-        //         PDFMenu.Instance.jumpTo(e.clientX, e.clientY);
-        //     }
-        // }
-
-        // if (PDFMenu.Instance.Highlighting) {
-        //     this.highlight(undefined, "goldenrod");
-        // }
-        // else {
-        //     PDFMenu.Instance.StartDrag = this.startDrag;
-        //     PDFMenu.Instance.Highlight = this.highlight;
-        // }
-        document.removeEventListener("pointermove", this.onSelectStart);
+        else {
+            let sel = window.getSelection();
+            if (sel && sel.type === "Range") {
+                let selRange = sel.getRangeAt(0);
+                this.createTextAnnotation(sel, selRange);
+                PDFMenu.Instance.jumpTo(e.clientX, e.clientY);
+            }
+        }
+
+        if (PDFMenu.Instance.Highlighting) {
+            this.highlight(undefined, "goldenrod");
+        }
+        else {
+            PDFMenu.Instance.StartDrag = this.startDrag;
+            PDFMenu.Instance.Highlight = this.highlight;
+        }
+        document.removeEventListener("pointermove", this.onSelectMove);
         document.removeEventListener("pointerup", this.onSelectEnd);
     }
 
@@ -468,7 +477,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     highlight = (targetDoc: Doc | undefined, color: string) => {
         // creates annotation documents for current highlights
         let annotationDoc = this.makeAnnotationDocument(targetDoc, color, false);
-        Doc.AddDocToList(this.props.fieldExtensionDoc, "annotations", annotationDoc);
+        Doc.AddDocToList(this.props.fieldExtensionDoc, this.props.fieldExt, annotationDoc);
         return annotationDoc;
     }
 
@@ -529,7 +538,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     removeDocument(doc: Doc): boolean {
         //TODO This won't create the field if it doesn't already exist
         let targetDataDoc = this.props.fieldExtensionDoc;
-        let targetField = "annotations";
+        let targetField = this.props.fieldExt;
         let value = Cast(targetDataDoc[targetField], listSpec(Doc), []);
         let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1);
         index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1);
@@ -539,8 +548,22 @@ export class PDFViewer extends React.Component<IViewerProps> {
     scrollXf = () => {
         return this._mainCont.current ? this.props.ScreenToLocalTransform().translate(0, this._mainCont.current.scrollTop) : this.props.ScreenToLocalTransform();
     }
+    setPreviewCursor = (func?: (x: number, y: number) => void) => {
+        this._setPreviewCursor = func;
+    }
+    onClick = (e: React.MouseEvent) => {
+        this._setPreviewCursor && this._marqueeing && Math.abs(e.clientX - this._downX) < 3 && Math.abs(e.clientY - this._downY) < 3 &&
+            this._setPreviewCursor(e.clientX, e.clientY);
+    }
+    whenActiveChanged = (isActive: boolean) => {
+        this._isChildActive = isActive;
+        //this.props.whenActiveChanged(isActive); // bcz: is this needed here?
+    }
+    active = () => {
+        return this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0;
+    }
     render() {
-        return (<div className="pdfViewer-viewer" onPointerDown={this.onPointerDown} onWheel={(e) => e.stopPropagation()} ref={this._mainCont}>
+        return (<div className="pdfViewer-viewer" onPointerDown={this.onPointerDown} onWheel={(e) => e.stopPropagation()} onClick={this.onClick} ref={this._mainCont}>
             <div className="pdfViewer-text" ref={this._viewer} />
             <div className="pdfViewer-dragAnnotationBox" ref={this._marquee}
                 style={{
@@ -554,17 +577,24 @@ export class PDFViewer extends React.Component<IViewerProps> {
                     <Annotation {...this.props} anno={anno} key={`${anno[Id]}-annotation`} />)}
             </div>
             <CollectionFreeFormView {...this.props}
-                fieldExt="annotations"
+                setPreviewCursor={this.setPreviewCursor}
                 PanelHeight={() => this._pageSizes.length && this._pageSizes[0] ? this.props.pdf.numPages * this._pageSizes[0].height : 300}
+                PanelWidth={() => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : 300}
+                focus={emptyFunction}
+                isSelected={this.props.isSelected}
+                select={emptyFunction}
+                active={this.active}
+                ContentScaling={returnOne}
+                whenActiveChanged={this.whenActiveChanged}
                 removeDocument={this.removeDocument}
                 moveDocument={this.moveDocument}
-                addDocument={(doc: Doc, allow: boolean | undefined) => { Doc.AddDocToList(this.props.fieldExtensionDoc, "annotations", doc); return true; }}
+                addDocument={(doc: Doc, allow: boolean | undefined) => { Doc.AddDocToList(this.props.fieldExtensionDoc, this.props.fieldExt, doc); return true; }}
                 CollectionView={this.props.ContainingCollectionView}
                 ScreenToLocalTransform={this.scrollXf}
-                ruleProvider={this.props.ruleProvider}
-                chromeCollapsed={true}
-                layoutKey={undefined}
-                backgroundLayout={undefined} >
+                ruleProvider={undefined}
+                renderDepth={this.props.renderDepth + 1}
+                ContainingCollectionDoc={this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document}
+                chromeCollapsed={true}>
             </CollectionFreeFormView>
         </div >);
     }
-- 
cgit v1.2.3-70-g09d2


From 8790670f8e2173dd2a578500b3f03ad08ef793f2 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 30 Sep 2019 20:56:10 -0400
Subject: switching presentatons to be colllections

---
 .../views/collections/CollectionSchemaView.tsx     |  9 ++-
 .../views/collections/CollectionStackingView.scss  |  2 +-
 .../views/collections/CollectionStackingView.tsx   |  4 +-
 .../views/collections/CollectionTreeView.scss      |  4 +-
 .../views/collections/CollectionTreeView.tsx       | 18 +++---
 src/client/views/collections/CollectionView.tsx    |  8 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 20 +-----
 src/client/views/nodes/PresBox.scss                |  4 +-
 src/client/views/nodes/PresBox.tsx                 | 73 ++++++++++++++--------
 .../views/presentationview/PresElementBox.scss     |  1 +
 .../views/presentationview/PresElementBox.tsx      | 46 +++++++-------
 11 files changed, 101 insertions(+), 88 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 8d931f812..77d86b2fa 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -166,6 +166,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 width={this.previewWidth}
                 height={this.previewHeight}
                 getTransform={this.getPreviewTransform}
+                CollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
                 CollectionView={this.props.CollectionView}
                 moveDocument={this.props.moveDocument}
                 addDocument={this.props.addDocument}
@@ -906,8 +907,10 @@ interface CollectionSchemaPreviewProps {
     width: () => number;
     height: () => number;
     ruleProvider: Doc | undefined;
+    focus?: (doc: Doc) => void;
     showOverlays?: (doc: Doc) => { title?: string, caption?: string };
     CollectionView?: CollectionView | CollectionPDFView | CollectionVideoView;
+    CollectionDoc?: Doc;
     onClick?: ScriptField;
     getTransform: () => Transform;
     addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
@@ -994,7 +997,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         height: this.props.height(),
                         width: this.props.width()
                     }}>
-                    <DocumentView
+                    <DocumentView {...this.props}
                         DataDoc={this.props.DataDocument}
                         Document={this.props.Document}
                         fitToBox={this.props.fitToBox}
@@ -1006,7 +1009,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         moveDocument={this.props.moveDocument}
                         whenActiveChanged={this.props.whenActiveChanged}
                         ContainingCollectionView={this.props.CollectionView}
-                        ContainingCollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
+                        ContainingCollectionDoc={this.props.CollectionDoc}
                         addDocTab={this.props.addDocTab}
                         pinToPres={this.props.pinToPres}
                         parentActive={this.props.active}
@@ -1015,7 +1018,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         ContentScaling={this.contentScaling}
                         PanelWidth={this.PanelWidth}
                         PanelHeight={this.PanelHeight}
-                        focus={emptyFunction}
+                        focus={this.props.focus || emptyFunction}
                         backgroundColor={returnEmptyString}
                         bringToFront={emptyFunction}
                         zoomToScale={emptyFunction}
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 01d4ea2b6..74da4ef85 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -9,7 +9,7 @@
 .collectionStackingView, .collectionMasonryView{
     height: 100%;
     width: 100%;
-    position: absolute;
+    position: relative;
     top: 0;
     overflow-y: auto;
     flex-wrap: wrap;
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 1eeb16c4a..6712e8cfe 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -133,7 +133,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     getDisplayDoc(layoutDoc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) {
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
-        return <CollectionSchemaPreview
+        return <CollectionSchemaPreview {...this.props}
             Document={layoutDoc}
             DataDocument={dataDoc}
             showOverlays={this.overlays}
@@ -144,6 +144,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             width={width}
             height={height}
             getTransform={finalDxf}
+            focus={this.props.focus}
+            CollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
             CollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
             moveDocument={this.props.moveDocument}
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 197e57808..ab01a1086 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -8,11 +8,11 @@
     box-sizing: border-box;
     height: 100%;
     width:100%;
-    position: absolute;
+    position: relative;
     top:0;
     padding-top: 20px;
     padding-left: 10px;
-    padding-right: 0px;
+    padding-right: 10px;
     background: $light-color-secondary;
     font-size: 13px;
     overflow: auto;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index e5313f68c..a133e2c51 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,12 +1,13 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faArrowsAltH, faCaretSquareDown, faCaretSquareRight, faTrashAlt, faPlus, faMinus } from '@fortawesome/free-solid-svg-icons';
+import { faAngleRight, faArrowsAltH, faBell, faCamera, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faExpand, faMinus, faPlus, faTrash, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, trace, untracked } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCast, HeightSym, WidthSym, Opt, Field } from '../../../new_fields/Doc';
+import { Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
 import { Document, listSpec } from '../../../new_fields/Schema';
+import { ComputedField, ScriptField } from '../../../new_fields/ScriptField';
 import { BoolCast, Cast, NumCast, StrCast } from '../../../new_fields/Types';
 import { emptyFunction, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
@@ -17,18 +18,16 @@ import { SelectionManager } from '../../util/SelectionManager';
 import { Transform } from '../../util/Transform';
 import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from '../ContextMenu';
+import { ContextMenuProps } from '../ContextMenuItem';
 import { EditableView } from "../EditableView";
 import { MainView } from '../MainView';
+import { KeyValueBox } from '../nodes/KeyValueBox';
 import { Templates } from '../Templates';
 import { CollectionViewType } from './CollectionBaseView';
-import { CollectionDockingView } from './CollectionDockingView';
 import { CollectionSchemaPreview } from './CollectionSchemaView';
 import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import React = require("react");
-import { ComputedField, ScriptField } from '../../../new_fields/ScriptField';
-import { KeyValueBox } from '../nodes/KeyValueBox';
-import { ContextMenuProps } from '../ContextMenuItem';
 
 
 export interface TreeViewProps {
@@ -250,8 +249,8 @@ class TreeView extends React.Component<TreeViewProps> {
     }
     docWidth = () => {
         let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth);
-        if (aspect) return Math.min(this.props.document[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 5));
-        return NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5;
+        if (aspect) return Math.min(this.props.document[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 20));
+        return NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 20) : this.props.panelWidth() - 20;
     }
     docHeight = () => {
         let bounds = this.boundsOfCollectionDocument;
@@ -331,6 +330,7 @@ class TreeView extends React.Component<TreeViewProps> {
                     width={this.docWidth}
                     height={this.docHeight}
                     getTransform={this.docTransform}
+                    CollectionDoc={this.props.containingCollection}
                     CollectionView={undefined}
                     addDocument={emptyFunction as any}
                     moveDocument={this.props.moveDocument}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 90fa00202..6eb444dde 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,25 +1,23 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faEye } from '@fortawesome/free-regular-svg-icons';
-import { faColumns, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree, faCopy } from '@fortawesome/free-solid-svg-icons';
+import { faColumns, faCopy, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons';
 import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from "mobx-react";
 import * as React from 'react';
-import { Doc, DocListCastAsync } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
-import { StrCast, Cast } from '../../../new_fields/Types';
+import { StrCast } from '../../../new_fields/Types';
 import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
 import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from '../ContextMenuItem';
 import { FieldView, FieldViewProps } from '../nodes/FieldView';
 import { CollectionBaseView, CollectionRenderProps, CollectionViewType } from './CollectionBaseView';
 import { CollectionDockingView } from "./CollectionDockingView";
+import { AddCustomFreeFormLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines';
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
 import { CollectionSchemaView } from "./CollectionSchemaView";
 import { CollectionStackingView } from './CollectionStackingView';
 import { CollectionTreeView } from "./CollectionTreeView";
 import { CollectionViewBaseChrome } from './CollectionViewChromes';
-import { ImageField } from '../../../new_fields/URLField';
-import { AddCustomFreeFormLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines';
 export const COLLECTION_BORDER_WIDTH = 2;
 
 library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a9699d17b..6fc809f7f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -443,11 +443,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps {
         return {
+            ...this.props,
             DataDoc: childData,
             Document: childLayout,
-            addDocument: this.props.addDocument,
-            removeDocument: this.props.removeDocument,
-            moveDocument: this.props.moveDocument,
             ruleProvider: this.Document.isRuleProvider && childLayout.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider, //bcz: hack! - currently ruleProviders apply to documents in nested colleciton, not direct children of themselves
             onClick: undefined, // this.props.onClick,  // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them
             ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform,
@@ -460,37 +458,23 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             focus: this.focusDocument,
             backgroundColor: this.getClusterColor,
             parentActive: this.props.active,
-            whenActiveChanged: this.props.whenActiveChanged,
             bringToFront: this.bringToFront,
-            addDocTab: this.props.addDocTab,
-            pinToPres: this.props.pinToPres,
             zoomToScale: this.zoomToScale,
             getScale: this.getScale
         };
     }
     getDocumentViewProps(layoutDoc: Doc): DocumentViewProps {
         return {
-            DataDoc: this.props.DataDoc,
-            Document: this.props.Document,
-            addDocument: this.props.addDocument,
-            removeDocument: this.props.removeDocument,
-            moveDocument: this.props.moveDocument,
-            ruleProvider: this.props.ruleProvider,
-            onClick: this.props.onClick,
+            ...this.props,
             ScreenToLocalTransform: this.getTransform,
-            renderDepth: this.props.renderDepth,
             PanelWidth: layoutDoc[WidthSym],
             PanelHeight: layoutDoc[HeightSym],
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
-            ContainingCollectionDoc: this.props.ContainingCollectionDoc,
             focus: this.focusDocument,
             backgroundColor: returnEmptyString,
             parentActive: this.props.active,
-            whenActiveChanged: this.props.whenActiveChanged,
             bringToFront: this.bringToFront,
-            addDocTab: this.props.addDocTab,
-            pinToPres: this.props.pinToPres,
             zoomToScale: this.zoomToScale,
             getScale: this.getScale
         };
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index 2aadd77aa..e5a79ab11 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -15,6 +15,7 @@
     pointer-events: all;
 
     .presBox-listCont {
+        position: relative;
         padding-left: 10px;
         padding-right: 10px;
     }
@@ -29,5 +30,4 @@
             border-radius: 5px;
         }
     }
-}
-
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index d3a24eb7a..ab777d534 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -2,7 +2,7 @@ import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, observable, runInAction, computed } from "mobx";
+import { action, computed, reaction, IReactionDisposer } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
 import { listSpec } from "../../../new_fields/Schema";
@@ -10,12 +10,15 @@ import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { DocumentManager } from "../../util/DocumentManager";
 import { undoBatch } from "../../util/UndoManager";
+import { CollectionViewType } from "../collections/CollectionBaseView";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionView } from "../collections/CollectionView";
 import { ContextMenu } from "../ContextMenu";
-import "./PresBox.scss";
 import { FieldView, FieldViewProps } from './FieldView';
-import { PresElementBox } from "../presentationview/PresElementBox";
-import { Id } from "../../../new_fields/FieldSymbols";
+import "./PresBox.scss";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { Docs } from "../../documents/Documents";
+import { ComputedField } from "../../../new_fields/ScriptField";
 
 library.add(faArrowLeft);
 library.add(faArrowRight);
@@ -29,6 +32,29 @@ library.add(faEdit);
 @observer
 export class PresBox extends React.Component<FieldViewProps> {
     public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(PresBox, fieldKey); }
+    _docListChangedReaction: IReactionDisposer | undefined;
+    componentDidMount() {
+        this._docListChangedReaction = reaction(() => {
+            const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)));
+            return value ? value.slice() : value;
+        }, () => {
+            const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc)));
+            if (value) {
+                value.forEach((item, i) => {
+                    if (item instanceof Doc && item.type !== DocumentType.PRESELEMENT) {
+                        let pinDoc = Docs.Create.PresElementBoxDocument();
+                        Doc.GetProto(pinDoc).target = item;
+                        Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.target instanceof Doc) && this.target.title.toString()');
+                        value.splice(i, 1, pinDoc);
+                    }
+                })
+            }
+        });
+    }
+
+    componentWillUnmount() {
+        this._docListChangedReaction && this._docListChangedReaction();
+    }
 
     @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); }
 
@@ -275,20 +301,14 @@ export class PresBox extends React.Component<FieldViewProps> {
     //directly at start.
     startPresentation = (startIndex: number) => {
         this.childDocs.map(doc => {
-            if (doc.hideTillShownButton) {
-                if (this.childDocs.indexOf(doc) > startIndex) {
-                    doc.opacity = 0;
-                }
+            if (doc.hideTillShownButton && this.childDocs.indexOf(doc) > startIndex) {
+                doc.opacity = 0;
             }
-            if (doc.hideAfterButton) {
-                if (this.childDocs.indexOf(doc) < startIndex) {
-                    doc.opacity = 0;
-                }
+            if (doc.hideAfterButton && this.childDocs.indexOf(doc) < startIndex) {
+                doc.opacity = 0;
             }
-            if (doc.fadeButton) {
-                if (this.childDocs.indexOf(doc) < startIndex) {
-                    doc.opacity = 0.5;
-                }
+            if (doc.fadeButton && this.childDocs.indexOf(doc) < startIndex) {
+                doc.opacity = 0.5;
             }
         });
     }
@@ -316,8 +336,13 @@ export class PresBox extends React.Component<FieldViewProps> {
      * that they will be displayed in a canvas with scale 1.
      */
     @action
-    initializeScaleViews = (docList: Doc[]) => {
+    initializeScaleViews = (docList: Doc[], viewtype: number) => {
+        this.props.Document.chromeStatus = "disabled";
+        let hgt = (viewtype === CollectionViewType.Tree) ? 50 : 72;
         docList.forEach((doc: Doc) => {
+            doc.presBox = this.props.Document;
+            doc.presBoxKey = this.props.fieldKey;
+            doc.height = hgt;
             let curScale = NumCast(doc.viewScale, null);
             if (curScale === undefined) {
                 doc.viewScale = 1;
@@ -325,13 +350,14 @@ export class PresBox extends React.Component<FieldViewProps> {
         });
     }
 
+
     selectElement = (doc: Doc) => {
         let index = DocListCast(this.props.Document[this.props.fieldKey]).indexOf(doc);
         index !== -1 && this.gotoDocument(index, NumCast(this.props.Document.selectedDoc));
     }
 
     render() {
-        this.initializeScaleViews(this.childDocs);
+        this.initializeScaleViews(this.childDocs, NumCast(this.props.Document.viewType));
         return (
             <div className="presBox-cont" onContextMenu={this.specificContextMenu}>
                 <div className="presBox-buttons">
@@ -344,14 +370,9 @@ export class PresBox extends React.Component<FieldViewProps> {
                 </div>
                 {this.props.Document.minimizedView ? (null) :
                     <div className="presBox-listCont" >
-                        {this.childDocs.map(doc =>
-                            <PresElementBox key={doc[Id]}  {... this.props} Document={doc}
-                                removeDocument={this.removeDocument}
-                                focus={this.selectElement}
-                                presBox={this}
-                            />
-                        )}
-                    </div>}
+                        <CollectionView {...this.props} focus={this.selectElement} />
+                    </div>
+                }
             </div>
         );
     }
diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss
index c7d846718..51f2d2ab8 100644
--- a/src/client/views/presentationview/PresElementBox.scss
+++ b/src/client/views/presentationview/PresElementBox.scss
@@ -1,6 +1,7 @@
 .presElementBox-item {
     padding: 10px;
     display: inline-block;
+    pointer-events: all;
     width: 100%;
     outline-color: maroon;
     outline-style: dashed;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 1b4c841e7..7692800c3 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -12,11 +12,11 @@ import { DocumentType } from "../../documents/DocumentTypes";
 import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
+import { CollectionViewType } from '../collections/CollectionBaseView';
 import { DocumentView } from "../nodes/DocumentView";
-import React = require("react");
+import { FieldView, FieldViewProps } from '../nodes/FieldView';
 import "./PresElementBox.scss";
-import { FieldViewProps, FieldView } from '../nodes/FieldView';
-import { PresBox } from '../nodes/PresBox';
+import React = require("react");
 
 
 library.add(faArrowUp);
@@ -25,26 +25,22 @@ library.add(faLocationArrow);
 library.add(fileRegular as any);
 library.add(faSearch);
 library.add(faArrowDown);
-
-interface PresElementProps {
-    presBox: PresBox;
-}
-
 /**
  * This class models the view a document added to presentation will have in the presentation.
  * It involves some functionality for its buttons and options.
  */
 @observer
-export class PresElementBox extends React.Component<PresElementProps & FieldViewProps> {
+export class PresElementBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(PresElementBox); }
     private header?: HTMLDivElement | undefined;
     private listdropDisposer?: DragManager.DragDropDisposer;
     private presElRef: React.RefObject<HTMLDivElement> = React.createRef();
+    private _embedHeight = 100;
 
-    @computed get myIndex() { return DocListCast(this.props.presBox.props.Document[this.props.presBox.props.fieldKey]).indexOf(this.props.Document) }
-    @computed get presentationDoc() { return this.props.presBox.props.Document; }
-    @computed get presentationFieldKey() { return this.props.presBox.props.fieldKey; }
+    @computed get myIndex() { return DocListCast(this.presentationDoc[this.presentationFieldKey]).indexOf(this.props.Document); }
+    @computed get presentationDoc() { return this.props.Document.presBox as Doc; }
+    @computed get presentationFieldKey() { return StrCast(this.props.Document.presBoxKey); }
     @computed get currentIndex() { return NumCast(this.presentationDoc.selectedDoc); }
     @computed get showButton() { return BoolCast(this.props.Document.showButton); }
     @computed get navButton() { return BoolCast(this.props.Document.navButton); }
@@ -266,12 +262,12 @@ export class PresElementBox extends React.Component<PresElementProps & FieldView
         let scale = () => 175 / NumCast(this.props.Document.nativeWidth, 175);
         return (
             <div className="presElementBox-embedded" style={{
-                height: propDocHeight === 0 ? 100 : propDocHeight * scale(),
+                height: propDocHeight === 0 ? this._embedHeight : propDocHeight * scale(),
                 width: propDocWidth === 0 ? "auto" : propDocWidth * scale(),
             }}>
                 <DocumentView
                     fitToBox={StrCast(this.props.Document.type).indexOf(DocumentType.COL) !== -1}
-                    Document={this.props.Document.target as Doc}
+                    Document={this.props.Document.target}
                     addDocument={returnFalse}
                     removeDocument={returnFalse}
                     ruleProvider={undefined}
@@ -300,6 +296,7 @@ export class PresElementBox extends React.Component<PresElementProps & FieldView
     render() {
         let p = this.props;
 
+        let treecontainer = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.viewType === CollectionViewType.Tree;
         let className = "presElementBox-item" + (this.currentIndex === this.myIndex ? " presElementBox-selected" : "");
         let dropAction = StrCast(this.props.Document.dropAction) as dropActionType;
         let onItemDown = SetupDrag(this.presElRef, () => p.Document, this.move, dropAction, this.presentationDoc[Id], true);
@@ -310,18 +307,25 @@ export class PresElementBox extends React.Component<PresElementProps & FieldView
                 onPointerDown={onItemDown}
                 style={{ outlineWidth: Doc.IsBrushed(p.Document) ? `1px` : "0px", }}
                 onClick={e => p.focus(p.Document)}>
-                <strong className="presElementBox-name">
-                    {`${this.myIndex + 1}. ${p.Document.title}`}
-                </strong>
-                <button className="presElementBox-icon" onPointerDown={e => e.stopPropagation()} onClick={e => this.props.removeDocument && this.props.removeDocument(p.Document)}>X</button>
-                <br />
+                {treecontainer ? (null) : <>
+                    <strong className="presElementBox-name">
+                        {`${this.myIndex + 1}. ${p.Document.title}`}
+                    </strong>
+                    <button className="presElementBox-icon" onPointerDown={e => e.stopPropagation()} onClick={e => this.props.removeDocument && this.props.removeDocument(p.Document)}>X</button>
+                    <br />
+                </>
+                }
                 <button title="Zoom" className={"presElementBox-interaction" + (this.showButton ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={this.onZoomDocumentClick}><FontAwesomeIcon icon={"search"} /></button>
                 <button title="Navigate" className={"presElementBox-interaction" + (this.navButton ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={this.onNavigateDocumentClick}><FontAwesomeIcon icon={"location-arrow"} /></button>
                 <button title="Hide Til Presented" className={"presElementBox-interaction" + (this.hideTillShownButton ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={this.onHideDocumentUntilPressClick}><FontAwesomeIcon icon={fileSolid} /></button>
                 <button title="Fade After Presented" className={"presElementBox-interaction" + (this.fadeButton ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={this.onFadeDocumentAfterPresentedClick}><FontAwesomeIcon icon={faFileDownload} /></button>
                 <button title="Hide After Presented" className={"presElementBox-interaction" + (this.hideAfterButton ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={this.onHideDocumentAfterPresentedClick}><FontAwesomeIcon icon={faFileDownload} /></button>
-                <button title="Group With Up" className={"presElementBox-interaction" + (this.groupButton ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={action(() => this.groupButton = !this.groupButton)}> <FontAwesomeIcon icon={"arrow-up"} /> </button>
-                <button title="Expand Inline" className={"presElementBox-interaction" + (this.embedInline ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={action(() => this.embedInline = !this.embedInline)}><FontAwesomeIcon icon={"arrow-down"} /></button>
+                <button title="Group With Up" className={"presElementBox-interaction" + (this.groupButton ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={action((e: any) => { e.stopPropagation(); this.groupButton = !this.groupButton; })}> <FontAwesomeIcon icon={"arrow-up"} /> </button>
+                <button title="Expand Inline" className={"presElementBox-interaction" + (this.embedInline ? "-selected" : "")} onPointerDown={(e) => e.stopPropagation()} onClick={action((e: any) => {
+                    this.embedInline = !this.embedInline;
+                    this.props.Document.height = NumCast(this.props.Document.height) + (this.embedInline ? 1 : -1) * this._embedHeight;
+                    e.stopPropagation();
+                })}><FontAwesomeIcon icon={"arrow-down"} /></button>
 
                 <br />
                 {this.renderEmbeddedInline()}
-- 
cgit v1.2.3-70-g09d2


From 9e1234abe64d289927122ad641e3bcaf0b9eaf6e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 1 Oct 2019 02:54:03 -0400
Subject: bugs, bugs.  this time with fittobox when called from schema view
 which was passing width and height as functions, not values.  switched to
 PanelWidth and PanelHeight

---
 .../views/collections/CollectionSchemaView.tsx     | 32 +++++++++++-----------
 .../views/collections/CollectionStackingView.tsx   |  4 +--
 .../views/collections/CollectionTreeView.tsx       |  4 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +--
 src/client/views/nodes/PresBox.tsx                 |  4 +--
 .../views/presentationview/PresElementBox.tsx      | 22 ++++++---------
 6 files changed, 33 insertions(+), 37 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 77d86b2fa..59cce7386 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -163,8 +163,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 childDocs={this.childDocs}
                 renderDepth={this.props.renderDepth}
                 ruleProvider={this.props.Document.isRuleProvider && layoutDoc && layoutDoc.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider}
-                width={this.previewWidth}
-                height={this.previewHeight}
+                PanelWidth={this.previewWidth}
+                PanelHeight={this.previewHeight}
                 getTransform={this.getPreviewTransform}
                 CollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
                 CollectionView={this.props.CollectionView}
@@ -904,8 +904,8 @@ interface CollectionSchemaPreviewProps {
     childDocs?: Doc[];
     renderDepth: number;
     fitToBox?: boolean;
-    width: () => number;
-    height: () => number;
+    PanelWidth: () => number;
+    PanelHeight: () => number;
     ruleProvider: Doc | undefined;
     focus?: (doc: Doc) => void;
     showOverlays?: (doc: Doc) => { title?: string, caption?: string };
@@ -928,12 +928,12 @@ interface CollectionSchemaPreviewProps {
 export class CollectionSchemaPreview extends React.Component<CollectionSchemaPreviewProps>{
     private dropDisposer?: DragManager.DragDropDisposer;
     _mainCont?: HTMLDivElement;
-    private get nativeWidth() { return NumCast(this.props.Document!.nativeWidth, this.props.width()); }
-    private get nativeHeight() { return NumCast(this.props.Document!.nativeHeight, this.props.height()); }
+    private get nativeWidth() { return NumCast(this.props.Document!.nativeWidth, this.props.PanelWidth()); }
+    private get nativeHeight() { return NumCast(this.props.Document!.nativeHeight, this.props.PanelHeight()); }
     private contentScaling = () => {
-        let wscale = this.props.width() / (this.nativeWidth ? this.nativeWidth : this.props.width());
-        if (wscale * this.nativeHeight > this.props.height()) {
-            return this.props.height() / (this.nativeHeight ? this.nativeHeight : this.props.height());
+        let wscale = this.props.PanelWidth() / (this.nativeWidth ? this.nativeWidth : this.props.PanelWidth());
+        if (wscale * this.nativeHeight > this.props.PanelHeight()) {
+            return this.props.PanelHeight() / (this.nativeHeight ? this.nativeHeight : this.props.PanelHeight());
         }
         return wscale;
     }
@@ -962,10 +962,10 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
         }
         return true;
     }
-    private PanelWidth = () => this.nativeWidth ? this.nativeWidth * this.contentScaling() : this.props.width();
-    private PanelHeight = () => this.nativeHeight ? this.nativeHeight * this.contentScaling() : this.props.height();
+    private PanelWidth = () => this.nativeWidth ? this.nativeWidth * this.contentScaling() : this.props.PanelWidth();
+    private PanelHeight = () => this.nativeHeight ? this.nativeHeight * this.contentScaling() : this.props.PanelHeight();
     private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling());
-    get centeringOffset() { return this.nativeWidth ? (this.props.width() - this.nativeWidth * this.contentScaling()) / 2 : 0; }
+    get centeringOffset() { return this.nativeWidth ? (this.props.PanelWidth() - this.nativeWidth * this.contentScaling()) / 2 : 0; }
     @action
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.props.setPreviewScript(e.currentTarget.value);
@@ -987,15 +987,15 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
             <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>;
         return (<div className="collectionSchemaView-previewRegion"
-            style={{ width: this.props.width(), height: this.props.height() }}>
-            {!this.props.Document || !this.props.width ? (null) : (
+            style={{ width: this.props.PanelWidth(), height: this.props.PanelHeight() }}>
+            {!this.props.Document || !this.props.PanelWidth ? (null) : (
                 <div className="collectionSchemaView-previewDoc"
                     style={{
                         transform: `translate(${this.centeringOffset}px, 0px)`,
                         borderRadius: this.borderRounding,
                         display: "inline",
-                        height: this.props.height(),
-                        width: this.props.width()
+                        height: this.props.PanelHeight(),
+                        width: this.props.PanelWidth()
                     }}>
                     <DocumentView {...this.props}
                         DataDoc={this.props.DataDocument}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index c7060f110..e2020601b 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -141,8 +141,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             ruleProvider={this.props.Document.isRuleProvider && layoutDoc.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider}
             fitToBox={this.props.fitToBox}
             onClick={layoutDoc.isTemplate ? this.onClickHandler : this.onChildClickHandler}
-            width={width}
-            height={height}
+            PanelWidth={width}
+            PanelHeight={height}
             getTransform={finalDxf}
             focus={this.props.focus}
             CollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 6ce5d8e20..ffd1f9170 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -327,8 +327,8 @@ class TreeView extends React.Component<TreeViewProps> {
                     showOverlays={this.noOverlays}
                     ruleProvider={this.props.document.isRuleProvider && layoutDoc.type !== DocumentType.TEXT ? this.props.document : this.props.ruleProvider}
                     fitToBox={this.boundsOfCollectionDocument !== undefined}
-                    width={this.docWidth}
-                    height={this.docHeight}
+                    PanelWidth={this.docWidth}
+                    PanelHeight={this.docHeight}
                     getTransform={this.docTransform}
                     CollectionDoc={this.props.containingCollection}
                     CollectionView={undefined}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 6fc809f7f..27b9a06f5 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -745,8 +745,8 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
         const ceny = this.props.centeringShiftY();
         const panx = -this.props.panX();
         const pany = -this.props.panY();
-        const zoom = this.props.zoomScaling();// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
-        return <div className={freeformclass} style={{ borderRadius: "inherit", transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
+        const zoom = this.props.zoomScaling();
+        return <div className={freeformclass} style={{ borderRadius: "inherit", transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}) translate(${panx}px, ${pany}px)` }}>
             {this.props.children}
         </div>;
     }
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 66608fb8d..f44ca99b9 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -47,7 +47,7 @@ export class PresBox extends React.Component<FieldViewProps> {
                         Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.target instanceof Doc) && this.target.title.toString()');
                         value.splice(i, 1, pinDoc);
                     }
-                })
+                });
             }
         });
     }
@@ -343,7 +343,7 @@ export class PresBox extends React.Component<FieldViewProps> {
             doc.presBox = this.props.Document;
             doc.presBoxKey = this.props.fieldKey;
             doc.collapsedHeight = hgt;
-            doc.height = ComputedField.MakeFunction("this.collapsedHeight + Number(this.embedOpen ? 100:0)")
+            doc.height = ComputedField.MakeFunction("this.collapsedHeight + Number(this.embedOpen ? 100:0)");
             let curScale = NumCast(doc.viewScale, null);
             if (curScale === undefined) {
                 doc.viewScale = 1;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index fb9474cde..de3242d32 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -15,6 +15,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from '../nodes/FieldView';
 import "./PresElementBox.scss";
 import React = require("react");
+import { CollectionSchemaPreview } from '../collections/CollectionSchemaView';
 
 
 library.add(faArrowUp);
@@ -173,28 +174,23 @@ export class PresElementBox extends React.Component<FieldViewProps> {
                 height: propDocHeight === 0 ? NumCast(this.props.Document.height) - NumCast(this.props.Document.collapsedHeight) : propDocHeight * scale(),
                 width: propDocWidth === 0 ? "auto" : propDocWidth * scale(),
             }}>
-                <DocumentView
-                    fitToBox={StrCast(this.props.Document.type).indexOf(DocumentType.COL) !== -1}
+                <CollectionSchemaPreview
+                    fitToBox={StrCast(this.props.Document.target.type).indexOf(DocumentType.COL) !== -1}
                     Document={this.props.Document.target}
                     addDocument={returnFalse}
                     removeDocument={returnFalse}
                     ruleProvider={undefined}
-                    ScreenToLocalTransform={Transform.Identity}
                     addDocTab={returnFalse}
                     pinToPres={returnFalse}
+                    PanelWidth={() => this.props.PanelWidth() - 20}
+                    PanelHeight={() => 100}
+                    setPreviewScript={emptyFunction}
+                    getTransform={Transform.Identity}
+                    active={this.props.active}
+                    moveDocument={this.props.moveDocument!}
                     renderDepth={1}
-                    PanelWidth={() => 350}
-                    PanelHeight={() => 90}
                     focus={emptyFunction}
-                    backgroundColor={returnEmptyString}
-                    parentActive={returnFalse}
                     whenActiveChanged={returnFalse}
-                    bringToFront={emptyFunction}
-                    zoomToScale={emptyFunction}
-                    getScale={returnOne}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined}
-                    ContentScaling={scale}
                 />
                 <div className="presElementBox-embeddedMask" />
             </div>
-- 
cgit v1.2.3-70-g09d2


From faaff9fe8aab3bd5d116eab8bd85198a0756fe30 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 1 Oct 2019 10:12:50 -0400
Subject: fixed issues with pdf loading and layout.

---
 package.json                                       |  2 +-
 .../views/collections/CollectionSchemaView.tsx     | 16 +++++------
 src/client/views/nodes/PDFBox.scss                 | 31 ++++++++++++++++++++++
 src/client/views/nodes/PDFBox.tsx                  |  5 ++--
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 src/server/index.ts                                |  8 +++++-
 6 files changed, 49 insertions(+), 15 deletions(-)

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

diff --git a/package.json b/package.json
index fa722a6ae..e516a6979 100644
--- a/package.json
+++ b/package.json
@@ -167,7 +167,7 @@
         "nodemailer": "^5.1.1",
         "nodemon": "^1.18.10",
         "normalize.css": "^8.0.1",
-        "npm": "^6.10.3",
+        "npm": "^6.11.3",
         "p-limit": "^2.2.0",
         "passport": "^0.4.0",
         "passport-google-oauth20": "^2.0.0",
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 59cce7386..853808335 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -303,21 +303,17 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this.props.Document.textwrappedSchemaRows = new List<string>(textWrappedRows);
     }
 
-    @computed get resized(): { "id": string, "value": number }[] {
+    @computed get resized(): { id: string, value: number }[] {
         return this.columns.reduce((resized, shf) => {
-            if (shf.width > -1) {
-                resized.push({ "id": shf.heading, "value": shf.width });
-            }
+            (shf.width > -1) && resized.push({ id: shf.heading, value: shf.width });
             return resized;
-        }, [] as { "id": string, "value": number }[]);
+        }, [] as { id: string, value: number }[]);
     }
-    @computed get sorted(): { id: string, desc: boolean }[] {
+    @computed get sorted(): { id: string, desc?: true }[] {
         return this.columns.reduce((sorted, shf) => {
-            if (shf.desc) {
-                sorted.push({ "id": shf.heading, "desc": shf.desc });
-            }
+            shf.desc && sorted.push({ id: shf.heading, desc: shf.desc });
             return sorted;
-        }, [] as { id: string, desc: boolean }[]);
+        }, [] as { id: string, desc?: true }[]);
     }
 
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index 2917c81cb..3f5f47e05 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -9,6 +9,37 @@
     z-index: -1;
 }
 
+.pdfBox-title-outer {
+    
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    background: lightslategray;
+    .pdfBox-title-cont {
+        width: 150%;
+        height: 100%;
+        position: relative;
+        display: grid;
+        
+        .pdfBox-title {
+            color:lightgray;
+            margin-top: auto;
+            margin-bottom: auto;
+            transform-origin: 42% -18%;
+            width: 100%;
+            transform: rotate(55deg);
+            font-size: 144;
+            padding: 5%;
+            overflow: hidden;
+            display: inline-block;
+            white-space: pre;
+            text-overflow: ellipsis;
+            text-align: center;
+        }
+    }
+}
+
+
 .pdfBox-cont {
     pointer-events: none;
     .collectionFreeFormView-none {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index fe71e76fd..3014af944 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -180,8 +180,9 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     render() {
         const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
         let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.active ? "" : "-interactive");
-        return (!(pdfUrl instanceof PdfField) || !this._pdf ?
-            <div>{`pdf, ${this.dataDoc[this.props.fieldKey]}, not found`}</div> :
+        return (!(pdfUrl instanceof PdfField) || !this._pdf || this.props.ScreenToLocalTransform().Scale > 6 ?
+            <div className="pdfBox-title-outer"><div className="pdfBox-title-cont" >
+                <strong className="pdfBox-title" >{` ${this.props.Document.title}`}</strong> </div></div> :
             <div className={classname} onContextMenu={this.specificContextMenu} onPointerDown={(e: React.PointerEvent) => {
                 let hit = document.elementFromPoint(e.clientX, e.clientY);
                 if (hit && hit.localName === "span" && this.props.isSelected()) {  // drag selecting text stops propagation
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 13fd8ea98..3bf53340b 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -628,7 +628,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         }
         let nativeWidth = NumCast(this.props.Document.nativeWidth);
         let nativeHeight = NumCast(this.props.Document.nativeHeight);
-        return <img key={this._coverPath.path} src={this._coverPath.path} onLoad={action(() => this._showWaiting = false)}
+        return <img key={this._coverPath.path} src={this._coverPath.path} onError={action(() => this._coverPath.path = "http://www.cs.brown.edu/~bcz/face.gif")} onLoad={action(() => this._showWaiting = false)}
             style={{ position: "absolute", display: "inline-block", top: 0, left: 0, width: `${nativeWidth}px`, height: `${nativeHeight}px` }} />;
     }
 
diff --git a/src/server/index.ts b/src/server/index.ts
index a265853ff..690836fff 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -613,7 +613,13 @@ app.post(
                     const result: ParsedPDF = await pdf(dataBuffer);
                     await new Promise<void>(resolve => {
                         const path = pdfDirectory + "/" + filename.substring(0, filename.length - ".pdf".length) + ".txt";
-                        fs.createWriteStream(path).write(result.text, error => error === null ? resolve() : reject(error));
+                        fs.createWriteStream(path).write(result.text, error => {
+                            if (!error) {
+                                resolve();
+                            } else {
+                                reject(error);
+                            }
+                        });
                     });
                 } else {
                     await DashUploadUtils.UploadImage(uploadDirectory + filename, filename).catch(() => console.log(`Unable to process ${filename}`));
-- 
cgit v1.2.3-70-g09d2


From 69e4a936c4eb0cc2e35e4e7f3258aed1f72b8da7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 1 Oct 2019 15:10:22 -0400
Subject: fixed a bunch of pdf related things with stacking views.

---
 .../views/collections/CollectionDockingView.tsx    |  9 ++--
 .../views/collections/CollectionSchemaView.tsx     |  6 +--
 .../views/collections/CollectionStackingView.tsx   |  6 +--
 src/client/views/nodes/DocumentView.tsx            | 54 ++++++++++++++++------
 src/client/views/nodes/PDFBox.tsx                  | 16 +++++--
 src/client/views/pdf/PDFViewer.tsx                 | 17 +++++--
 src/new_fields/Doc.ts                              |  1 +
 7 files changed, 78 insertions(+), 31 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 246546c9e..98aff41d3 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -3,7 +3,7 @@ import { faFile } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, Lambda, observable, reaction, computed, runInAction } from "mobx";
+import { action, Lambda, observable, reaction, computed, runInAction, trace } from "mobx";
 import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
@@ -659,7 +659,10 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
             return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc);
         }
     }
-    docView(document: Doc) {
+
+    @computed get docView() {
+        if (!this._document) return (null);
+        const document = this._document;
         let resolvedDataDoc = document.layout instanceof Doc ? document : this._dataDoc;
         return <DocumentView key={document[Id]}
             Document={document}
@@ -692,7 +695,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                     transform: `translate(${this.previewPanelCenteringOffset}px, 0px)`,
                     height: this._document && this._document.fitWidth ? undefined : "100%"
                 }}>
-                {this.docView(this._document)}
+                {this.docView}
             </div >);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 853808335..24f585a07 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -958,10 +958,10 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
         }
         return true;
     }
-    private PanelWidth = () => this.nativeWidth ? this.nativeWidth * this.contentScaling() : this.props.PanelWidth();
-    private PanelHeight = () => this.nativeHeight ? this.nativeHeight * this.contentScaling() : this.props.PanelHeight();
+    private PanelWidth = () => this.nativeWidth && (!this.props.Document || !this.props.Document.fitWidth) ? this.nativeWidth * this.contentScaling() : this.props.PanelWidth();
+    private PanelHeight = () => this.nativeHeight && (!this.props.Document || !this.props.Document.fitWidth) ? this.nativeHeight * this.contentScaling() : this.props.PanelHeight();
     private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling());
-    get centeringOffset() { return this.nativeWidth ? (this.props.PanelWidth() - this.nativeWidth * this.contentScaling()) / 2 : 0; }
+    get centeringOffset() { return this.nativeWidth && (!this.props.Document || !this.props.Document.fitWidth) ? (this.props.PanelWidth() - this.nativeWidth * this.contentScaling()) / 2 : 0; }
     @action
     onPreviewScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.props.setPreviewScript(e.currentTarget.value);
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index e2020601b..4b81db3a6 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,7 +1,7 @@
 import React = require("react");
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { CursorProperty } from "csstype";
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx";
 import { observer } from "mobx-react";
 import Switch from 'rc-switch';
 import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc";
@@ -133,7 +133,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     getDisplayDoc(layoutDoc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) {
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
-        return <CollectionSchemaPreview {...this.props}
+        return <CollectionSchemaPreview
             Document={layoutDoc}
             DataDocument={dataDoc}
             showOverlays={this.overlays}
@@ -168,7 +168,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             if (!(d.nativeWidth && !d.ignoreAspect && this.props.Document.fillColumn)) wid = Math.min(d[WidthSym](), wid);
             return wid * aspect;
         }
-        return d.fitWidth ? Math.min(this.props.PanelHeight() - 2 * this.yMargin, d[HeightSym]()) : d[HeightSym]();
+        return d.fitWidth ? this.props.PanelHeight() - 2 * this.yMargin : d[HeightSym]();
     }
 
     columnDividerDown = (e: React.PointerEvent) => {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 779e701ea..ded50890d 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 * as fa from '@fortawesome/free-solid-svg-icons';
-import { action, computed, runInAction } from "mobx";
+import { action, computed, runInAction, trace } from "mobx";
 import { observer } from "mobx-react";
 import * as rp from "request-promise";
 import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc";
@@ -601,6 +601,39 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         return (showTitle ? 25 : 0) + 1;
     }
 
+    childScaling = () => (this.props.Document.fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling());
+    @computed get contents() {
+        return (<DocumentContentsView ContainingCollectionView={this.props.ContainingCollectionView}
+            ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+            Document={this.props.Document}
+            fitToBox={this.props.fitToBox}
+            addDocument={this.props.addDocument}
+            removeDocument={this.props.removeDocument}
+            moveDocument={this.props.moveDocument}
+            ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+            renderDepth={this.props.renderDepth}
+            showOverlays={this.props.showOverlays}
+            ContentScaling={this.childScaling}
+            ruleProvider={this.props.ruleProvider}
+            PanelWidth={this.props.PanelWidth}
+            PanelHeight={this.props.PanelHeight}
+            focus={this.props.focus}
+            parentActive={this.props.parentActive}
+            whenActiveChanged={this.props.whenActiveChanged}
+            bringToFront={this.props.bringToFront}
+            addDocTab={this.props.addDocTab}
+            pinToPres={this.props.pinToPres}
+            zoomToScale={this.props.zoomToScale}
+            backgroundColor={this.props.backgroundColor}
+            animateBetweenIcon={this.props.animateBetweenIcon}
+            getScale={this.props.getScale}
+            ChromeHeight={this.chromeHeight}
+            isSelected={this.isSelected}
+            select={this.select}
+            onClick={this.onClickHandler}
+            layoutKey="layout"
+            DataDoc={this.props.DataDoc} />);
+    }
     render() {
         const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined;
         const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined;
@@ -610,8 +643,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             this.props.backgroundColor(this.Document) || StrCast(this.layoutDoc.backgroundColor) :
             ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document);
 
-        const nativeWidth = this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%";
-        const nativeHeight = this.Document.ignoreAspect || this.props.Document.fitWidth ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : nativeWidth !== "100%" ? nativeWidth : "100%";
+        const nativeWidth = this.props.Document.fitWidth ? this.props.PanelWidth() : this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%";
+        const nativeHeight = this.props.Document.fitWidth ? this.props.PanelHeight() : this.Document.ignoreAspect || this.props.Document.fitWidth ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : nativeWidth !== "100%" ? nativeWidth : "100%";
         const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined;
         const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.getLayoutPropStr("showTitle");
         const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.getLayoutPropStr("showCaption");
@@ -645,13 +678,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     SetValue={(value: string) => (Doc.GetProto(this.Document)[showTitle] = value) ? true : true}
                 />
             </div>);
-        const contents = (<DocumentContentsView {...this.props}
-            ChromeHeight={this.chromeHeight}
-            isSelected={this.isSelected}
-            select={this.select}
-            onClick={this.onClickHandler}
-            layoutKey={"layout"}
-            DataDoc={this.props.DataDoc} />);
         return (
             <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
@@ -666,7 +692,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     background: backgroundColor,
                     width: nativeWidth,
                     height: nativeHeight,
-                    transform: `scale(${this.props.ContentScaling()})`,
+                    transform: `scale(${this.props.Document.fitWidth ? 1 : this.props.ContentScaling()})`,
                     opacity: this.Document.opacity
                 }}
                 onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
@@ -675,15 +701,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 {!showTitle && !showCaption ?
                     this.Document.searchFields ?
                         (<div className="documentView-searchWrapper">
-                            {contents}
+                            {this.contents}
                             {searchHighlight}
                         </div>)
                         :
-                        contents
+                        this.contents
                     :
                     <div className="documentView-styleWrapper" >
                         <div className="documentView-styleContentWrapper" style={{ height: showTextTitle ? "calc(100% - 29px)" : "100%", top: showTextTitle ? "29px" : undefined }}>
-                            {contents}
+                            {this.contents}
                         </div>
                         {titleView}
                         {captionView}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3014af944..3ad0b4010 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -35,6 +35,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     private _scriptValue: string = "";
     private _searchString: string = "";
     private _isChildActive = false;
+    private _everActive = false; // has this box ever had its contents activated -- if so, stop drawing the overlay title
     private _pdfViewer: PDFViewer | undefined;
     private _keyRef: React.RefObject<HTMLInputElement> = React.createRef();
     private _valueRef: React.RefObject<HTMLInputElement> = React.createRef();
@@ -176,20 +177,25 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
 
         ContextMenu.Instance.addItem({ description: "Pdf Funcs...", subitems: funcs, icon: "asterisk" });
     }
-
     render() {
         const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
         let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.active ? "" : "-interactive");
-        return (!(pdfUrl instanceof PdfField) || !this._pdf || this.props.ScreenToLocalTransform().Scale > 6 ?
+        let noPdf = !(pdfUrl instanceof PdfField) || !this._pdf;
+        if (!noPdf && (this.props.isSelected() || this.props.ScreenToLocalTransform().Scale < 2.5)) this._everActive = true;
+        return (!this._everActive ?
             <div className="pdfBox-title-outer"><div className="pdfBox-title-cont" >
                 <strong className="pdfBox-title" >{` ${this.props.Document.title}`}</strong> </div></div> :
-            <div className={classname} onContextMenu={this.specificContextMenu} onPointerDown={(e: React.PointerEvent) => {
+            <div className={classname} style={{
+                transformOrigin: "top left", width: this.props.Document.fitWidth ? `${100 / this.props.ContentScaling()}%` : undefined,
+                height: this.props.Document.fitWidth ? `${100 / this.props.ContentScaling()}%` : undefined,
+                transform: `scale(${this.props.Document.fitWidth ? this.props.ContentScaling() : 1})`
+            }} onContextMenu={this.specificContextMenu} onPointerDown={(e: React.PointerEvent) => {
                 let hit = document.elementFromPoint(e.clientX, e.clientY);
                 if (hit && hit.localName === "span" && this.props.isSelected()) {  // drag selecting text stops propagation
                     e.button === 0 && e.stopPropagation();
                 }
             }}>
-                <PDFViewer {...this.props} pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} loaded={this.loaded}
+                <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={this.loaded}
                     setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView}
                     renderDepth={this.props.renderDepth} PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth}
                     Document={this.props.Document} DataDoc={this.dataDoc} ContentScaling={this.props.ContentScaling}
@@ -197,7 +203,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
                     pinToPres={this.props.pinToPres} addDocument={this.props.addDocument}
                     ScreenToLocalTransform={this.props.ScreenToLocalTransform} select={this.props.select}
                     isSelected={this.props.isSelected} whenActiveChanged={this.whenActiveChanged}
-                    fieldKey={this.props.fieldKey} fieldExtensionDoc={this.extensionDoc} />
+                    fieldKey={this.props.fieldKey} fieldExtensionDoc={this.extensionDoc} startupLive={this.props.ScreenToLocalTransform().Scale < 2.5 ? true : false} />
                 {this.settingsPanel()}
             </div>);
     }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 3bf53340b..91a8cbf9f 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -41,6 +41,7 @@ interface IViewerProps {
     PanelHeight: () => number;
     ContentScaling: () => number;
     select: (isCtrlPressed: boolean) => void;
+    startupLive: boolean;
     renderDepth: number;
     isSelected: () => boolean;
     loaded: (nw: number, nh: number, np: number) => void;
@@ -75,6 +76,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     @observable private _zoomed = 1;
 
     public pdfViewer: any;
+    private _retries = 0; // number of times tried to create the PDF viewer 
     private _isChildActive = false;
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean) => void);
     private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
@@ -84,7 +86,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
     private _filterReactionDisposer?: IReactionDisposer;
     private _viewer: React.RefObject<HTMLDivElement> = React.createRef();
     private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
-    private _marquee: React.RefObject<HTMLDivElement> = React.createRef();
     private _selectionText: string = "";
     private _startX: number = 0;
     private _startY: number = 0;
@@ -106,7 +107,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         // file address of the pdf
         this._coverPath = JSON.parse(await rp.get(Utils.prepend(`/thumbnail${this.props.url.substring("files/".length, this.props.url.length - ".pdf".length)}-${NumCast(this.props.Document.curPage, 1)}.PNG`)));
         runInAction(() => this._showWaiting = this._showCover = true);
-        this._selectionReactionDisposer = reaction(() => this.props.isSelected(), () => this.setupPdfJsViewer());
+        this._selectionReactionDisposer = reaction(() => this.props.isSelected(), () => this.setupPdfJsViewer(), { fireImmediately: this.props.startupLive });
         this._reactionDisposer = reaction(
             () => this.props.Document.scrollY,
             (scrollY) => {
@@ -199,6 +200,17 @@ export class PDFViewer extends React.Component<IViewerProps> {
             this.gotoPage(NumCast(this.props.Document.curPage, 1));
         }));
         document.addEventListener("pagerendered", action(() => this._showCover = this._showWaiting = false));
+        this.createPdfViewer();
+    }
+
+    createPdfViewer() {
+        if (!this._mainCont.current) {
+            if (this._retries < 5) {
+                this._retries++;
+                setTimeout(() => this.createPdfViewer(), 1000);
+            }
+            return;
+        }
         var pdfLinkService = new PDFJSViewer.PDFLinkService();
         let pdfFindController = new PDFJSViewer.PDFFindController({
             linkService: pdfLinkService,
@@ -664,7 +676,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
     marqueeY = () => this._marqueeY;
     marqueeing = () => this._marqueeing;
     render() {
-        trace();
         return (<div className={"pdfViewer-viewer" + (this._zoomed !== 1 ? "-zoomed" : "")} onScroll={this.onScroll} onWheel={this.onZoomWheel} onPointerDown={this.onPointerDown} onClick={this.onClick} ref={this._mainCont}>
             {this.pdfViewerDiv}
             <PdfViewerMarquee isMarqueeing={this.marqueeing} width={this.marqueeWidth} height={this.marqueeHeight} x={this.marqueeX} y={this.marqueeY} />
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 4a03fed08..a68692732 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -712,6 +712,7 @@ export namespace Doc {
 }
 Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; });
 Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); });
+Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); });
 Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); });
 Scripting.addGlobal(function aliasDocs(field: any) { return new List<Doc>(field.map((d: any) => Doc.MakeAlias(d))); });
 Scripting.addGlobal(function docList(field: any) { return DocListCast(field); });
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2

