From ecd6d50cf6dd89f7d860096037efee81230eb535 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 7 Jun 2019 19:42:52 -0400
Subject: from last

---
 .../views/collections/CollectionTreeView.tsx       | 188 +++++++++++++++------
 1 file changed, 137 insertions(+), 51 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 9fb1da716..8dc10bcd1 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -6,7 +6,7 @@ import { observer } from "mobx-react";
 import { Doc, DocListCast } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { Document, listSpec } from '../../../new_fields/Schema';
-import { BoolCast, Cast, NumCast, StrCast } from '../../../new_fields/Types';
+import { BoolCast, Cast, NumCast, StrCast, PromiseValue } from '../../../new_fields/Types';
 import { Docs } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
@@ -19,6 +19,7 @@ import { CollectionDockingView } from './CollectionDockingView';
 import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import React = require("react");
+import { Transform } from '../../util/Transform';
 
 
 export interface TreeViewProps {
@@ -27,6 +28,10 @@ export interface TreeViewProps {
     moveDocument: DragManager.MoveFunction;
     dropAction: "alias" | "copy" | undefined;
     addDocTab: (doc: Doc, where: string) => void;
+    addDocument: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
+    ScreenToLocalTransform: () => Transform;
+    treeViewId: string;
+    parentKey: string;
 }
 
 export enum BulletType {
@@ -45,23 +50,49 @@ library.add(faCaretRight);
  * Component that takes in a document prop and a boolean whether it's collapsed or not.
  */
 class TreeView extends React.Component<TreeViewProps> {
+    private _header?: React.RefObject<HTMLDivElement> = React.createRef();
+    private treedropDisposer?: DragManager.DragDropDisposer;
+    protected createTreeDropTarget = (ele: HTMLDivElement) => {
+        this.treedropDisposer && this.treedropDisposer();
+        if (ele) {
+            this.treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } });
+        }
+    }
 
+    @observable _isOver: boolean = false;
     @observable _collapsed: boolean = true;
 
     @undoBatch delete = () => this.props.deleteDoc(this.props.document);
+    @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight");
+
+    @action onMouseEnter = () => { this._isOver = true; }
+    @action onMouseLeave = () => { this._isOver = false; }
 
-    @undoBatch openRight = async () => {
-        if (this.props.document.dockingConfig) {
-            MainView.Instance.openWorkspace(this.props.document);
-        } else {
-            this.props.addDocTab(this.props.document, "openRight");
+    onPointerEnter = (e: React.PointerEvent): void => {
+        this.props.document.libraryBrush = true;
+        if (e.buttons === 1) {
+            this._header!.current!.className = "treeViewItem-header";
+            document.addEventListener("pointermove", this.onDragMove, true);
         }
     }
-
-    get children() {
-        return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed?    .filter(doc => FieldValue(doc));
+    onPointerLeave = (e: React.PointerEvent): void => {
+        this.props.document.libraryBrush = false;
+        this._header!.current!.className = "treeViewItem-header";
+        document.removeEventListener("pointermove", this.onDragMove, true);
+    }
+    onDragMove = (e: PointerEvent): void => {
+        this.props.document.libraryBrush = false;
+        let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+        let rect = this._header!.current!.getBoundingClientRect();
+        let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+        let before = x[1] < bounds[1];
+        let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible);
+        this._header!.current!.className = "treeViewItem-header"
+        if (inside && this._bulletType != BulletType.List) this._header!.current!.className = "treeViewItem-header-inside";
+        else if (before) this._header!.current!.className = "treeViewItem-header-above";
+        else if (!before) this._header!.current!.className = "treeViewItem-header-below";
+        e.stopPropagation();
     }
-
     onPointerDown = (e: React.PointerEvent) => {
         e.stopPropagation();
     }
@@ -69,19 +100,17 @@ class TreeView extends React.Component<TreeViewProps> {
     @action
     remove = (document: Document, key: string) => {
         let children = Cast(this.props.document[key], listSpec(Doc), []);
-        if (children) {
-            children.splice(children.indexOf(document), 1);
-        }
+        children.indexOf(document) !== -1 && children.splice(children.indexOf(document), 1);
     }
 
     @action
-    move: DragManager.MoveFunction = (document, target, addDoc) => {
-        if (this.props.document === target) {
-            return true;
+    move: DragManager.MoveFunction = (document: Doc, target: Doc, addDoc) => {
+        if (this.props.document !== target) {
+            //TODO This should check if it was removed
+            this.props.deleteDoc(document);
+            return addDoc(document);
         }
-        //TODO This should check if it was removed
-        this.remove(document, "data");
-        return addDoc(document);
+        return true;
     }
 
     renderBullet(type: BulletType) {
@@ -93,22 +122,12 @@ class TreeView extends React.Component<TreeViewProps> {
         }
         return <div className="bullet" onClick={onClicked}>{bullet ? <FontAwesomeIcon icon={bullet} /> : ""} </div>;
     }
-
-    @action
-    onMouseEnter = () => {
-        this._isOver = true;
-    }
-    @observable _isOver: boolean = false;
-    @action
-    onMouseLeave = () => {
-        this._isOver = false;
-    }
     /**
      * Renders the EditableView title element for placement into the tree.
      */
     renderTitle() {
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.dropAction);
+        let onItemDown = SetupDrag(reference, () => this.props.document, this.move, this.props.dropAction, this.props.treeViewId, true);
         let editableView = (titleString: string) =>
             (<EditableView
                 oneLine={!this._isOver ? true : false}
@@ -129,9 +148,9 @@ class TreeView extends React.Component<TreeViewProps> {
                 {/* <FontAwesomeIcon icon="angle-right" size="lg" /> */}
             </div>);
         return (
-            <div className="docContainer" ref={reference} onPointerDown={onItemDown} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
+            <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
                 style={{ background: BoolCast(this.props.document.protoBrush, false) ? "#06123232" : BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0" }}
-                onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+            >
                 {editableView(StrCast(this.props.document.title))}
                 {openRight}
                 {/* {<div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>} */}
@@ -152,14 +171,51 @@ class TreeView extends React.Component<TreeViewProps> {
             } else {
                 ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)) });
             }
-            ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
+            ContextMenu.Instance.displayMenu(e.pageX - 156, e.pageY - 15);
+            e.stopPropagation();
+        }
+    }
+    treeDrop = (e: Event, de: DragManager.DropEvent) => {
+        let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
+        let rect = this._header!.current!.getBoundingClientRect();
+        let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+        let before = x[1] < bounds[1];
+        let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible);
+        if (de.data instanceof DragManager.DocumentDragData) {
+            let addDoc = (doc: Doc) => this.props.addDocument(doc, this.props.document, before);
+            if (inside) {
+                let docList = Cast(this.props.document.data, listSpec(Doc));
+                if (docList !== undefined) {
+                    addDoc = (doc: Doc) => { docList && docList.push(doc); return true; }
+                }
+            }
+            let added = false;
+            if (de.data.dropAction || de.data.userDropAction) {
+                added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.props.document, before) || added, false);
+            } else if (de.data.moveDocument) {
+                let movedDocs = de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments;
+                added = movedDocs.reduce((added: boolean, d) =>
+                    de.data.moveDocument(d, this.props.document, addDoc) || added, false);
+            } else {
+                added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.props.document, before), false);
+            }
             e.stopPropagation();
+            return added;
         }
+        return false;
     }
 
-    onPointerEnter = (e: React.PointerEvent): void => { this.props.document.libraryBrush = true; };
-    onPointerLeave = (e: React.PointerEvent): void => { this.props.document.libraryBrush = false; };
+    public static AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean) {
+        let list = Cast(target[key], listSpec(Doc));
+        if (list) {
+            let ind = relativeTo ? list.indexOf(relativeTo) : -1;
+            if (ind === -1) list.push(doc);
+            else list.splice(before ? ind : ind + 1, 0, doc);
+        }
+        return true;
+    }
 
+    _bulletType: BulletType = BulletType.List;
     render() {
         let bulletType = BulletType.List;
         let contentElement: (JSX.Element | null)[] = [];
@@ -170,16 +226,17 @@ class TreeView extends React.Component<TreeViewProps> {
         }
         keys.map(key => {
             let docList = DocListCast(this.props.document[key]);
+            let remDoc = (doc: Doc) => this.remove(doc, key);
+            let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, key, doc, addBefore, before);
             let doc = Cast(this.props.document[key], Doc);
             if (doc instanceof Doc || docList.length) {
                 if (!this._collapsed) {
                     bulletType = BulletType.Collapsible;
-                    let spacing = (key === "data") ? 0 : -10;
                     contentElement.push(<ul key={key + "more"}>
                         {(key === "data") ? (null) :
                             <span className="collectionTreeView-keyHeader" style={{ display: "block", marginTop: "7px" }} key={key}>{key}</span>}
-                        <div style={{ display: "block", marginTop: `${spacing}px` }}>
-                            {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction, this.props.addDocTab)}
+                        <div style={{ display: "block" }}>
+                            {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, this.props.treeViewId, key, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform)}
                         </div>
                     </ul >);
                 } else {
@@ -187,29 +244,52 @@ class TreeView extends React.Component<TreeViewProps> {
                 }
             }
         });
+        this._bulletType = bulletType;
         return <div className="treeViewItem-container"
+            ref={this.createTreeDropTarget}
             onContextMenu={this.onWorkspaceContextMenu}>
             <li className="collection-child">
-                {this.renderBullet(bulletType)}
-                {this.renderTitle()}
+                <div className="treeViewItem-header" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+                    {this.renderBullet(bulletType)}
+                    {this.renderTitle()}
+                </div>
                 {contentElement}
             </li>
         </div>;
     }
-    public static GetChildElements(docs: Doc[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType, addDocTab: (doc: Doc, where: string) => void) {
-        return docs.filter(child => !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).map(child =>
-            <TreeView document={child} key={child[Id]} deleteDoc={remove} moveDocument={move} dropAction={dropAction} addDocTab={addDocTab} />);
+    public static GetChildElements(
+        docs: Doc[],
+        treeViewId: string,
+        key: string,
+        add: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean,
+        remove: ((doc: Doc) => void),
+        move: DragManager.MoveFunction,
+        dropAction: dropActionType,
+        addDocTab: (doc: Doc, where: string) => void,
+        screenToLocalXf: () => Transform
+    ) {
+        return docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized)).map(child =>
+            <TreeView document={child} treeViewId={treeViewId} key={child[Id]} deleteDoc={remove} addDocument={add} moveDocument={move}
+                dropAction={dropAction} addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} parentKey={key} />);
     }
 }
 
 @observer
 export class CollectionTreeView extends CollectionSubView(Document) {
+    private treedropDisposer?: DragManager.DragDropDisposer;
+    protected createTreeDropTarget = (ele: HTMLDivElement) => {
+        if (this.treedropDisposer) {
+            this.treedropDisposer();
+        }
+        if (ele) {
+            this.treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
+        }
+    }
+
     @action
     remove = (document: Document) => {
-        let children = Cast(this.props.Document.data, listSpec(Doc), []);
-        if (children) {
-            children.splice(children.indexOf(document), 1);
-        }
+        let children = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []);
+        children.indexOf(document) !== -1 && children.splice(children.indexOf(document), 1);
     }
     onContextMenu = (e: React.MouseEvent): void => {
         // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
@@ -218,20 +298,26 @@ export class CollectionTreeView extends CollectionSubView(Document) {
             ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)) });
         }
     }
+
+    onTreeDrop = (e: React.DragEvent) => {
+        this.onDrop(e, {});
+    }
     render() {
-        trace();
-        let dropAction = StrCast(this.props.Document.dropAction, "alias") as dropActionType;
+        let dropAction = Cast(this.props.Document.dropAction, "string") as dropActionType;
         if (!this.childDocs) {
             return (null);
         }
-        let childElements = TreeView.GetChildElements(this.childDocs, false, this.remove, this.props.moveDocument, dropAction, this.props.addDocTab);
+        let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
+        let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
+        let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform);
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
                 style={{ borderRadius: "inherit" }}
                 onContextMenu={this.onContextMenu}
                 onWheel={(e: React.WheelEvent) => this.props.isSelected() && e.stopPropagation()}
-                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
+                onDrop={this.onTreeDrop}
+                ref={this.createTreeDropTarget}>
                 <div className="coll-title">
                     <EditableView
                         contents={this.props.Document.title}
-- 
cgit v1.2.3-70-g09d2


From c56851026c4054cde26ea36a9a24db14fac6c49c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 10 Jun 2019 13:03:47 -0400
Subject: fixes for treeview highlighting, templates, field deletion,
 overlaytext box positioning

---
 src/Utils.ts                                       |  2 +-
 src/client/util/DragManager.ts                     |  6 ++++--
 src/client/util/SelectionManager.ts                |  9 +++++---
 src/client/views/MainOverlayTextBox.tsx            |  8 +++++---
 src/client/views/Templates.tsx                     | 16 ++++-----------
 .../views/collections/CollectionTreeView.tsx       | 24 ++++++++++++++--------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  3 +--
 src/client/views/nodes/DocumentView.tsx            |  6 +++---
 src/new_fields/util.ts                             |  4 ++--
 9 files changed, 42 insertions(+), 36 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index 611c61135..e8a80bdc3 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -15,7 +15,7 @@ export class Utils {
         return v5(seed, v5.URL);
     }
 
-    public static GetScreenTransform(ele: HTMLElement): { scale: number, translateX: number, translateY: number } {
+    public static GetScreenTransform(ele?: HTMLElement): { scale: number, translateX: number, translateY: number } {
         if (!ele) {
             return { scale: 1, translateX: 1, translateY: 1 };
         }
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4c9f798a8..8ee1ad2af 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,9 +1,10 @@
-import { action, runInAction } from "mobx";
+import { action, runInAction, observable } from "mobx";
 import { Doc, DocListCastAsync } from "../../new_fields/Doc";
 import { Cast } from "../../new_fields/Types";
 import { emptyFunction } from "../../Utils";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import * as globalCssVariables from "../views/globalCssVariables.scss";
+import { SelectionManager } from "./SelectionManager";
 
 export type dropActionType = "alias" | "copy" | undefined;
 export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () => Doc | Promise<Doc>, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) {
@@ -194,7 +195,7 @@ export namespace DragManager {
             dragDiv.style.pointerEvents = "none";
             DragManager.Root().appendChild(dragDiv);
         }
-
+        SelectionManager.SetIsDragging(true);
         let scaleXs: number[] = [];
         let scaleYs: number[] = [];
         let xs: number[] = [];
@@ -293,6 +294,7 @@ export namespace DragManager {
         };
 
         let hideDragElements = () => {
+            SelectionManager.SetIsDragging(false);
             dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement));
             eles.map(ele => (ele.hidden = false));
         };
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 0e22d576c..ddad4b818 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,4 +1,4 @@
-import { observable, action } from "mobx";
+import { observable, action, runInAction } from "mobx";
 import { Doc } from "../../new_fields/Doc";
 import { DocumentView } from "../views/nodes/DocumentView";
 import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
@@ -6,8 +6,8 @@ import { NumCast } from "../../new_fields/Types";
 
 export namespace SelectionManager {
     class Manager {
-        @observable
-        SelectedDocuments: Array<DocumentView> = [];
+        @observable IsDragging: boolean = false;
+        @observable SelectedDocuments: Array<DocumentView> = [];
 
         @action
         SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
@@ -51,6 +51,9 @@ export namespace SelectionManager {
         if (found) manager.SelectDoc(found, false);
     }
 
+    export function SetIsDragging(dragging: boolean) { runInAction(() => manager.IsDragging = dragging); }
+    export function GetIsDragging() { return manager.IsDragging; }
+
     export function SelectedDocuments(): Array<DocumentView> {
         return manager.SelectedDocuments;
     }
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 6bbd70a25..0eb3e9707 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -1,7 +1,7 @@
 import { action, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { emptyFunction, returnTrue, returnZero } from '../../Utils';
+import { emptyFunction, returnTrue, returnZero, Utils } from '../../Utils';
 import { DragManager } from '../util/DragManager';
 import { Transform } from '../util/Transform';
 import "normalize.css";
@@ -29,7 +29,8 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
         MainOverlayTextBox.Instance = this;
         reaction(() => FormattedTextBox.InputBoxOverlay,
             (box?: FormattedTextBox) => {
-                if (box) this.setTextDoc(box.props.fieldKey, box.CurrentDiv, box.props.ScreenToLocalTransform);
+                let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined);
+                if (box) this.setTextDoc(box.props.fieldKey, box.CurrentDiv, () => new Transform(-sxf.translateX, -sxf.translateY, 1 / sxf.scale));
                 else this.setTextDoc();
             });
     }
@@ -93,9 +94,10 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
         if (FormattedTextBox.InputBoxOverlay && this._textTargetDiv) {
             let textRect = this._textTargetDiv.getBoundingClientRect();
             let s = this._textXf().Scale;
+            let auto = FormattedTextBox.InputBoxOverlay.props.height;
             return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${textRect.left}px, ${textRect.top}px) scale(${1 / s},${1 / s})`, width: "auto", height: "auto" }} >
                 <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll}
-                    style={{ width: `${textRect.width * s}px`, height: `${textRect.height * s}px` }}>
+                    style={{ width: `${textRect.width * s}px`, height: auto ? "auto" : `${textRect.height * s}px` }}>
                     <FormattedTextBox color={`${this._textColor}`} fieldKey={this._textFieldKey} hideOnLeave={this._textHideOnLeave} isOverlay={true} Document={FormattedTextBox.InputBoxOverlay.props.Document} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
                         selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
                         ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} addDocTab={this.addDocTab} />
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index 8943bbcaf..3cd525afa 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -41,21 +41,13 @@ export namespace Templates {
 
     export const Caption = new Template("Caption", TemplatePosition.OutterBottom,
         `<div>
-            <div style="height:100%; width:100%;position:absolute;">{layout}</div>
+            <div style="height:100%; width:100%;">{layout}</div>
             <div style="bottom: 0; font-size:14px; width:100%; position:absolute">
-                <FormattedTextBox {...props} fieldKey={"caption"} hideOnLeave={"true"} />
+                <FormattedTextBox {...props} height="min-content" fieldKey={"caption"} hideOnLeave={"true"} />
             </div>
         </div>` );
 
-    export const ImageTitle = new Template("Image Title", TemplatePosition.InnerTop,
-        `<div style="height:100%">
-            <div style="height:100%; width:100%;position:absolute;">{layout}</div>
-            <div style="height:25px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .4); color: white; ">
-                <span style="text-align:center;width:100%;font-size:20px;position:absolute;overflow:hidden;white-space:nowrap;text-overflow:ellipsis">{props.Document.title}</span>
-            </div>
-        </div>` );
-
-    export const TextTitle = new Template("Text Title", TemplatePosition.InnerTop,
+    export const Title = new Template("Title", TemplatePosition.InnerTop,
         `<div style="height:100%">
             <div style="height:25px; width:100%; background-color: rgba(0, 0, 0, .4); color: white; ">
                 <span style="text-align:center;width:100%;font-size:20px;position:absolute;overflow:hidden;white-space:nowrap;text-overflow:ellipsis">{props.Document.title}</span>
@@ -92,7 +84,7 @@ export namespace Templates {
             </div > `);
     }
 
-    export const TemplateList: Template[] = [TextTitle, Header, ImageTitle, Caption, Bullet];
+    export const TemplateList: Template[] = [Title, Header, Caption, Bullet];
 
     export function sortTemplates(a: Template, b: Template) {
         if (a.Position < b.Position) { return -1; }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8dc10bcd1..8a6764c58 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -20,6 +20,7 @@ import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import React = require("react");
 import { Transform } from '../../util/Transform';
+import { SelectionManager } from '../../util/SelectionManager';
 
 
 export interface TreeViewProps {
@@ -32,6 +33,7 @@ export interface TreeViewProps {
     ScreenToLocalTransform: () => Transform;
     treeViewId: string;
     parentKey: string;
+    active: () => boolean;
 }
 
 export enum BulletType {
@@ -69,7 +71,7 @@ class TreeView extends React.Component<TreeViewProps> {
     @action onMouseLeave = () => { this._isOver = false; }
 
     onPointerEnter = (e: React.PointerEvent): void => {
-        this.props.document.libraryBrush = true;
+        this.props.active() && (this.props.document.libraryBrush = true);
         if (e.buttons === 1) {
             this._header!.current!.className = "treeViewItem-header";
             document.addEventListener("pointermove", this.onDragMove, true);
@@ -149,7 +151,10 @@ class TreeView extends React.Component<TreeViewProps> {
             </div>);
         return (
             <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
-                style={{ background: BoolCast(this.props.document.protoBrush, false) ? "#06123232" : BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0" }}
+                style={{
+                    background: BoolCast(this.props.document.protoBrush, false) ? "#06123232" : BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0",
+                    pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none"
+                }}
             >
                 {editableView(StrCast(this.props.document.title))}
                 {openRight}
@@ -225,18 +230,19 @@ class TreeView extends React.Component<TreeViewProps> {
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
         keys.map(key => {
-            let docList = DocListCast(this.props.document[key]);
+            let docList = Cast(this.props.document[key], listSpec(Doc));
             let remDoc = (doc: Doc) => this.remove(doc, key);
             let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, key, doc, addBefore, before);
             let doc = Cast(this.props.document[key], Doc);
-            if (doc instanceof Doc || docList.length) {
+            if (doc instanceof Doc || docList) {
                 if (!this._collapsed) {
                     bulletType = BulletType.Collapsible;
                     contentElement.push(<ul key={key + "more"}>
                         {(key === "data") ? (null) :
                             <span className="collectionTreeView-keyHeader" style={{ display: "block", marginTop: "7px" }} key={key}>{key}</span>}
                         <div style={{ display: "block" }}>
-                            {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, this.props.treeViewId, key, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform)}
+                            {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move,
+                                this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active)}
                         </div>
                     </ul >);
                 } else {
@@ -266,11 +272,12 @@ class TreeView extends React.Component<TreeViewProps> {
         move: DragManager.MoveFunction,
         dropAction: dropActionType,
         addDocTab: (doc: Doc, where: string) => void,
-        screenToLocalXf: () => Transform
+        screenToLocalXf: () => Transform,
+        active: () => boolean
     ) {
         return docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized)).map(child =>
             <TreeView document={child} treeViewId={treeViewId} key={child[Id]} deleteDoc={remove} addDocument={add} moveDocument={move}
-                dropAction={dropAction} addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} parentKey={key} />);
+                dropAction={dropAction} addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} parentKey={key} active={active} />);
     }
 }
 
@@ -309,7 +316,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         }
         let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
         let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
-        let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform);
+        let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove,
+            moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active);
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d23bef2d3..63f24ff53 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -6,7 +6,6 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField";
 import { createSchema, makeInterface } from "../../../../new_fields/Schema";
 import { BoolCast, Cast, FieldValue, NumCast } from "../../../../new_fields/Types";
 import { emptyFunction, returnOne } from "../../../../Utils";
-import { DocServer } from "../../../DocServer";
 import { DocumentManager } from "../../../util/DocumentManager";
 import { DragManager } from "../../../util/DragManager";
 import { HistoryUtil } from "../../../util/History";
@@ -26,7 +25,6 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import v5 = require("uuid/v5");
-import { Docs } from "../../../documents/Documents";
 
 export const panZoomSchema = createSchema({
     panX: "number",
@@ -218,6 +216,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     @action
     setPan(panX: number, panY: number) {
+
         this.props.Document.panTransformType = "None";
         var scale = this.getLocalTransform().inverse().Scale;
         const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2ac6d12bf..19f5c7d36 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -349,9 +349,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 dst.nativeHeight = src.nativeHeight;
             }
             else {
-                const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
-                const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView);
-                DocUtils.MakeLink(sourceDoc, destDoc, views.length ? views[0].props.Document : undefined);
+                // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
+                // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView);
+                DocUtils.MakeLink(sourceDoc, destDoc, this.props.ContainingCollectionView ? this.props.ContainingCollectionView.props.Document : undefined);
                 de.data.droppedDocuments.push(destDoc);
             }
         }
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index fe0da2e7a..8cb1db953 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -6,7 +6,7 @@ import { FieldValue } from "./Types";
 import { RefField } from "./RefField";
 import { ObjectField } from "./ObjectField";
 import { action } from "mobx";
-import { Parent, OnUpdate, Update, Id } from "./FieldSymbols";
+import { Parent, OnUpdate, Update, Id, SelfProxy } from "./FieldSymbols";
 import { ComputedField } from "../fields/ScriptField";
 
 export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
@@ -86,7 +86,7 @@ export function deleteProperty(target: any, prop: string | number | symbol) {
         delete target[prop];
         return true;
     }
-    target[prop] = undefined;
+    target[SelfProxy][prop] = undefined;
     return true;
 }
 
-- 
cgit v1.2.3-70-g09d2


From 6763fc89d2ba9782d88a7677661dbe5ae27ee097 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 15 Jun 2019 21:41:29 -0400
Subject: several fixes to tree view

---
 .../views/collections/CollectionTreeView.scss      | 30 ++++++++--------------
 .../views/collections/CollectionTreeView.tsx       | 16 +++++++-----
 2 files changed, 21 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 2dc4b2e80..2568bf182 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -25,12 +25,10 @@
     }
 
     .bullet {
-        float: left;
         position: relative;
         width: 15px;
-        display: block;
         color: $intermediate-color;
-        margin-top: 8px;
+        margin-top: 4px;
         transform: scale(1.3, 1.3);
     }
     .editableView-container {
@@ -46,13 +44,6 @@
     }
 
 
-    .docContainer:hover {
-        .delete-button {
-            display: inline;
-            // width: auto;
-        }
-    }
-
     .coll-title {
         width: max-content;
         display: block;
@@ -66,23 +57,23 @@
 }
 
 .docContainer {
-    margin-left: 10px;
-    display: block;
+    position: relative;
+    text-overflow: ellipsis;
+    white-space: pre-wrap;
+    overflow: hidden;
     // width:100%;//width: max-content;
 
-    .treeViewItem-openRight {
-        margin-left: 5px;
-        display: none;
-    }
 }
-#docContainer-data {
-    margin-top: 5px;
+.treeViewItem-openRight {
+    display: none;
 }
 
-.docContainer:hover {
+.treeViewItem-header:hover {
     .treeViewItem-openRight {
         display: inline-block;
         height:13px;
+        margin-top:2px;
+        margin-left: 5px;
         // display: inline;
         svg {
             display:block;
@@ -94,6 +85,7 @@
 
 .treeViewItem-header {
     border: transparent 1px solid;
+    display:flex;
 }
 .treeViewItem-header-above {
     border: transparent 1px solid;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8a6764c58..65b364c47 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -149,7 +149,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 <FontAwesomeIcon icon="angle-right" size="lg" />
                 {/* <FontAwesomeIcon icon="angle-right" size="lg" /> */}
             </div>);
-        return (
+        return <>
             <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
                 style={{
                     background: BoolCast(this.props.document.protoBrush, false) ? "#06123232" : BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0",
@@ -157,9 +157,10 @@ class TreeView extends React.Component<TreeViewProps> {
                 }}
             >
                 {editableView(StrCast(this.props.document.title))}
-                {openRight}
                 {/* {<div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>} */}
-            </div >);
+            </div >
+            {openRight}
+        </>;
     }
 
     onWorkspaceContextMenu = (e: React.MouseEvent): void => {
@@ -229,17 +230,20 @@ class TreeView extends React.Component<TreeViewProps> {
             keys.push(...Array.from(Object.keys(this.props.document.proto)));
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
+        if (keys.indexOf("data") !== -1) {
+            keys.splice(keys.indexOf("data"), 1);
+            keys.splice(0, 0, "data");
+        }
         keys.map(key => {
             let docList = Cast(this.props.document[key], listSpec(Doc));
             let remDoc = (doc: Doc) => this.remove(doc, key);
             let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, key, doc, addBefore, before);
             let doc = Cast(this.props.document[key], Doc);
-            if (doc instanceof Doc || docList) {
+            if (doc instanceof Doc || (docList && (DocListCast(docList).length > 0 || key === "data"))) {
                 if (!this._collapsed) {
                     bulletType = BulletType.Collapsible;
                     contentElement.push(<ul key={key + "more"}>
-                        {(key === "data") ? (null) :
-                            <span className="collectionTreeView-keyHeader" style={{ display: "block", marginTop: "7px" }} key={key}>{key}</span>}
+                        <span className="collectionTreeView-keyHeader" style={{ display: "block", marginTop: "7px" }} key={key}>{key}</span>
                         <div style={{ display: "block" }}>
                             {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move,
                                 this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active)}
-- 
cgit v1.2.3-70-g09d2


From c3b1877b4d17715416267ff3601cc982ca3b1535 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 15 Jun 2019 22:46:40 -0400
Subject: partial fix for dragging tree view items

---
 src/client/views/collections/CollectionTreeView.scss | 3 ---
 src/client/views/collections/CollectionTreeView.tsx  | 7 ++++---
 2 files changed, 4 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 2568bf182..f6df96d92 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -88,14 +88,11 @@
     display:flex;
 }
 .treeViewItem-header-above {
-    border: transparent 1px solid;
     border-top: black 1px solid;
 }
 .treeViewItem-header-below {
-    border: transparent 1px solid;
     border-bottom: black 1px solid;
 }
 .treeViewItem-header-inside {
-    border: transparent 1px solid;
     border: black 1px solid;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 65b364c47..809b2af2b 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -71,6 +71,7 @@ class TreeView extends React.Component<TreeViewProps> {
     @action onMouseLeave = () => { this._isOver = false; }
 
     onPointerEnter = (e: React.PointerEvent): void => {
+        console.log("ENTER =  " + this.props.document.title);
         this.props.active() && (this.props.document.libraryBrush = true);
         if (e.buttons === 1) {
             this._header!.current!.className = "treeViewItem-header";
@@ -90,9 +91,9 @@ class TreeView extends React.Component<TreeViewProps> {
         let before = x[1] < bounds[1];
         let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible);
         this._header!.current!.className = "treeViewItem-header"
-        if (inside && this._bulletType != BulletType.List) this._header!.current!.className = "treeViewItem-header-inside";
-        else if (before) this._header!.current!.className = "treeViewItem-header-above";
-        else if (!before) this._header!.current!.className = "treeViewItem-header-below";
+        if (inside && this._bulletType != BulletType.List) this._header!.current!.className += " treeViewItem-header-inside";
+        else if (before) this._header!.current!.className += " treeViewItem-header-above";
+        else if (!before) this._header!.current!.className += " treeViewItem-header-below";
         e.stopPropagation();
     }
     onPointerDown = (e: React.PointerEvent) => {
-- 
cgit v1.2.3-70-g09d2


From 19c3ffc07038e6d5f5dbaa1b789f2799a2958985 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 15 Jun 2019 23:08:07 -0400
Subject: from last

---
 src/client/views/collections/CollectionTreeView.tsx | 1 -
 1 file changed, 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 809b2af2b..659cb2f28 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -71,7 +71,6 @@ class TreeView extends React.Component<TreeViewProps> {
     @action onMouseLeave = () => { this._isOver = false; }
 
     onPointerEnter = (e: React.PointerEvent): void => {
-        console.log("ENTER =  " + this.props.document.title);
         this.props.active() && (this.props.document.libraryBrush = true);
         if (e.buttons === 1) {
             this._header!.current!.className = "treeViewItem-header";
-- 
cgit v1.2.3-70-g09d2


From 3a25bad918c72f5d6de9a720de9e0d316c00f2fe Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 18 Jun 2019 13:03:28 -0400
Subject: fixed issues with expanding text boxes that have a dynamic title

---
 src/client/views/MainOverlayTextBox.tsx             | 1 -
 src/client/views/collections/CollectionSubView.tsx  | 8 +-------
 src/client/views/collections/CollectionTreeView.tsx | 2 +-
 src/client/views/nodes/FormattedTextBox.tsx         | 4 ++--
 4 files changed, 4 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 4e983c906..0de880175 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -71,7 +71,6 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
     textScroll = (e: React.UIEvent) => {
         if (this._textProxyDiv.current && this._textTargetDiv) {
             this._textTargetDiv.scrollTop = (e as any)._targetInst.stateNode.scrollTop;
-            console.log(this._textTargetDiv.scrollTop + " != " + (e as any)._targetInst.stateNode.scrollTop + " != " + (this._textBox!.CurrentDiv ? this._textBox!.CurrentDiv.scrollTop : -1));
         }
     }
 
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 783f40d0a..e55cd9e37 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -36,9 +36,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
     class CollectionSubView extends DocComponent<SubCollectionViewProps, T>(schemaCtor) {
         private dropDisposer?: DragManager.DragDropDisposer;
         protected createDropTarget = (ele: HTMLDivElement) => {
-            if (this.dropDisposer) {
-                this.dropDisposer();
-            }
+            this.dropDisposer && this.dropDisposer();
             if (ele) {
                 this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
             }
@@ -96,10 +94,6 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 return added;
             }
             else if (de.data instanceof DragManager.AnnotationDragData) {
-                console.log("dropped!");
-                console.log(de.data);
-                // de.data.dropDocument.x = de.x;
-                // de.data.dropDocument.y = de.y;
                 return this.props.addDocument(de.data.dropDocument);
             }
             return false;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 659cb2f28..b13694e9d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -314,7 +314,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         this.onDrop(e, {});
     }
     render() {
-        let dropAction = Cast(this.props.Document.dropAction, "string") as dropActionType;
+        let dropAction = StrCast(this.props.Document.dropAction) as dropActionType;
         if (!this.childDocs) {
             return (null);
         }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index aa44995ca..36d902c4f 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,6 +1,6 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faEdit, faSmile } from '@fortawesome/free-solid-svg-icons';
-import { action, IReactionDisposer, observable, reaction } from "mobx";
+import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { baseKeymap } from "prosemirror-commands";
 import { history } from "prosemirror-history";
@@ -196,7 +196,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                         FormattedTextBox.InputBoxOverlay = this;
                         FormattedTextBox.InputBoxOverlayScroll = this._ref.current!.scrollTop;
                     }
-                });
+                }, { fireImmediately: true });
         }
 
         this._reactionDisposer = reaction(
-- 
cgit v1.2.3-70-g09d2


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

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

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

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


From 3b880d7b15b7107049ae27601b9f759b17f7fde9 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 18 Jun 2019 22:51:46 -0400
Subject: added initial keyboard shortcuts for adding and moving docs in
 TreeView.  fixed image drag bug.

---
 src/client/documents/Documents.ts                  |  3 +-
 src/client/views/EditableView.tsx                  | 34 +++++---
 .../views/collections/CollectionDockingView.tsx    |  1 +
 .../views/collections/CollectionTreeView.tsx       | 96 +++++++++++++++++-----
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 5 files changed, 103 insertions(+), 33 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 91d3707f6..fcd1010c6 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -51,7 +51,6 @@ export interface DocumentOptions {
     panY?: number;
     page?: number;
     scale?: number;
-    baseLayout?: string;
     layout?: string;
     templates?: List<string>;
     viewType?: number;
@@ -136,7 +135,7 @@ export namespace Docs {
     }
 
     function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Doc {
-        return Doc.assign(new Doc(protoId, true), { ...options, title: title, layout: layout, baseLayout: layout });
+        return Doc.assign(new Doc(protoId, true), { ...options, title: title, layout: layout });
     }
     function SetInstanceOptions<U extends Field>(doc: Doc, options: DocumentOptions, value: U) {
         const deleg = Doc.MakeDelegate(doc);
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index c946d68e1..a96fca464 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -18,13 +18,17 @@ export interface EditableProps {
 
     OnFillDown?(value: string): void;
 
+    OnTab?(): void;
+
     /**
      * The contents to render when not editing
      */
     contents: any;
+    fontStyle?: string;
     height?: number;
     display?: string;
     oneLine?: boolean;
+    editing?: boolean
 }
 
 /**
@@ -34,40 +38,48 @@ export interface EditableProps {
  */
 @observer
 export class EditableView extends React.Component<EditableProps> {
-    @observable
-    editing: boolean = false;
+    @observable _editing: boolean = false;
+
+    constructor(props: EditableProps) {
+        super(props);
+        this._editing = this.props.editing ? true : false;
+    }
 
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
-        if (e.key === "Enter") {
+        if (e.key === "Tab") {
+            this.props.OnTab && this.props.OnTab();
+        } else if (e.key === "Enter") {
             if (!e.ctrlKey) {
                 if (this.props.SetValue(e.currentTarget.value)) {
-                    this.editing = false;
+                    this._editing = false;
                 }
             } else if (this.props.OnFillDown) {
                 this.props.OnFillDown(e.currentTarget.value);
-                this.editing = false;
+                this._editing = false;
             }
         } else if (e.key === "Escape") {
-            this.editing = false;
+            this._editing = false;
         }
     }
 
     @action
     onClick = (e: React.MouseEvent) => {
-        this.editing = true;
+        this._editing = true;
         e.stopPropagation();
     }
 
     render() {
-        if (this.editing) {
-            return <input className="editableView-input" defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus onBlur={action(() => this.editing = false)}
+        if (this._editing) {
+            return <input className="editableView-input" defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus
+                onBlur={action(() => this._editing = false)}
                 style={{ display: this.props.display }} />;
         } else {
             return (
-                <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`} style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }}
+                <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`}
+                    style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }}
                     onClick={this.onClick} >
-                    <span>{this.props.contents}</span>
+                    <span style={{ fontStyle: this.props.fontStyle }}>{this.props.contents}</span>
                 </div>
             );
         }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f2b3528b8..bd3020a78 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -467,6 +467,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         let docHeight = NumCast(this._document!.height);
         if (NumCast(this._document!.nativeWidth) || !docWidth || !this._panelWidth || !this._panelHeight) return 1;
         if (StrCast(this._document!.layout).indexOf("Collection") === -1 ||
+            !BoolCast(this._document!.fitToContents, false) ||
             NumCast(this._document!.viewType) !== CollectionViewType.Freeform) return 1;
         let scaling = Math.max(1, this._panelWidth / docWidth * docHeight > this._panelHeight ?
             this._panelHeight / docHeight : this._panelWidth / docWidth);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b13694e9d..23efe9f79 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -21,6 +21,7 @@ import "./CollectionTreeView.scss";
 import React = require("react");
 import { Transform } from '../../util/Transform';
 import { SelectionManager } from '../../util/SelectionManager';
+import { emptyFunction } from '../../../Utils';
 
 
 export interface TreeViewProps {
@@ -30,6 +31,7 @@ export interface TreeViewProps {
     dropAction: "alias" | "copy" | undefined;
     addDocTab: (doc: Doc, where: string) => void;
     addDocument: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
+    indentDocument?: () => void;
     ScreenToLocalTransform: () => Transform;
     treeViewId: string;
     parentKey: string;
@@ -114,6 +116,12 @@ class TreeView extends React.Component<TreeViewProps> {
         }
         return true;
     }
+    @action
+    indent = () => {
+        this.props.addDocument(this.props.document);
+        this.delete();
+    }
+
 
     renderBullet(type: BulletType) {
         let onClicked = action(() => this._collapsed = !this._collapsed);
@@ -124,25 +132,37 @@ class TreeView extends React.Component<TreeViewProps> {
         }
         return <div className="bullet" onClick={onClicked}>{bullet ? <FontAwesomeIcon icon={bullet} /> : ""} </div>;
     }
+    static loadId = "";
+    editableView = (key: string, style?: string) =>
+        (<EditableView
+            oneLine={true}
+            display={"inline"}
+            editing={this.props.document[Id] === TreeView.loadId}
+            contents={StrCast(this.props.document[key])}
+            height={36}
+            fontStyle={style}
+            GetValue={() => StrCast(this.props.document[key])}
+            OnFillDown={(value: string) => {
+                Doc.GetProto(this.props.document)[key] = value;
+                let doc = Docs.FreeformDocument([], { title: "untitled" });
+                TreeView.loadId = doc[Id];
+                this.props.addDocument(doc);
+                return true;
+            }}
+            OnTab={() => this.props.indentDocument && this.props.indentDocument()}
+            SetValue={(value: string) => {
+                Doc.GetProto(this.props.document)[key] = value;
+                return true;
+            }}
+        />);
+
     /**
      * Renders the EditableView title element for placement into the tree.
      */
     renderTitle() {
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = SetupDrag(reference, () => this.props.document, this.move, this.props.dropAction, this.props.treeViewId, true);
-        let editableView = (titleString: string) =>
-            (<EditableView
-                oneLine={!this._isOver ? true : false}
-                display={"inline"}
-                contents={titleString}
-                height={36}
-                GetValue={() => StrCast(this.props.document.title)}
-                SetValue={(value: string) => {
-                    let target = this.props.document.proto ? this.props.document.proto : this.props.document;
-                    target.title = value;
-                    return true;
-                }}
-            />);
+
         let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []) : [];
         let openRight = dataDocs && dataDocs.indexOf(this.props.document) !== -1 ? (null) : (
             <div className="treeViewItem-openRight" onPointerDown={this.onPointerDown} onClick={this.openRight}>
@@ -156,7 +176,7 @@ class TreeView extends React.Component<TreeViewProps> {
                     pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none"
                 }}
             >
-                {editableView(StrCast(this.props.document.title))}
+                {this.editableView("title")}
                 {/* {<div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>} */}
             </div >
             {openRight}
@@ -221,6 +241,7 @@ class TreeView extends React.Component<TreeViewProps> {
         return true;
     }
 
+    @observable _chosenKey: string = "data"
     _bulletType: BulletType = BulletType.List;
     render() {
         let bulletType = BulletType.List;
@@ -234,7 +255,21 @@ class TreeView extends React.Component<TreeViewProps> {
             keys.splice(keys.indexOf("data"), 1);
             keys.splice(0, 0, "data");
         }
+        let keyList: string[] = [];
         keys.map(key => {
+            let docList = Cast(this.props.document[key], listSpec(Doc));
+            let doc = Cast(this.props.document[key], Doc);
+            if (doc instanceof Doc || (docList && (DocListCast(docList).length > 0 || key === "data"))) {
+                keyList.push(key);
+            }
+        });
+        let headerElements = <div style={{ display: "block", marginTop: "7px" }} key={this._chosenKey}>{keyList.map(key =>
+            <span className="collectionTreeView-keyHeader" key={key} onPointerDown={action(() => this._chosenKey = key)}
+                style={{ display: "inline", marginRight: "3px", marginTop: "7px", background: key === this._chosenKey ? "lightgray" : undefined }}>
+                {key}
+            </span>)}
+        </div>
+        [this._chosenKey].map(key => {
             let docList = Cast(this.props.document[key], listSpec(Doc));
             let remDoc = (doc: Doc) => this.remove(doc, key);
             let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, key, doc, addBefore, before);
@@ -243,9 +278,10 @@ class TreeView extends React.Component<TreeViewProps> {
                 if (!this._collapsed) {
                     bulletType = BulletType.Collapsible;
                     contentElement.push(<ul key={key + "more"}>
-                        <span className="collectionTreeView-keyHeader" style={{ display: "block", marginTop: "7px" }} key={key}>{key}</span>
+                        {headerElements}
                         <div style={{ display: "block" }}>
                             {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move,
+                                this.indent,
                                 this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active)}
                         </div>
                     </ul >);
@@ -274,14 +310,36 @@ class TreeView extends React.Component<TreeViewProps> {
         add: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean,
         remove: ((doc: Doc) => void),
         move: DragManager.MoveFunction,
+        indent: () => void,
         dropAction: dropActionType,
         addDocTab: (doc: Doc, where: string) => void,
         screenToLocalXf: () => Transform,
         active: () => boolean
     ) {
-        return docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized)).map(child =>
-            <TreeView document={child} treeViewId={treeViewId} key={child[Id]} deleteDoc={remove} addDocument={add} moveDocument={move}
-                dropAction={dropAction} addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} parentKey={key} active={active} />);
+        let docList = docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized));
+        return docList.map((child, i) => {
+            let indent = i == 0 ? undefined : () => {
+                if (StrCast(docList[i - 1].layout).indexOf("CollectionView") !== -1) {
+                    let fieldKeysub = StrCast(docList[i - 1].layout).split("fieldKey")[1];
+                    let fieldKey = fieldKeysub.split("\"")[1];
+                    TreeView.AddDocToList(docList[i - 1], fieldKey, child);
+                    remove(child);
+                }
+            }
+            return <TreeView
+                document={child}
+                treeViewId={treeViewId}
+                key={child[Id]}
+                indentDocument={indent}
+                deleteDoc={remove}
+                addDocument={add}
+                moveDocument={move}
+                dropAction={dropAction}
+                addDocTab={addDocTab}
+                ScreenToLocalTransform={screenToLocalXf}
+                parentKey={key}
+                active={active} />
+        });
     }
 }
 
@@ -321,7 +379,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
         let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
         let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove,
-            moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active);
+            moveDoc, emptyFunction, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active);
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 6b8b64c5f..345fa5cc7 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -217,7 +217,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
         let aspect = (rotation % 180) ? this.props.Document[HeightSym]() / this.props.Document[WidthSym]() : 1;
         let shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0;
         return (
-            <div id={id} className={`imageBox-cont${interactive}`}
+            <div id={id} className={`imageBox-cont${interactive}`} style={{ background: "transparent" }}
                 onPointerDown={this.onPointerDown}
                 onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
                 <img id={id}
-- 
cgit v1.2.3-70-g09d2


From 1472d2b56aa64896f0a93f172322121d19cd1592 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 19 Jun 2019 09:11:35 -0400
Subject: fixed lint errors.

---
 src/client/views/EditableView.tsx                   |  2 +-
 src/client/views/collections/CollectionTreeView.tsx | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index a96fca464..70d6c22bf 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -28,7 +28,7 @@ export interface EditableProps {
     height?: number;
     display?: string;
     oneLine?: boolean;
-    editing?: boolean
+    editing?: boolean;
 }
 
 /**
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 6a2ab9d7d..f6c9ba86b 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -154,7 +154,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 Doc.GetProto(this.props.document)[key] = value;
                 return true;
             }}
-        />);
+        />)
 
     /**
      * Renders the EditableView title element for placement into the tree.
@@ -241,7 +241,7 @@ class TreeView extends React.Component<TreeViewProps> {
         return true;
     }
 
-    @observable _chosenKey: string = "data"
+    @observable _chosenKey: string = "data";
     _bulletType: BulletType = BulletType.List;
     render() {
         let bulletType = BulletType.List;
@@ -268,7 +268,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 style={{ display: "inline", marginRight: "3px", marginTop: "7px", background: key === this._chosenKey ? "lightgray" : undefined }}>
                 {key}
             </span>)}
-        </div>
+        </div>;
         [this._chosenKey].map(key => {
             let docList = Cast(this.props.document[key], listSpec(Doc));
             let remDoc = (doc: Doc) => this.remove(doc, key);
@@ -318,7 +318,7 @@ class TreeView extends React.Component<TreeViewProps> {
     ) {
         let docList = docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized));
         return docList.map((child, i) => {
-            let indent = i == 0 ? undefined : () => {
+            let indent = i === 0 ? undefined : () => {
                 if (StrCast(docList[i - 1].layout).indexOf("CollectionView") !== -1) {
                     let fieldKeysub = StrCast(docList[i - 1].layout).split("fieldKey")[1];
                     let fieldKey = fieldKeysub.split("\"")[1];
@@ -338,7 +338,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 addDocTab={addDocTab}
                 ScreenToLocalTransform={screenToLocalXf}
                 parentKey={key}
-                active={active} />
+                active={active} />;
         });
     }
 }
-- 
cgit v1.2.3-70-g09d2


From 0674331f3611d297028526c888c718a75b012e0a Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 19 Jun 2019 09:36:21 -0400
Subject: fixed resizing stacking views.  changed defaults for new docs in
 treeView

---
 src/client/views/DocumentDecorations.tsx            | 4 ++--
 src/client/views/collections/CollectionTreeView.tsx | 5 ++++-
 2 files changed, 6 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index e60f8c86c..d8642d675 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -503,8 +503,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                         proto.nativeWidth = (doc.width || 0) / doc.height * NumCast(proto.nativeHeight);
                     }
                 } else {
-                    doc.width = zoomBasis * actualdW;
-                    doc.height = zoomBasis * actualdH;
+                    dW && (doc.width = zoomBasis * actualdW);
+                    dH && (doc.height = zoomBasis * actualdH);
                     proto.autoHeight = undefined;
                 }
             }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index f6c9ba86b..5e690361c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -22,6 +22,8 @@ import React = require("react");
 import { Transform } from '../../util/Transform';
 import { SelectionManager } from '../../util/SelectionManager';
 import { emptyFunction } from '../../../Utils';
+import { List } from '../../../new_fields/List';
+import { Templates } from '../Templates';
 
 
 export interface TreeViewProps {
@@ -144,8 +146,9 @@ class TreeView extends React.Component<TreeViewProps> {
             GetValue={() => StrCast(this.props.document[key])}
             OnFillDown={(value: string) => {
                 Doc.GetProto(this.props.document)[key] = value;
-                let doc = Docs.FreeformDocument([], { title: "untitled" });
+                let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25 });
                 TreeView.loadId = doc[Id];
+                doc.templates = new List<string>([Templates.Title.Layout]);
                 this.props.addDocument(doc);
                 return true;
             }}
-- 
cgit v1.2.3-70-g09d2


From 0bb20528c8167b3ba1c4c88d97586d50ae183b4c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 19 Jun 2019 10:37:36 -0400
Subject: added highlight for expanded tree view items

---
 src/client/views/collections/CollectionTreeView.scss | 5 +++++
 src/client/views/collections/CollectionTreeView.tsx  | 4 +++-
 2 files changed, 8 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index f6df96d92..2d5092980 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -68,6 +68,11 @@
     display: none;
 }
 
+.treeViewItem-border {
+    display:inherit;
+    border-left: dashed 1px #00000042;
+}
+
 .treeViewItem-header:hover {
     .treeViewItem-openRight {
         display: inline-block;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 5e690361c..d43402e7d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -302,7 +302,9 @@ class TreeView extends React.Component<TreeViewProps> {
                     {this.renderBullet(bulletType)}
                     {this.renderTitle()}
                 </div>
-                {contentElement}
+                <div className="treeViewItem-border">
+                    {contentElement}
+                </div>
             </li>
         </div>;
     }
-- 
cgit v1.2.3-70-g09d2


From 358437eeafe42e029ffe27702bde15a3fad54a3b Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 19 Jun 2019 16:17:18 -0400
Subject: working version of embedded tree view docs.

---
 .../views/collections/CollectionStackingView.tsx   |   2 +
 .../views/collections/CollectionTreeView.scss      |  15 ++-
 .../views/collections/CollectionTreeView.tsx       | 132 +++++++++++++++------
 src/client/views/nodes/DocumentView.tsx            |   5 +-
 src/client/views/nodes/FormattedTextBox.tsx        |   1 +
 5 files changed, 109 insertions(+), 46 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index f80ba0a4b..368e94a8c 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -10,6 +10,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { CollectionSchemaPreview } from "./CollectionSchemaView";
 import "./CollectionStackingView.scss";
 import { CollectionSubView } from "./CollectionSubView";
+import { auto } from "async";
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -112,6 +113,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 style={{
                     width: width(),
                     height: height(),
+                    overflow: "auto",
                     transformOrigin: "top left",
                     gridRowEnd: `span ${rowSpan}`,
                     gridColumnEnd: `span 1`,
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 2d5092980..ec78fdb80 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -12,7 +12,7 @@
     padding-right: 0px;
     background: $light-color-secondary;
     font-size: 13px;
-    overflow: scroll;
+    overflow: auto;
 
     ul {
         list-style: none;
@@ -50,10 +50,12 @@
         font-size: 24px;
     }
 
-    .collectionTreeView-keyHeader {
-        font-style: italic;
-        font-size: 8pt;
-    }
+}
+.collectionTreeView-keyHeader {
+    font-style: italic;
+    font-size: 8pt;
+    margin-left: 3px;
+    display:none;
 }
 
 .docContainer {
@@ -74,6 +76,9 @@
 }
 
 .treeViewItem-header:hover {
+    .collectionTreeView-keyHeader {
+        display:inherit;
+    }
     .treeViewItem-openRight {
         display: inline-block;
         height:13px;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index d43402e7d..1eab541b3 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,9 +1,9 @@
 import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
 import { faAngleRight, faCaretDown, faCaretRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, observable, trace } from "mobx";
+import { action, observable, trace, computed } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCast } from '../../../new_fields/Doc';
+import { Doc, DocListCast, WidthSym, HeightSym } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { Document, listSpec } from '../../../new_fields/Schema';
 import { BoolCast, Cast, NumCast, StrCast, PromiseValue } from '../../../new_fields/Types';
@@ -16,14 +16,18 @@ import { EditableView } from "../EditableView";
 import { MainView } from '../MainView';
 import { CollectionViewType } from './CollectionBaseView';
 import { CollectionDockingView } from './CollectionDockingView';
-import { CollectionSubView } from "./CollectionSubView";
+import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import React = require("react");
 import { Transform } from '../../util/Transform';
 import { SelectionManager } from '../../util/SelectionManager';
-import { emptyFunction } from '../../../Utils';
+import { emptyFunction, returnFalse, Utils, returnOne, returnZero } from '../../../Utils';
 import { List } from '../../../new_fields/List';
 import { Templates } from '../Templates';
+import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
+import { number } from 'prop-types';
+import ReactTable from 'react-table';
+import { MainOverlayTextBox } from '../MainOverlayTextBox';
 
 
 export interface TreeViewProps {
@@ -32,9 +36,12 @@ export interface TreeViewProps {
     moveDocument: DragManager.MoveFunction;
     dropAction: "alias" | "copy" | undefined;
     addDocTab: (doc: Doc, where: string) => void;
+    panelWidth: () => number;
+    panelHeight: () => number;
     addDocument: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
     indentDocument?: () => void;
     ScreenToLocalTransform: () => Transform;
+    outerXf: () => number[];
     treeViewId: string;
     parentKey: string;
     active: () => boolean;
@@ -58,11 +65,13 @@ library.add(faCaretRight);
 class TreeView extends React.Component<TreeViewProps> {
     private _header?: React.RefObject<HTMLDivElement> = React.createRef();
     private treedropDisposer?: DragManager.DragDropDisposer;
+    private _mainEle?: HTMLDivElement;
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
         this.treedropDisposer && this.treedropDisposer();
         if (ele) {
             this.treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } });
         }
+        this._mainEle = ele;
     }
 
     @observable _isOver: boolean = false;
@@ -76,7 +85,7 @@ class TreeView extends React.Component<TreeViewProps> {
 
     onPointerEnter = (e: React.PointerEvent): void => {
         this.props.active() && (this.props.document.libraryBrush = true);
-        if (e.buttons === 1) {
+        if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
             this._header!.current!.className = "treeViewItem-header";
             document.addEventListener("pointermove", this.onDragMove, true);
         }
@@ -166,6 +175,28 @@ class TreeView extends React.Component<TreeViewProps> {
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = SetupDrag(reference, () => this.props.document, this.move, this.props.dropAction, this.props.treeViewId, true);
 
+        let keyList: string[] = [];
+        let keys = Array.from(Object.keys(this.props.document));
+        if (this.props.document.proto instanceof Doc) {
+            keys.push(...Array.from(Object.keys(this.props.document.proto)));
+            while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
+        }
+        if (keys.indexOf("data") !== -1) {
+            keys.splice(keys.indexOf("data"), 1);
+            keys.splice(0, 0, "data");
+        }
+        keys.map(key => {
+            let docList = Cast(this.props.document[key], listSpec(Doc));
+            let doc = Cast(this.props.document[key], Doc);
+            if (doc instanceof Doc || (docList && (DocListCast(docList).length > 0 || key === "data"))) {
+                keyList.push(key);
+            }
+        });
+        let headerElements = this._bulletType === BulletType.List ? (null) : [this._chosenKey].map(key =>
+            <span className="collectionTreeView-keyHeader" key={key} onPointerDown={action(() => { this._chosenKey = key; this.props.document.embed = !BoolCast(this.props.document.embed, false) })}
+                style={{ background: key === this._chosenKey ? "lightgray" : undefined }}>
+                {key}
+            </span>);
         let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []) : [];
         let openRight = dataDocs && dataDocs.indexOf(this.props.document) !== -1 ? (null) : (
             <div className="treeViewItem-openRight" onPointerDown={this.onPointerDown} onClick={this.openRight}>
@@ -182,6 +213,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 {this.editableView("title")}
                 {/* {<div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>} */}
             </div >
+            {headerElements}
             {openRight}
         </>;
     }
@@ -244,34 +276,20 @@ class TreeView extends React.Component<TreeViewProps> {
         return true;
     }
 
+    docTransform = () => {
+        let { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!);
+        let outerXf = this.props.outerXf();
+        let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf[0] - translateX, outerXf[1] - translateY);
+        let finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1]);
+        return finalXf;
+    }
     @observable _chosenKey: string = "data";
     _bulletType: BulletType = BulletType.List;
+
+    _dref = React.createRef<HTMLDivElement>();
     render() {
         let bulletType = BulletType.List;
         let contentElement: (JSX.Element | null)[] = [];
-        let keys = Array.from(Object.keys(this.props.document));
-        if (this.props.document.proto instanceof Doc) {
-            keys.push(...Array.from(Object.keys(this.props.document.proto)));
-            while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
-        }
-        if (keys.indexOf("data") !== -1) {
-            keys.splice(keys.indexOf("data"), 1);
-            keys.splice(0, 0, "data");
-        }
-        let keyList: string[] = [];
-        keys.map(key => {
-            let docList = Cast(this.props.document[key], listSpec(Doc));
-            let doc = Cast(this.props.document[key], Doc);
-            if (doc instanceof Doc || (docList && (DocListCast(docList).length > 0 || key === "data"))) {
-                keyList.push(key);
-            }
-        });
-        let headerElements = <div style={{ display: "block", marginTop: "7px" }} key={this._chosenKey}>{keyList.map(key =>
-            <span className="collectionTreeView-keyHeader" key={key} onPointerDown={action(() => this._chosenKey = key)}
-                style={{ display: "inline", marginRight: "3px", marginTop: "7px", background: key === this._chosenKey ? "lightgray" : undefined }}>
-                {key}
-            </span>)}
-        </div>;
         [this._chosenKey].map(key => {
             let docList = Cast(this.props.document[key], listSpec(Doc));
             let remDoc = (doc: Doc) => this.remove(doc, key);
@@ -280,14 +298,31 @@ class TreeView extends React.Component<TreeViewProps> {
             if (doc instanceof Doc || (docList && (DocListCast(docList).length > 0 || key === "data"))) {
                 if (!this._collapsed) {
                     bulletType = BulletType.Collapsible;
-                    contentElement.push(<ul key={key + "more"}>
-                        {headerElements}
-                        <div style={{ display: "block" }}>
-                            {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move,
-                                this.indent,
-                                this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active)}
-                        </div>
-                    </ul >);
+                    if (this.props.document.embed) {
+                        contentElement.push(
+                            <div ref={this._dref} style={{ width: "max-content", display: "unset" }} key={this.props.document[Id]}>
+                                <DocumentView Document={this.props.document}
+                                    ContainingCollectionView={undefined}
+                                    ScreenToLocalTransform={this.docTransform}
+                                    isTopMost={false}
+                                    useActualDimensions={true}
+                                    ContentScaling={returnOne}
+                                    PanelWidth={this.props.document[WidthSym]}
+                                    PanelHeight={this.props.document[HeightSym]}
+                                    focus={emptyFunction}
+                                    selectOnLoad={false}
+                                    parentActive={returnFalse}
+                                    whenActiveChanged={emptyFunction}
+                                    bringToFront={emptyFunction}
+                                    addDocTab={this.props.addDocTab}
+                                /></div>);
+                    } else
+                        contentElement.push(<ul key={key + "more"}>
+                            <div style={{ display: "block" }}>
+                                {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move,
+                                    this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.panelHeight)}
+                            </div>
+                        </ul >);
                 } else {
                     bulletType = BulletType.Collapsed;
                 }
@@ -315,11 +350,13 @@ class TreeView extends React.Component<TreeViewProps> {
         add: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean,
         remove: ((doc: Doc) => void),
         move: DragManager.MoveFunction,
-        indent: () => void,
         dropAction: dropActionType,
         addDocTab: (doc: Doc, where: string) => void,
         screenToLocalXf: () => Transform,
-        active: () => boolean
+        outerXf: () => number[],
+        active: () => boolean,
+        panelWidth: () => number,
+        panelHeight: () => number
     ) {
         let docList = docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized));
         return docList.map((child, i) => {
@@ -338,10 +375,13 @@ class TreeView extends React.Component<TreeViewProps> {
                 indentDocument={indent}
                 deleteDoc={remove}
                 addDocument={add}
+                panelWidth={panelWidth}
+                panelHeight={panelHeight}
                 moveDocument={move}
                 dropAction={dropAction}
                 addDocTab={addDocTab}
                 ScreenToLocalTransform={screenToLocalXf}
+                outerXf={outerXf}
                 parentKey={key}
                 active={active} />;
         });
@@ -351,6 +391,7 @@ class TreeView extends React.Component<TreeViewProps> {
 @observer
 export class CollectionTreeView extends CollectionSubView(Document) {
     private treedropDisposer?: DragManager.DragDropDisposer;
+    private _mainEle?: HTMLDivElement;
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
         if (this.treedropDisposer) {
             this.treedropDisposer();
@@ -358,6 +399,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         if (ele) {
             this.treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
         }
+        this._mainEle = ele;
     }
 
     @action
@@ -373,6 +415,10 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         }
     }
 
+    outerXf = () => {
+        let outerXf = Utils.GetScreenTransform(this._mainEle!);
+        return [outerXf.translateX, outerXf.translateY];
+    }
     onTreeDrop = (e: React.DragEvent) => {
         this.onDrop(e, {});
     }
@@ -384,7 +430,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
         let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
         let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove,
-            moveDoc, emptyFunction, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active);
+            moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.outerXf, this.props.active, this.props.PanelWidth, () => 25);
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
@@ -399,6 +445,14 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                         display={"inline"}
                         height={72}
                         GetValue={() => StrCast(this.props.Document.title)}
+                        OnFillDown={(value: string) => {
+                            let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+                            target.title = value;
+                            let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25 });
+                            TreeView.loadId = doc[Id];
+                            doc.templates = new List<string>([Templates.Title.Layout]);
+                            this.props.addDocument(doc);
+                        }}
                         SetValue={(value: string) => {
                             let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
                             target.title = value;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4992669df..f7836d947 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -72,6 +72,7 @@ export interface DocumentViewProps {
     ScreenToLocalTransform: () => Transform;
     isTopMost: boolean;
     ContentScaling: () => number;
+    useActualDimensions?: boolean;
     PanelWidth: () => number;
     PanelHeight: () => number;
     focus: (doc: Doc) => void;
@@ -538,8 +539,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     render() {
         var scaling = this.props.ContentScaling();
-        var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%";
-        var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
+        var nativeWidth = this.props.useActualDimensions ? NumCast(this.props.Document.width) : this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%";
+        var nativeHeight = this.props.useActualDimensions ? NumCast(this.props.Document.height) : BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
         return (
             <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index df12f261b..376b5a574 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -409,6 +409,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                     opacity: this.props.hideOnLeave ? (this._entered || this.props.isSelected() || this.props.Document.libraryBrush ? 1 : 0.1) : 1,
                     color: this.props.color ? this.props.color : this.props.hideOnLeave ? "white" : "initial",
                     pointerEvents: interactive ? "all" : "none",
+                    fontSize: "13px"
                 }}
                 onKeyDown={this.onKeyPress}
                 onFocus={this.onFocused}
-- 
cgit v1.2.3-70-g09d2


From 118ecb14ce519bcbade12b3d52e11b22fcc371b3 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 19 Jun 2019 22:40:54 -0400
Subject: cleaned up and enhanced tree view

---
 src/client/documents/Documents.ts                  |   1 -
 .../views/collections/CollectionSchemaView.tsx     |   2 +-
 .../views/collections/CollectionTreeView.scss      |   5 +-
 .../views/collections/CollectionTreeView.tsx       | 347 +++++++++------------
 src/client/views/nodes/DocumentView.tsx            |   5 +-
 5 files changed, 158 insertions(+), 202 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index fcd1010c6..de6c5bc6a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -18,7 +18,6 @@ import { action } from "mobx";
 import { ColumnAttributeModel } from "../northstar/core/attribute/AttributeModel";
 import { AttributeTransformationModel } from "../northstar/core/attribute/AttributeTransformationModel";
 import { AggregateFunction } from "../northstar/model/idea/idea";
-import { Template } from "../views/Templates";
 import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss";
 import { IconBox } from "../views/nodes/IconBox";
 import { Field, Doc, Opt } from "../../new_fields/Doc";
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index faea8d44d..9cc8961e3 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -385,7 +385,7 @@ interface CollectionSchemaPreviewProps {
     Document?: Doc;
     width: () => number;
     height: () => number;
-    CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
+    CollectionView?: CollectionView | CollectionPDFView | CollectionVideoView;
     getTransform: () => Transform;
     addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
     moveDocument: (document: Doc, target: Doc, addDoc: ((doc: Doc) => boolean)) => boolean;
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index ec78fdb80..a85604e58 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -4,10 +4,10 @@
     border-width: $COLLECTION_BORDER_WIDTH;
     border-color: transparent;
     border-style: solid;
-    border-radius: $border-radius;
+    border-radius: inherit;
     box-sizing: border-box;
     height: 100%;
-    padding: 20px;
+    padding-top: 20px;
     padding-left: 10px;
     padding-right: 0px;
     background: $light-color-secondary;
@@ -56,6 +56,7 @@
     font-size: 8pt;
     margin-left: 3px;
     display:none;
+    background: lightgray;
 }
 
 .docContainer {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 1eab541b3..856430036 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,38 +1,35 @@
-import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
-import { faAngleRight, faCaretDown, faCaretRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faAngleRight, faCaretDown, faCaretRight, faTrashAlt, faCaretSquareRight, faCaretSquareDown } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, observable, trace, computed } from "mobx";
+import { action, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCast, WidthSym, HeightSym } from '../../../new_fields/Doc';
+import { Doc, DocListCast, HeightSym, 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 { BoolCast, Cast, NumCast, StrCast, PromiseValue } from '../../../new_fields/Types';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../new_fields/Types';
+import { emptyFunction, Utils } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
+import { SelectionManager } from '../../util/SelectionManager';
+import { Transform } from '../../util/Transform';
 import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from '../ContextMenu';
 import { EditableView } from "../EditableView";
 import { MainView } from '../MainView';
+import { Templates } from '../Templates';
 import { CollectionViewType } from './CollectionBaseView';
 import { CollectionDockingView } from './CollectionDockingView';
-import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
+import { CollectionSchemaPreview } from './CollectionSchemaView';
+import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import React = require("react");
-import { Transform } from '../../util/Transform';
-import { SelectionManager } from '../../util/SelectionManager';
-import { emptyFunction, returnFalse, Utils, returnOne, returnZero } from '../../../Utils';
-import { List } from '../../../new_fields/List';
-import { Templates } from '../Templates';
-import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
-import { number } from 'prop-types';
-import ReactTable from 'react-table';
-import { MainOverlayTextBox } from '../MainOverlayTextBox';
 
 
 export interface TreeViewProps {
     document: Doc;
-    deleteDoc: (doc: Doc) => void;
+    deleteDoc: (doc: Doc) => boolean;
     moveDocument: DragManager.MoveFunction;
     dropAction: "alias" | "copy" | undefined;
     addDocTab: (doc: Doc, where: string) => void;
@@ -41,22 +38,18 @@ export interface TreeViewProps {
     addDocument: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
     indentDocument?: () => void;
     ScreenToLocalTransform: () => Transform;
-    outerXf: () => number[];
+    outerXf: () => { translateX: number, translateY: number };
     treeViewId: string;
     parentKey: string;
     active: () => boolean;
 }
 
-export enum BulletType {
-    Collapsed,
-    Collapsible,
-    List
-}
-
 library.add(faTrashAlt);
 library.add(faAngleRight);
 library.add(faCaretDown);
 library.add(faCaretRight);
+library.add(faCaretSquareDown);
+library.add(faCaretSquareRight);
 
 @observer
 /**
@@ -64,25 +57,22 @@ library.add(faCaretRight);
  */
 class TreeView extends React.Component<TreeViewProps> {
     private _header?: React.RefObject<HTMLDivElement> = React.createRef();
-    private treedropDisposer?: DragManager.DragDropDisposer;
-    private _mainEle?: HTMLDivElement;
+    private _treedropDisposer?: DragManager.DragDropDisposer;
+    private _dref = React.createRef<HTMLDivElement>();
+    @observable _chosenKey: string = "data";
+    @observable _collapsed: boolean = true;
+
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
-        this.treedropDisposer && this.treedropDisposer();
+        this._treedropDisposer && this._treedropDisposer();
         if (ele) {
-            this.treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } });
+            this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } });
         }
-        this._mainEle = ele;
     }
 
-    @observable _isOver: boolean = false;
-    @observable _collapsed: boolean = true;
-
     @undoBatch delete = () => this.props.deleteDoc(this.props.document);
     @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight");
 
-    @action onMouseEnter = () => { this._isOver = true; };
-    @action onMouseLeave = () => { this._isOver = false; };
-
+    onPointerDown = (e: React.PointerEvent) => e.stopPropagation()
     onPointerEnter = (e: React.PointerEvent): void => {
         this.props.active() && (this.props.document.libraryBrush = true);
         if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
@@ -101,80 +91,60 @@ class TreeView extends React.Component<TreeViewProps> {
         let rect = this._header!.current!.getBoundingClientRect();
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
         let before = x[1] < bounds[1];
-        let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible);
+        let inside = x[0] > bounds[0] + 75 || (!before && !this._collapsed);
         this._header!.current!.className = "treeViewItem-header";
-        if (inside && this._bulletType !== BulletType.List) this._header!.current!.className += " treeViewItem-header-inside";
+        if (inside) this._header!.current!.className += " treeViewItem-header-inside";
         else if (before) this._header!.current!.className += " treeViewItem-header-above";
         else if (!before) this._header!.current!.className += " treeViewItem-header-below";
         e.stopPropagation();
     }
-    onPointerDown = (e: React.PointerEvent) => {
-        e.stopPropagation();
-    }
 
     @action
-    remove = (document: Document, key: string) => {
+    remove = (document: Document, key: string): boolean => {
         let children = Cast(this.props.document[key], listSpec(Doc), []);
-        children.indexOf(document) !== -1 && children.splice(children.indexOf(document), 1);
+        if (children.indexOf(document) !== -1) {
+            children.splice(children.indexOf(document), 1);
+            return true;
+        }
+        return false;
     }
 
     @action
-    move: DragManager.MoveFunction = (document: Doc, target: Doc, addDoc) => {
-        if (this.props.document !== target) {
-            //TODO This should check if it was removed
-            this.props.deleteDoc(document);
-            return addDoc(document);
-        }
-        return true;
+    move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => {
+        return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc);
     }
     @action
-    indent = () => {
-        this.props.addDocument(this.props.document);
-        this.delete();
-    }
-
+    indent = () => this.props.addDocument(this.props.document) && this.delete();
 
-    renderBullet(type: BulletType) {
-        let onClicked = action(() => this._collapsed = !this._collapsed);
-        let bullet: IconProp | undefined = undefined;
-        switch (type) {
-            case BulletType.Collapsed: bullet = "caret-right"; break;
-            case BulletType.Collapsible: bullet = "caret-down"; break;
-        }
-        return <div className="bullet" onClick={onClicked}>{bullet ? <FontAwesomeIcon icon={bullet} /> : ""} </div>;
+    renderBullet() {
+        let docList = Cast(this.props.document["data"], listSpec(Doc));
+        let doc = Cast(this.props.document["data"], Doc);
+        let isDoc = doc instanceof Doc || docList;
+        return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)}>
+            {<FontAwesomeIcon icon={this._collapsed ? (isDoc ? "caret-square-right" : "caret-right") : (isDoc ? "caret-square-down" : "caret-down")} />}
+        </div>;
     }
-    static loadId = "";
-    editableView = (key: string, style?: string) =>
-        (<EditableView
-            oneLine={true}
-            display={"inline"}
-            editing={this.props.document[Id] === TreeView.loadId}
-            contents={StrCast(this.props.document[key])}
-            height={36}
-            fontStyle={style}
-            GetValue={() => StrCast(this.props.document[key])}
-            OnFillDown={(value: string) => {
-                Doc.GetProto(this.props.document)[key] = value;
-                let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25 });
-                TreeView.loadId = doc[Id];
-                doc.templates = new List<string>([Templates.Title.Layout]);
-                this.props.addDocument(doc);
-                return true;
-            }}
-            OnTab={() => this.props.indentDocument && this.props.indentDocument()}
-            SetValue={(value: string) => {
-                Doc.GetProto(this.props.document)[key] = value;
-                return true;
-            }}
-        />)
 
-    /**
-     * Renders the EditableView title element for placement into the tree.
-     */
-    renderTitle() {
-        let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => this.props.document, this.move, this.props.dropAction, this.props.treeViewId, true);
+    static loadId = "";
+    editableView = (key: string, style?: string) => (<EditableView
+        oneLine={true}
+        display={"inline"}
+        editing={this.props.document[Id] === TreeView.loadId}
+        contents={StrCast(this.props.document[key])}
+        height={36}
+        fontStyle={style}
+        GetValue={() => StrCast(this.props.document[key])}
+        SetValue={(value: string) => (Doc.GetProto(this.props.document)[key] = value) ? true : true}
+        OnFillDown={(value: string) => {
+            Doc.GetProto(this.props.document)[key] = value;
+            let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) });
+            TreeView.loadId = doc[Id];
+            return this.props.addDocument(doc);
+        }}
+        OnTab={() => this.props.indentDocument && this.props.indentDocument()}
+    />)
 
+    get keyList() {
         let keyList: string[] = [];
         let keys = Array.from(Object.keys(this.props.document));
         if (this.props.document.proto instanceof Doc) {
@@ -192,19 +162,26 @@ class TreeView extends React.Component<TreeViewProps> {
                 keyList.push(key);
             }
         });
-        let headerElements = this._bulletType === BulletType.List ? (null) : [this._chosenKey].map(key =>
-            <span className="collectionTreeView-keyHeader" key={key} onPointerDown={action(() => { this._chosenKey = key; this.props.document.embed = !BoolCast(this.props.document.embed, false) })}
-                style={{ background: key === this._chosenKey ? "lightgray" : undefined }}>
-                {key}
+        return keyList;
+    }
+    /**
+     * Renders the EditableView title element for placement into the tree.
+     */
+    renderTitle() {
+        let reference = React.createRef<HTMLDivElement>();
+        let onItemDown = SetupDrag(reference, () => this.props.document, this.move, this.props.dropAction, this.props.treeViewId, true);
+
+        let headerElements = (
+            <span className="collectionTreeView-keyHeader" key={this._chosenKey} onPointerDown={action(() => this.props.document.embed = !BoolCast(this.props.document.embed))} >
+                {this._chosenKey}
             </span>);
         let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []) : [];
         let openRight = dataDocs && dataDocs.indexOf(this.props.document) !== -1 ? (null) : (
             <div className="treeViewItem-openRight" onPointerDown={this.onPointerDown} onClick={this.openRight}>
                 <FontAwesomeIcon icon="angle-right" size="lg" />
-                {/* <FontAwesomeIcon icon="angle-right" size="lg" /> */}
             </div>);
         return <>
-            <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
+            <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown}
                 style={{
                     background: BoolCast(this.props.document.protoBrush, false) ? "#06123232" : BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0",
                     pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none"
@@ -241,7 +218,7 @@ class TreeView extends React.Component<TreeViewProps> {
         let rect = this._header!.current!.getBoundingClientRect();
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
         let before = x[1] < bounds[1];
-        let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible);
+        let inside = x[0] > bounds[0] + 75 || (!before && !this._collapsed);
         if (de.data instanceof DragManager.DocumentDragData) {
             let addDoc = (doc: Doc) => this.props.addDocument(doc, this.props.document, before);
             if (inside) {
@@ -250,18 +227,13 @@ class TreeView extends React.Component<TreeViewProps> {
                     addDoc = (doc: Doc) => { docList && docList.push(doc); return true; };
                 }
             }
-            let added = false;
-            if (de.data.dropAction || de.data.userDropAction) {
-                added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.props.document, before) || added, false);
-            } else if (de.data.moveDocument) {
-                let movedDocs = de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments;
-                added = movedDocs.reduce((added: boolean, d) =>
-                    de.data.moveDocument(d, this.props.document, addDoc) || added, false);
-            } else {
-                added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.props.document, before), false);
-            }
             e.stopPropagation();
-            return added;
+            let movedDocs = (de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
+            return (de.data.dropAction || de.data.userDropAction) ?
+                de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.props.document, before) || added, false)
+                : (de.data.moveDocument) ?
+                    movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, this.props.document, addDoc) || added, false)
+                    : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.props.document, before), false);
         }
         return false;
     }
@@ -279,62 +251,47 @@ class TreeView extends React.Component<TreeViewProps> {
     docTransform = () => {
         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!);
         let outerXf = this.props.outerXf();
-        let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf[0] - translateX, outerXf[1] - translateY);
+        let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
         let finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1]);
         return finalXf;
     }
-    @observable _chosenKey: string = "data";
-    _bulletType: BulletType = BulletType.List;
 
-    _dref = React.createRef<HTMLDivElement>();
     render() {
-        let bulletType = BulletType.List;
-        let contentElement: (JSX.Element | null)[] = [];
-        [this._chosenKey].map(key => {
-            let docList = Cast(this.props.document[key], listSpec(Doc));
-            let remDoc = (doc: Doc) => this.remove(doc, key);
-            let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, key, doc, addBefore, before);
-            let doc = Cast(this.props.document[key], Doc);
-            if (doc instanceof Doc || (docList && (DocListCast(docList).length > 0 || key === "data"))) {
-                if (!this._collapsed) {
-                    bulletType = BulletType.Collapsible;
-                    if (this.props.document.embed) {
-                        contentElement.push(
-                            <div ref={this._dref} style={{ width: "max-content", display: "unset" }} key={this.props.document[Id]}>
-                                <DocumentView Document={this.props.document}
-                                    ContainingCollectionView={undefined}
-                                    ScreenToLocalTransform={this.docTransform}
-                                    isTopMost={false}
-                                    useActualDimensions={true}
-                                    ContentScaling={returnOne}
-                                    PanelWidth={this.props.document[WidthSym]}
-                                    PanelHeight={this.props.document[HeightSym]}
-                                    focus={emptyFunction}
-                                    selectOnLoad={false}
-                                    parentActive={returnFalse}
-                                    whenActiveChanged={emptyFunction}
-                                    bringToFront={emptyFunction}
-                                    addDocTab={this.props.addDocTab}
-                                /></div>);
-                    } else
-                        contentElement.push(<ul key={key + "more"}>
-                            <div style={{ display: "block" }}>
-                                {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move,
-                                    this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.panelHeight)}
-                            </div>
-                        </ul >);
-                } else {
-                    bulletType = BulletType.Collapsed;
-                }
+        let contentElement: (JSX.Element | null) = null;
+        let docList = Cast(this.props.document[this._chosenKey], listSpec(Doc));
+        let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
+        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before);
+        let doc = Cast(this.props.document[this._chosenKey], Doc);
+        let docWidth = () => NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5;
+        if (!this._collapsed) {
+            if (!this.props.document.embed && (docList && (DocListCast(docList).length > 0 || this._chosenKey === "data"))) {
+                contentElement = <ul key={this._chosenKey + "more"}>
+                    {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this._chosenKey, addDoc, remDoc, this.move,
+                        this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth)}
+                </ul >;
+            } else {
+                contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.props.panelHeight() }} key={this.props.document[Id]}>
+                    <CollectionSchemaPreview
+                        Document={this.props.document}
+                        width={docWidth}
+                        height={this.props.panelHeight}
+                        getTransform={this.docTransform}
+                        CollectionView={undefined}
+                        addDocument={emptyFunction as any}
+                        moveDocument={this.props.moveDocument}
+                        removeDocument={emptyFunction as any}
+                        active={this.props.active}
+                        whenActiveChanged={emptyFunction as any}
+                        addDocTab={this.props.addDocTab}
+                        setPreviewScript={emptyFunction}>
+                    </CollectionSchemaPreview>
+                </div>
             }
-        });
-        this._bulletType = bulletType;
-        return <div className="treeViewItem-container"
-            ref={this.createTreeDropTarget}
-            onContextMenu={this.onWorkspaceContextMenu}>
+        }
+        return <div className="treeViewItem-container" ref={this.createTreeDropTarget} onContextMenu={this.onWorkspaceContextMenu}>
             <li className="collection-child">
                 <div className="treeViewItem-header" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
-                    {this.renderBullet(bulletType)}
+                    {this.renderBullet()}
                     {this.renderTitle()}
                 </div>
                 <div className="treeViewItem-border">
@@ -348,17 +305,17 @@ class TreeView extends React.Component<TreeViewProps> {
         treeViewId: string,
         key: string,
         add: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean,
-        remove: ((doc: Doc) => void),
+        remove: ((doc: Doc) => boolean),
         move: DragManager.MoveFunction,
         dropAction: dropActionType,
         addDocTab: (doc: Doc, where: string) => void,
         screenToLocalXf: () => Transform,
-        outerXf: () => number[],
+        outerXf: () => { translateX: number, translateY: number },
         active: () => boolean,
         panelWidth: () => number,
-        panelHeight: () => number
     ) {
         let docList = docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized));
+        let rowWidth = () => panelWidth() - 20;
         return docList.map((child, i) => {
             let indent = i === 0 ? undefined : () => {
                 if (StrCast(docList[i - 1].layout).indexOf("CollectionView") !== -1) {
@@ -368,15 +325,22 @@ class TreeView extends React.Component<TreeViewProps> {
                     remove(child);
                 }
             }
+            let addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
+                return add(doc, relativeTo ? relativeTo : docList[i], before !== undefined ? before : false);
+            }
+            let rowHeight = () => {
+                let aspect = NumCast(child.nativeWidth, 0) / NumCast(child.nativeHeight, 0);
+                return aspect ? Math.min(child[WidthSym](), rowWidth()) / aspect : child[HeightSym]();
+            }
             return <TreeView
                 document={child}
                 treeViewId={treeViewId}
                 key={child[Id]}
                 indentDocument={indent}
                 deleteDoc={remove}
-                addDocument={add}
-                panelWidth={panelWidth}
-                panelHeight={panelHeight}
+                addDocument={addDocument}
+                panelWidth={rowWidth}
+                panelHeight={rowHeight}
                 moveDocument={move}
                 dropAction={dropAction}
                 addDocTab={addDocTab}
@@ -392,20 +356,26 @@ class TreeView extends React.Component<TreeViewProps> {
 export class CollectionTreeView extends CollectionSubView(Document) {
     private treedropDisposer?: DragManager.DragDropDisposer;
     private _mainEle?: HTMLDivElement;
+
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
-        if (this.treedropDisposer) {
-            this.treedropDisposer();
-        }
-        if (ele) {
+        this.treedropDisposer && this.treedropDisposer();
+        if (this._mainEle = ele) {
             this.treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
         }
-        this._mainEle = ele;
+    }
+
+    componentWillUnmount() {
+        this.treedropDisposer && this.treedropDisposer();
     }
 
     @action
-    remove = (document: Document) => {
+    remove = (document: Document): boolean => {
         let children = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []);
-        children.indexOf(document) !== -1 && children.splice(children.indexOf(document), 1);
+        if (children.indexOf(document) !== -1) {
+            children.splice(children.indexOf(document), 1);
+            return true;
+        }
+        return false;
     }
     onContextMenu = (e: React.MouseEvent): void => {
         // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
@@ -415,26 +385,16 @@ export class CollectionTreeView extends CollectionSubView(Document) {
         }
     }
 
-    outerXf = () => {
-        let outerXf = Utils.GetScreenTransform(this._mainEle!);
-        return [outerXf.translateX, outerXf.translateY];
-    }
-    onTreeDrop = (e: React.DragEvent) => {
-        this.onDrop(e, {});
-    }
+    outerXf = () => Utils.GetScreenTransform(this._mainEle!);
+    onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {});
+
     render() {
         let dropAction = StrCast(this.props.Document.dropAction) as dropActionType;
-        if (!this.childDocs) {
-            return (null);
-        }
         let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
         let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
-        let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove,
-            moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.outerXf, this.props.active, this.props.PanelWidth, () => 25);
 
-        return (
+        return !this.childDocs ? (null) : (
             <div id="body" className="collectionTreeView-dropTarget"
-                style={{ borderRadius: "inherit" }}
                 onContextMenu={this.onContextMenu}
                 onWheel={(e: React.WheelEvent) => this.props.isSelected() && e.stopPropagation()}
                 onDrop={this.onTreeDrop}
@@ -445,22 +405,19 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                         display={"inline"}
                         height={72}
                         GetValue={() => StrCast(this.props.Document.title)}
+                        SetValue={(value: string) => (Doc.GetProto(this.props.Document).title = value) ? true : true}
                         OnFillDown={(value: string) => {
-                            let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
-                            target.title = value;
-                            let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25 });
+                            Doc.GetProto(this.props.Document).title = value;
+                            let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) });
                             TreeView.loadId = doc[Id];
-                            doc.templates = new List<string>([Templates.Title.Layout]);
-                            this.props.addDocument(doc);
-                        }}
-                        SetValue={(value: string) => {
-                            let target = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
-                            target.title = value;
-                            return true;
+                            TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true);
                         }} />
                 </div>
                 <ul className="no-indent">
-                    {childElements}
+                    {
+                        TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove,
+                            moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.outerXf, this.props.active, this.props.PanelWidth)
+                    }
                 </ul>
             </div >
         );
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f7836d947..4992669df 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -72,7 +72,6 @@ export interface DocumentViewProps {
     ScreenToLocalTransform: () => Transform;
     isTopMost: boolean;
     ContentScaling: () => number;
-    useActualDimensions?: boolean;
     PanelWidth: () => number;
     PanelHeight: () => number;
     focus: (doc: Doc) => void;
@@ -539,8 +538,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     render() {
         var scaling = this.props.ContentScaling();
-        var nativeWidth = this.props.useActualDimensions ? NumCast(this.props.Document.width) : this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%";
-        var nativeHeight = this.props.useActualDimensions ? NumCast(this.props.Document.height) : BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
+        var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%";
+        var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
         return (
             <div className={`documentView-node${this.props.isTopMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
-- 
cgit v1.2.3-70-g09d2


From 38de022621175bda7410df4444fcd2bbee0919cb Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 19 Jun 2019 23:43:47 -0400
Subject: slight tweaks.

---
 src/client/views/EditableView.tsx                  |  5 +++-
 .../views/collections/CollectionTreeView.tsx       | 35 +++++++++++++++-------
 2 files changed, 28 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 70d6c22bf..0f6281b5c 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -29,6 +29,7 @@ export interface EditableProps {
     display?: string;
     oneLine?: boolean;
     editing?: boolean;
+    onClick?: (e: React.MouseEvent) => boolean;
 }
 
 /**
@@ -65,7 +66,9 @@ export class EditableView extends React.Component<EditableProps> {
 
     @action
     onClick = (e: React.MouseEvent) => {
-        this._editing = true;
+        if (!this.props.onClick || !this.props.onClick(e)) {
+            this._editing = true;
+        }
         e.stopPropagation();
     }
 
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 856430036..c51c16883 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,7 +1,7 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faAngleRight, faCaretDown, faCaretRight, faTrashAlt, faCaretSquareRight, faCaretSquareDown } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, observable } from "mobx";
+import { action, observable, computed } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, WidthSym } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
@@ -125,12 +125,20 @@ class TreeView extends React.Component<TreeViewProps> {
         </div>;
     }
 
+    titleClicked = (e: React.MouseEvent) => {
+        if (this._collapsed) return false;
+        else {
+            this.props.document.embed = !BoolCast(this.props.document.embed);
+            return true;
+        }
+    }
     static loadId = "";
     editableView = (key: string, style?: string) => (<EditableView
         oneLine={true}
         display={"inline"}
         editing={this.props.document[Id] === TreeView.loadId}
         contents={StrCast(this.props.document[key])}
+        onClick={this.titleClicked}
         height={36}
         fontStyle={style}
         GetValue={() => StrCast(this.props.document[key])}
@@ -144,24 +152,24 @@ class TreeView extends React.Component<TreeViewProps> {
         OnTab={() => this.props.indentDocument && this.props.indentDocument()}
     />)
 
-    get keyList() {
-        let keyList: string[] = [];
+    @computed get keyList() {
         let keys = Array.from(Object.keys(this.props.document));
         if (this.props.document.proto instanceof Doc) {
             keys.push(...Array.from(Object.keys(this.props.document.proto)));
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
-        if (keys.indexOf("data") !== -1) {
-            keys.splice(keys.indexOf("data"), 1);
-            keys.splice(0, 0, "data");
-        }
+        let keyList: string[] = [];
         keys.map(key => {
             let docList = Cast(this.props.document[key], listSpec(Doc));
             let doc = Cast(this.props.document[key], Doc);
-            if (doc instanceof Doc || (docList && (DocListCast(docList).length > 0 || key === "data"))) {
+            if (doc instanceof Doc || docList) {
                 keyList.push(key);
             }
         });
+        if (keyList.indexOf("data") !== -1) {
+            keyList.splice(keyList.indexOf("data"), 1);
+        }
+        keyList.splice(0, 0, "data");
         return keyList;
     }
     /**
@@ -172,7 +180,12 @@ class TreeView extends React.Component<TreeViewProps> {
         let onItemDown = SetupDrag(reference, () => this.props.document, this.move, this.props.dropAction, this.props.treeViewId, true);
 
         let headerElements = (
-            <span className="collectionTreeView-keyHeader" key={this._chosenKey} onPointerDown={action(() => this.props.document.embed = !BoolCast(this.props.document.embed))} >
+            <span className="collectionTreeView-keyHeader" key={this._chosenKey}
+                onPointerDown={action(() => {
+                    let ind = this.keyList.indexOf(this._chosenKey);
+                    ind = (ind + 1) % this.keyList.length;
+                    this._chosenKey = this.keyList[ind];
+                })} >
                 {this._chosenKey}
             </span>);
         let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []) : [];
@@ -209,7 +222,7 @@ class TreeView extends React.Component<TreeViewProps> {
             } else {
                 ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)) });
             }
-            ContextMenu.Instance.displayMenu(e.pageX - 156, e.pageY - 15);
+            ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15);
             e.stopPropagation();
         }
     }
@@ -264,7 +277,7 @@ class TreeView extends React.Component<TreeViewProps> {
         let doc = Cast(this.props.document[this._chosenKey], Doc);
         let docWidth = () => NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5;
         if (!this._collapsed) {
-            if (!this.props.document.embed && (docList && (DocListCast(docList).length > 0 || this._chosenKey === "data"))) {
+            if (!this.props.document.embed) {
                 contentElement = <ul key={this._chosenKey + "more"}>
                     {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this._chosenKey, addDoc, remDoc, this.move,
                         this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth)}
-- 
cgit v1.2.3-70-g09d2


From a39b2854b848006c19460685d7bf4005a9f650ae Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 20 Jun 2019 17:09:50 -0400
Subject: moved AddDocToList to Doc utils

---
 src/client/views/collections/CollectionTreeView.tsx | 18 ++++--------------
 src/new_fields/Doc.ts                               | 10 ++++++++++
 2 files changed, 14 insertions(+), 14 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index c51c16883..443c763bf 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -251,16 +251,6 @@ class TreeView extends React.Component<TreeViewProps> {
         return false;
     }
 
-    public static AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean) {
-        let list = Cast(target[key], listSpec(Doc));
-        if (list) {
-            let ind = relativeTo ? list.indexOf(relativeTo) : -1;
-            if (ind === -1) list.push(doc);
-            else list.splice(before ? ind : ind + 1, 0, doc);
-        }
-        return true;
-    }
-
     docTransform = () => {
         let { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!);
         let outerXf = this.props.outerXf();
@@ -273,7 +263,7 @@ class TreeView extends React.Component<TreeViewProps> {
         let contentElement: (JSX.Element | null) = null;
         let docList = Cast(this.props.document[this._chosenKey], listSpec(Doc));
         let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
-        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before);
+        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before);
         let doc = Cast(this.props.document[this._chosenKey], Doc);
         let docWidth = () => NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5;
         if (!this._collapsed) {
@@ -334,7 +324,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 if (StrCast(docList[i - 1].layout).indexOf("CollectionView") !== -1) {
                     let fieldKeysub = StrCast(docList[i - 1].layout).split("fieldKey")[1];
                     let fieldKey = fieldKeysub.split("\"")[1];
-                    TreeView.AddDocToList(docList[i - 1], fieldKey, child);
+                    Doc.AddDocToList(docList[i - 1], fieldKey, child);
                     remove(child);
                 }
             }
@@ -403,7 +393,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
 
     render() {
         let dropAction = StrCast(this.props.Document.dropAction) as dropActionType;
-        let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
+        let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
         let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
 
         return !this.childDocs ? (null) : (
@@ -423,7 +413,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
                             Doc.GetProto(this.props.Document).title = value;
                             let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) });
                             TreeView.loadId = doc[Id];
-                            TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true);
+                            Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true);
                         }} />
                 </div>
                 <ul className="no-indent">
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 1b0ff812f..7bae7a02d 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -222,6 +222,16 @@ export namespace Doc {
         return Array.from(results);
     }
 
+    export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean) {
+        let list = Cast(target[key], listSpec(Doc));
+        if (list) {
+            let ind = relativeTo ? list.indexOf(relativeTo) : -1;
+            if (ind === -1) list.push(doc);
+            else list.splice(before ? ind : ind + 1, 0, doc);
+        }
+        return true;
+    }
+
     export function MakeAlias(doc: Doc) {
         if (!GetT(doc, "isPrototype", "boolean", true)) {
             return Doc.MakeCopy(doc);
-- 
cgit v1.2.3-70-g09d2


From 0cab79a50719719e1dade40520a6967f7aa8f951 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Thu, 20 Jun 2019 18:35:45 -0400
Subject: Added debug and release modes to server and client

---
 .gitignore                                         |  2 ++
 package.json                                       |  2 ++
 src/client/util/ClientUtils.ts.temp                |  3 ++
 .../views/collections/CollectionStackingView.tsx   |  2 +-
 .../views/collections/CollectionTreeView.tsx       | 16 +++++-----
 src/server/index.ts                                | 34 ++++++++++++++++++----
 6 files changed, 45 insertions(+), 14 deletions(-)
 create mode 100644 src/client/util/ClientUtils.ts.temp

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

diff --git a/.gitignore b/.gitignore
index a499c39a3..5d3100dc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@ node_modules
 package-lock.json
 dist/
 .DS_Store
+.env
+ClientUtils.ts
\ No newline at end of file
diff --git a/package.json b/package.json
index 7fd6c4ba9..91d3a3853 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,7 @@
         "@types/cookie-parser": "^1.4.1",
         "@types/cookie-session": "^2.0.36",
         "@types/d3-format": "^1.3.1",
+        "@types/dotenv": "^6.1.1",
         "@types/express": "^4.16.1",
         "@types/express-flash": "0.0.0",
         "@types/express-session": "^1.15.12",
@@ -110,6 +111,7 @@
         "cookie-session": "^2.0.0-beta.3",
         "crypto-browserify": "^3.11.0",
         "d3-format": "^1.3.2",
+        "dotenv": "^8.0.0",
         "express": "^4.16.4",
         "express-flash": "0.0.2",
         "express-session": "^1.15.6",
diff --git a/src/client/util/ClientUtils.ts.temp b/src/client/util/ClientUtils.ts.temp
new file mode 100644
index 000000000..f9fad5ed9
--- /dev/null
+++ b/src/client/util/ClientUtils.ts.temp
@@ -0,0 +1,3 @@
+export namespace ClientUtils {
+    export const RELEASE = "mode";
+}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 368e94a8c..521e8d616 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -101,7 +101,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             let renderScale = this.columnWidth / NumCast(d.nativeWidth, this.columnWidth);
             let aspect = NumCast(d.nativeWidth) / NumCast(d.nativeHeight);
             let width = () => this.columnWidth;
-            let height = () => aspect ? width() / aspect : d[HeightSym]()
+            let height = () => aspect ? width() / aspect : d[HeightSym]();
             let rowSpan = Math.ceil((height() + this.gridGap) / (this._gridSize + this.gridGap));
             let childFocus = (doc: Doc) => {
                 doc.libraryBrush = true;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index c51c16883..c7ed2eb38 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -72,7 +72,7 @@ class TreeView extends React.Component<TreeViewProps> {
     @undoBatch delete = () => this.props.deleteDoc(this.props.document);
     @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight");
 
-    onPointerDown = (e: React.PointerEvent) => e.stopPropagation()
+    onPointerDown = (e: React.PointerEvent) => e.stopPropagation();
     onPointerEnter = (e: React.PointerEvent): void => {
         this.props.active() && (this.props.document.libraryBrush = true);
         if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
@@ -114,11 +114,11 @@ class TreeView extends React.Component<TreeViewProps> {
         return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc);
     }
     @action
-    indent = () => this.props.addDocument(this.props.document) && this.delete();
+    indent = () => this.props.addDocument(this.props.document) && this.delete()
 
     renderBullet() {
-        let docList = Cast(this.props.document["data"], listSpec(Doc));
-        let doc = Cast(this.props.document["data"], Doc);
+        let docList = Cast(this.props.document.data, listSpec(Doc));
+        let doc = Cast(this.props.document.data, Doc);
         let isDoc = doc instanceof Doc || docList;
         return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)}>
             {<FontAwesomeIcon icon={this._collapsed ? (isDoc ? "caret-square-right" : "caret-right") : (isDoc ? "caret-square-down" : "caret-down")} />}
@@ -298,7 +298,7 @@ class TreeView extends React.Component<TreeViewProps> {
                         addDocTab={this.props.addDocTab}
                         setPreviewScript={emptyFunction}>
                     </CollectionSchemaPreview>
-                </div>
+                </div>;
             }
         }
         return <div className="treeViewItem-container" ref={this.createTreeDropTarget} onContextMenu={this.onWorkspaceContextMenu}>
@@ -337,14 +337,14 @@ class TreeView extends React.Component<TreeViewProps> {
                     TreeView.AddDocToList(docList[i - 1], fieldKey, child);
                     remove(child);
                 }
-            }
+            };
             let addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
                 return add(doc, relativeTo ? relativeTo : docList[i], before !== undefined ? before : false);
-            }
+            };
             let rowHeight = () => {
                 let aspect = NumCast(child.nativeWidth, 0) / NumCast(child.nativeHeight, 0);
                 return aspect ? Math.min(child[WidthSym](), rowWidth()) / aspect : child[HeightSym]();
-            }
+            };
             return <TreeView
                 document={child}
                 treeViewId={treeViewId}
diff --git a/src/server/index.ts b/src/server/index.ts
index 2901f61ed..e645e29b4 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1,3 +1,4 @@
+require('dotenv').config();
 import * as bodyParser from 'body-parser';
 import { exec } from 'child_process';
 import * as cookieParser from 'cookie-parser';
@@ -45,6 +46,17 @@ const probe = require("probe-image-size");
 
 const download = (url: string, dest: fs.PathLike) => request.get(url).pipe(fs.createWriteStream(dest));
 
+const release = process.env.RELEASE === "true";
+if (process.env.RELEASE === "true") {
+    console.log("Running server in release mode");
+} else {
+    console.log("Running server in debug mode");
+}
+console.log(process.env.PWD);
+let clientUtils = fs.readFileSync("./src/client/util/ClientUtils.ts.temp", "utf8");
+clientUtils = `//AUTO-GENERATED FILE: DO NOT EDIT\n${clientUtils.replace('"mode"', String(release))}`;
+fs.writeFileSync("./src/client/util/ClientUtils.ts", clientUtils, "utf8");
+
 const mongoUrl = 'mongodb://localhost:27017/Dash';
 mongoose.connect(mongoUrl);
 mongoose.connection.on('connected', () => console.log("connected"));
@@ -406,11 +418,21 @@ app.post(RouteStore.reset, postReset);
 app.use(RouteStore.corsProxy, (req, res) =>
     req.pipe(request(req.url.substring(1))).pipe(res));
 
-app.get(RouteStore.delete, (req, res) =>
-    deleteFields().then(() => res.redirect(RouteStore.home)));
+app.get(RouteStore.delete, (req, res) => {
+    if (release) {
+        res.send("no");
+        return;
+    }
+    deleteFields().then(() => res.redirect(RouteStore.home));
+});
 
-app.get(RouteStore.deleteAll, (req, res) =>
-    deleteAll().then(() => res.redirect(RouteStore.home)));
+app.get(RouteStore.deleteAll, (req, res) => {
+    if (release) {
+        res.send("no");
+        return;
+    }
+    deleteAll().then(() => res.redirect(RouteStore.home));
+});
 
 app.use(wdm(compiler, { publicPath: config.output.publicPath }));
 
@@ -435,7 +457,9 @@ server.on("connection", function (socket: Socket) {
     Utils.AddServerHandler(socket, MessageStore.SetField, (args) => setField(socket, args));
     Utils.AddServerHandlerCallback(socket, MessageStore.GetField, getField);
     Utils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields);
-    Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields);
+    if (!release) {
+        Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields);
+    }
 
     Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField);
     Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff));
-- 
cgit v1.2.3-70-g09d2


From ca5e29fdc7c238274eaf90682a8fa2ddc90e4e17 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 20 Jun 2019 22:22:57 -0400
Subject: fix to open on right, fix to image drag fro web, and layout fixes for
 stacking view multi-column

---
 .../views/collections/CollectionStackingView.scss  | 13 +++++
 .../views/collections/CollectionStackingView.tsx   | 62 ++++++++--------------
 src/client/views/collections/CollectionSubView.tsx |  7 ++-
 .../views/collections/CollectionTreeView.tsx       |  2 +-
 4 files changed, 42 insertions(+), 42 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index af194aec9..485ecf1de 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -38,4 +38,17 @@
         background: $dark-color;
         color: $light-color;
     }
+
+
+    .collectionStackingView-columnDoc, 
+    .collectionStackingView-masonryDoc {
+        margin-left: auto;
+        margin-right: auto;
+    }
+    
+    .collectionStackingView-masonryDoc {
+        transform-origin: top left;
+        grid-column-end: span 1;
+        height: 100%;
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 368e94a8c..c855cb43a 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,5 +1,5 @@
 import React = require("react");
-import { action, computed, IReactionDisposer, reaction } from "mobx";
+import { action, computed, IReactionDisposer, reaction, trace } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
@@ -10,7 +10,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { CollectionSchemaPreview } from "./CollectionSchemaView";
 import "./CollectionStackingView.scss";
 import { CollectionSubView } from "./CollectionSubView";
-import { auto } from "async";
+import { Transform } from "../../util/Transform";
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -67,18 +67,17 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         let children = this.childDocs.filter(d => !d.isMinimized);
         return children.map((d, i) => {
             let dref = React.createRef<HTMLDivElement>();
-            let script = undefined;
-            let colWidth = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth;
-            let rowHeight = () => this.singleColDocHeight(d);
             let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]());
-            return <div className="collectionStackingView-masonryDoc"
+            let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth;
+            let height = () => this.singleColDocHeight(d);
+            return <div className="collectionStackingView-columnDoc"
                 key={d[Id]}
                 ref={dref}
-                style={{ width: colWidth(), height: rowHeight(), marginLeft: "auto", marginRight: "auto" }} >
+                style={{ width: width(), height: height() }} >
                 <CollectionSchemaPreview
                     Document={d}
-                    width={colWidth}
-                    height={rowHeight}
+                    width={width}
+                    height={height}
                     getTransform={dxf}
                     CollectionView={this.props.CollectionView}
                     addDocument={this.props.addDocument}
@@ -88,7 +87,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                     whenActiveChanged={this.props.whenActiveChanged}
                     addDocTab={this.props.addDocTab}
                     setPreviewScript={emptyFunction}
-                    previewScript={script}>
+                    previewScript={undefined}>
                 </CollectionSchemaPreview>
             </div>;
         });
@@ -96,46 +95,31 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     @computed
     get children() {
         return this.childDocs.filter(d => !d.isMinimized).map((d, i) => {
+            let aspect = d.nativeHeight ? NumCast(d.nativeWidth) / NumCast(d.nativeHeight) : undefined;
             let dref = React.createRef<HTMLDivElement>();
             let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]());
-            let renderScale = this.columnWidth / NumCast(d.nativeWidth, this.columnWidth);
-            let aspect = NumCast(d.nativeWidth) / NumCast(d.nativeHeight);
-            let width = () => this.columnWidth;
+            let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth;
             let height = () => aspect ? width() / aspect : d[HeightSym]()
             let rowSpan = Math.ceil((height() + this.gridGap) / (this._gridSize + this.gridGap));
-            let childFocus = (doc: Doc) => {
-                doc.libraryBrush = true;
-                this.props.focus(this.props.Document); // just focus on this collection, not the underlying document because the API doesn't support adding an offset to focus on and we can't pan zoom our contents to be centered.
-            };
             return (<div className="collectionStackingView-masonryDoc"
                 key={d[Id]}
                 ref={dref}
-                style={{
-                    width: width(),
-                    height: height(),
-                    overflow: "auto",
-                    transformOrigin: "top left",
-                    gridRowEnd: `span ${rowSpan}`,
-                    gridColumnEnd: `span 1`,
-                    transform: `scale(${renderScale})`
-                }} >
-                <DocumentView key={d[Id]} Document={d}
+                style={{ gridRowEnd: `span ${rowSpan}` }} >
+                <CollectionSchemaPreview
+                    Document={d}
+                    CollectionView={this.props.CollectionView}
                     addDocument={this.props.addDocument}
+                    moveDocument={this.props.moveDocument}
                     removeDocument={this.props.removeDocument}
-                    moveDocument={this.moveDocument}
-                    ContainingCollectionView={this.props.CollectionView}
-                    isTopMost={false}
-                    ScreenToLocalTransform={dxf}
-                    focus={childFocus}
-                    ContentScaling={returnOne}
-                    PanelWidth={width}
-                    PanelHeight={height}
-                    selectOnLoad={false}
-                    parentActive={this.props.active}
+                    getTransform={dxf}
+                    width={width}
+                    height={height}
+                    active={this.props.active}
                     addDocTab={this.props.addDocTab}
-                    bringToFront={emptyFunction}
                     whenActiveChanged={this.props.whenActiveChanged}
-                />
+                    setPreviewScript={emptyFunction}
+                    previewScript={undefined}>
+                </CollectionSchemaPreview>
             </div>);
         });
     }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index e55cd9e37..699bddc7c 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -176,8 +176,11 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 return;
             }
             if (html && !html.startsWith("<a")) {
-                if (html.indexOf("<img") === 0) {
-                    let split = html.split("\"")[1];
+                let tags = html.split("<");
+                if (tags[0] === "") tags.splice(0, 1);
+                let img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : "";
+                if (img) {
+                    let split = img.split("src=\"")[1].split("\"")[0];
                     let doc = Docs.ImageDocument(split, { ...options, width: 300 });
                     this.props.addDocument(doc, false);
                     return;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index c51c16883..e7a3c4022 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -70,7 +70,7 @@ class TreeView extends React.Component<TreeViewProps> {
     }
 
     @undoBatch delete = () => this.props.deleteDoc(this.props.document);
-    @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight");
+    @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "onRight");
 
     onPointerDown = (e: React.PointerEvent) => e.stopPropagation()
     onPointerEnter = (e: React.PointerEvent): void => {
-- 
cgit v1.2.3-70-g09d2

