From 08fbeaf2ebf4ee2466fa156e6e8c663d2bef7864 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 24 Apr 2020 00:06:48 -0400
Subject: moved iconify code into Doc from DocumentView.  fixed up starburst a
 bit.

---
 src/client/views/collections/CollectionTreeView.tsx | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 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 a052d045c..ca2004b79 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -3,13 +3,14 @@ import { faAngleRight, faArrowsAltH, faBell, faCamera, faCaretDown, faCaretRight
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, runInAction, untracked } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCast, Field, HeightSym, WidthSym, DataSym, Opt } from '../../../new_fields/Doc';
+import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
+import { RichTextField } from '../../../new_fields/RichTextField';
 import { Document, listSpec } from '../../../new_fields/Schema';
 import { ComputedField, ScriptField } from '../../../new_fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../new_fields/Types';
-import { emptyFunction, emptyPath, returnFalse, Utils, returnOne, returnZero, returnTransparent, returnTrue, simulateMouseClick } from '../../../Utils';
+import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { DocumentType } from "../../documents/DocumentTypes";
 import { DocumentManager } from '../../util/DocumentManager';
@@ -24,16 +25,14 @@ import { ContextMenuProps } from '../ContextMenuItem';
 import { EditableView } from "../EditableView";
 import { MainView } from '../MainView';
 import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView';
+import { DocumentView } from '../nodes/DocumentView';
 import { ImageBox } from '../nodes/ImageBox';
 import { KeyValueBox } from '../nodes/KeyValueBox';
-import { ScriptBox } from '../ScriptBox';
 import { Templates } from '../Templates';
-import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
+import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
+import { CollectionViewType } from './CollectionView';
 import React = require("react");
-import { CollectionViewType, CollectionView } from './CollectionView';
-import { RichTextField } from '../../../new_fields/RichTextField';
-import { DocumentView } from '../nodes/DocumentView';
 
 
 export interface TreeViewProps {
@@ -768,7 +767,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         const existingOnClick = ContextMenu.Instance.findByDescription("OnClick...");
         const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
         onClicks.push({
-            description: "Edit onChecked Script", event: () => UndoManager.RunInBatch(() => DocumentView.makeCustomViewClicked(this.props.Document, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit"
+            description: "Edit onChecked Script", event: () => UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit"
         });
         !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
     }
-- 
cgit v1.2.3-70-g09d2


From f1ac48c19b4683668b0df91bd4ad68690a069029 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 25 Apr 2020 21:43:21 -0400
Subject: added a targetDropAction field to specify the drop action from the
 target's side

---
 src/client/util/DragManager.ts                            | 15 ++++++++++-----
 src/client/views/collections/CollectionCarouselView.tsx   |  2 +-
 src/client/views/collections/CollectionLinearView.tsx     |  2 +-
 .../views/collections/CollectionSchemaMovableTableHOC.tsx |  2 +-
 src/client/views/collections/CollectionSubView.tsx        |  9 ++-------
 src/client/views/collections/CollectionTreeView.tsx       |  4 ++--
 src/client/views/collections/CollectionViewChromes.tsx    |  4 ++--
 src/client/views/nodes/DocumentView.tsx                   |  4 ++--
 src/client/views/nodes/FormattedTextBox.tsx               |  2 +-
 src/client/views/nodes/ImageBox.tsx                       |  2 +-
 src/client/views/nodes/LabelBox.tsx                       |  2 +-
 src/new_fields/documentSchemas.ts                         |  3 ++-
 12 files changed, 26 insertions(+), 25 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 6a55f4a00..577366cd4 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,5 +1,5 @@
 import { Doc, Field, DocListCast } from "../../new_fields/Doc";
-import { Cast, ScriptCast } from "../../new_fields/Types";
+import { Cast, ScriptCast, StrCast } from "../../new_fields/Types";
 import { emptyFunction } from "../../Utils";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import * as globalCssVariables from "../views/globalCssVariables.scss";
@@ -180,7 +180,7 @@ export namespace DragManager {
     export function MakeDropTarget(
         element: HTMLElement,
         dropFunc: (e: Event, de: DropEvent) => void,
-        preDropFunc?: (e: Event, de: DropEvent) => void
+        doc?:Doc
     ): DragDropDisposer {
         if ("canDrop" in element.dataset) {
             throw new Error(
@@ -189,12 +189,17 @@ export namespace DragManager {
         }
         element.dataset.canDrop = "true";
         const handler = (e: Event) => dropFunc(e, (e as CustomEvent<DropEvent>).detail);
-        const preDropHandler = (e: Event) => preDropFunc?.(e, (e as CustomEvent<DropEvent>).detail);
+        const preDropHandler = (e:Event) => {
+            const de = (e as CustomEvent<DropEvent>).detail;
+            if (de.complete.docDragData && doc?.targetDropAction) {
+                de.complete.docDragData!.dropAction = StrCast(doc.targetDropAction) as dropActionType;
+            }
+        }
         element.addEventListener("dashOnDrop", handler);
-        preDropFunc && element.addEventListener("dashPreDrop", preDropHandler);
+        doc && element.addEventListener("dashPreDrop", preDropHandler);
         return () => {
             element.removeEventListener("dashOnDrop", handler);
-            preDropFunc && element.removeEventListener("dashPreDrop", preDropHandler);
+            doc && element.removeEventListener("dashPreDrop", preDropHandler);
             delete element.dataset.canDrop;
         };
     }
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 9e7248db2..2453acddf 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -27,7 +27,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
     protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
         this._dropDisposer?.();
         if (ele) {
-            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
+            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
         }
     }
 
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index cb0206260..344dca23a 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -64,7 +64,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
     protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
         this._dropDisposer && this._dropDisposer();
         if (ele) {
-            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
+            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
         }
     }
 
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 670d6dbb2..972714e34 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -54,7 +54,7 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
     }
 
     createColDropTarget = (ele: HTMLDivElement) => {
-        this._colDropDisposer && this._colDropDisposer();
+        this._colDropDisposer?.();
         if (ele) {
             this._colDropDisposer = DragManager.MakeDropTarget(ele, this.colDrop.bind(this));
         }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 60cc1bd49..49abc6ee6 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -11,7 +11,7 @@ import { Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { Docs, DocumentOptions } from "../../documents/Documents";
-import { DragManager } from "../../util/DragManager";
+import { DragManager, dropActionType } from "../../util/DragManager";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { DocComponent } from "../DocComponent";
 import { FieldViewProps } from "../nodes/FieldView";
@@ -64,7 +64,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
             this.multiTouchDisposer?.();
             if (ele) {
                 this._mainCont = ele;
-                this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.onInternalPreDrop.bind(this));
+                this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
                 this.gestureDisposer = GestureUtils.MakeGestureTarget(ele, this.onGesture.bind(this));
                 this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(ele, this.onTouchStart.bind(this));
             }
@@ -208,11 +208,6 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
         protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {
         }
 
-        protected onInternalPreDrop(e: Event, de: DragManager.DropEvent): boolean {
-            // de.complete.docDragData!.dropAction = "alias";  bcz: for example, you can convert all drops to aliases here
-            return true;
-        }
-
         @undoBatch
         @action
         protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ca2004b79..8c5a4538e 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -143,7 +143,7 @@ class TreeView extends React.Component<TreeViewProps> {
 
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
         this._treedropDisposer && this._treedropDisposer();
-        ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this)));
+        ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this)), this.props.document);
     }
 
     onPointerEnter = (e: React.PointerEvent): void => {
@@ -663,7 +663,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
         this.treedropDisposer?.();
         if (this._mainEle = ele) {
-            this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
+            this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.props.Document);
         }
     }
 
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 7315d2c4e..d26e3a38b 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -215,9 +215,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
 
     private dropDisposer?: DragManager.DragDropDisposer;
     protected createDropTarget = (ele: HTMLDivElement) => {
-        this.dropDisposer && this.dropDisposer();
+        this.dropDisposer?.();
         if (ele) {
-            this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this));
+            this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.document);
         }
     }
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7ae77fc65..2aee49ad3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -191,7 +191,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @action
     componentDidMount() {
-        this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this)));
+        this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document));
         this._mainCont.current && (this._gestureEventDisposer = GestureUtils.MakeGestureTarget(this._mainCont.current, this.onGesture.bind(this)));
         this._mainCont.current && (this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this)));
         // this._mainCont.current && (this.holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this)));
@@ -208,7 +208,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         this.multiTouchDisposer?.();
         this.holdDisposer?.();
         if (this._mainCont.current) {
-            this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this));
+            this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document);
             this._gestureEventDisposer = GestureUtils.MakeGestureTarget(this._mainCont.current, this.onGesture.bind(this));
             this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this));
             this.holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this));
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d7cfbae9f..815b8b3ae 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -253,7 +253,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     protected createDropTarget = (ele: HTMLDivElement) => {
         this.ProseRef = ele;
         this.dropDisposer?.();
-        ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)));
+        ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document));
     }
 
     @undoBatch
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 14b367868..08917d281 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -76,7 +76,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
 
     protected createDropTarget = (ele: HTMLDivElement) => {
         this._dropDisposer && this._dropDisposer();
-        ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)));
+        ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document));
     }
 
     @undoBatch
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 5c2fc3ffe..a41e4fac4 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -32,7 +32,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps, LabelDocument
     protected createDropTarget = (ele: HTMLDivElement) => {
         this.dropDisposer?.();
         if (ele) {
-            this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this));
+            this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document);
         }
     }
 
diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts
index 61b185e5c..f24ad42b2 100644
--- a/src/new_fields/documentSchemas.ts
+++ b/src/new_fields/documentSchemas.ts
@@ -8,7 +8,8 @@ export const documentSchema = createSchema({
     layout: "string",           // this is the native layout string for the document.  templates can be added using other fields and setting layoutKey below
     layoutKey: "string",        // holds the field key for the field that actually holds the current lyoat
     title: "string",            // document title (can be on either data document or layout)
-    dropAction: "string",       // override specifying what should happen when this document is dropped (can be "alias" or "copy")
+    dropAction: "string",       // override specifying what should happen when this document is dropped (can be "alias", "copy", "move")
+    targetDropAction: "string",  // allows the target of a drop event to specify the dropAction ("alias", "copy", "move")
     childDropAction: "string",  // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "alias" or "copy")
     _autoHeight: "boolean",     // whether the height of the document should be computed automatically based on its contents
     _nativeWidth: "number",     // native width of document which determines how much document contents are scaled when the document's width is set
-- 
cgit v1.2.3-70-g09d2


From e6549d43be83b50d364c4a3ab1e8e7381ce2fd59 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 26 Apr 2020 01:56:41 -0400
Subject: fixed title layout for text.  fixed documentBox for nested
 collections.  fixed tree view for text boxes. changed labelbox formatting.

---
 src/client/util/DragManager.ts                              |  8 ++++----
 src/client/views/collections/CollectionTreeView.tsx         | 13 +++++++++----
 .../collectionFreeForm/CollectionFreeFormView.tsx           |  3 ++-
 src/client/views/nodes/ColorBox.scss                        |  1 +
 src/client/views/nodes/DocumentBox.tsx                      |  4 ++--
 src/client/views/nodes/DocumentView.tsx                     |  7 ++-----
 src/client/views/nodes/FormattedTextBox.scss                |  1 -
 src/client/views/nodes/FormattedTextBox.tsx                 |  4 ++--
 src/client/views/nodes/LabelBox.scss                        |  2 --
 src/client/views/nodes/LabelBox.tsx                         |  8 +++++++-
 src/server/authentication/models/current_user_utils.ts      |  4 ++--
 11 files changed, 31 insertions(+), 24 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 577366cd4..35694a6bd 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -180,7 +180,7 @@ export namespace DragManager {
     export function MakeDropTarget(
         element: HTMLElement,
         dropFunc: (e: Event, de: DropEvent) => void,
-        doc?:Doc
+        doc?: Doc
     ): DragDropDisposer {
         if ("canDrop" in element.dataset) {
             throw new Error(
@@ -189,12 +189,12 @@ export namespace DragManager {
         }
         element.dataset.canDrop = "true";
         const handler = (e: Event) => dropFunc(e, (e as CustomEvent<DropEvent>).detail);
-        const preDropHandler = (e:Event) => {
+        const preDropHandler = (e: Event) => {
             const de = (e as CustomEvent<DropEvent>).detail;
             if (de.complete.docDragData && doc?.targetDropAction) {
-                de.complete.docDragData!.dropAction = StrCast(doc.targetDropAction) as dropActionType;
+                de.complete.docDragData.dropAction = StrCast(doc.targetDropAction) as dropActionType;
             }
-        }
+        };
         element.addEventListener("dashOnDrop", handler);
         doc && element.addEventListener("dashPreDrop", preDropHandler);
         return () => {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8c5a4538e..ddd7474bd 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -261,7 +261,7 @@ class TreeView extends React.Component<TreeViewProps> {
     docHeight = () => {
         const layoutDoc = Doc.Layout(this.props.document);
         const bounds = this.boundsOfCollectionDocument;
-        return Math.min(this.MAX_EMBED_HEIGHT, (() => {
+        return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
             const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
             if (aspect) return this.docWidth() * aspect;
             if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x);
@@ -269,7 +269,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
                     NumCast(this.props.containingCollection._height)))) :
                 NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
-        })());
+        })()));
     }
 
     @computed get expandedField() {
@@ -321,6 +321,9 @@ class TreeView extends React.Component<TreeViewProps> {
         return rows;
     }
 
+    rtfWidth = () => Math.min(Doc.Layout(this.props.document)?.[WidthSym](), this.props.panelWidth() - 20);
+    rtfHeight = () => this.rtfWidth() < Doc.Layout(this.props.document)?.[WidthSym]() ? Math.min(Doc.Layout(this.props.document)?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
+
     @computed get renderContent() {
         const expandKey = this.treeViewExpandedView === this.fieldKey ? this.fieldKey : this.treeViewExpandedView === "links" ? "links" : undefined;
         if (expandKey !== undefined) {
@@ -355,8 +358,10 @@ class TreeView extends React.Component<TreeViewProps> {
                     backgroundColor={this.props.backgroundColor}
                     fitToBox={this.boundsOfCollectionDocument !== undefined}
                     FreezeDimensions={true}
-                    PanelWidth={this.docWidth}
-                    PanelHeight={this.docHeight}
+                    NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
+                    NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined}
+                    PanelWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth}
+                    PanelHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight}
                     getTransform={this.docTransform}
                     CollectionDoc={this.props.containingCollection}
                     CollectionView={undefined}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 852442fd4..28b461313 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1026,7 +1026,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                             true :
                             (this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? false : undefined}
                     jitterRotation={NumCast(this.props.Document._jitterRotation)}
-                    fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)}
+                    //fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
+                    fitToBox={BoolCast(this.props.freezeChildDimensions)} // bcz: check this
                     FreezeDimensions={BoolCast(this.props.freezeChildDimensions)}
                 />,
                 bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica)
diff --git a/src/client/views/nodes/ColorBox.scss b/src/client/views/nodes/ColorBox.scss
index bf334c939..da3266dc1 100644
--- a/src/client/views/nodes/ColorBox.scss
+++ b/src/client/views/nodes/ColorBox.scss
@@ -3,6 +3,7 @@
      height:100%;
      position: relative;
      pointer-events: none;
+     transform-origin: top left;
      
     .sketch-picker {
         margin:auto;
diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx
index 0111cadd5..0d18baaed 100644
--- a/src/client/views/nodes/DocumentBox.tsx
+++ b/src/client/views/nodes/DocumentBox.tsx
@@ -120,8 +120,8 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
             DataDocument={undefined}
             LibraryPath={emptyPath}
             CollectionView={this as any} // bcz: hack!  need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked.  currently, the up selector allows only a containing collection to be selected
-            fitToBox={this.props.fitToBox}
-            layoutKey={"layout_" + childTemplateName}
+            fitToBox={true}
+            layoutKey={childTemplateName ? "layout_" + childTemplateName : "layout"}
             rootSelected={this.props.isSelected}
             addDocument={this.props.addDocument}
             moveDocument={this.props.moveDocument}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2aee49ad3..f8bf9bf64 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1072,7 +1072,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     layoutKey={this.finalLayoutKey} />
             </div>);
         const titleView = (!showTitle ? (null) :
-            <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} style={{
+            <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} key="title" style={{
                 position: showTextTitle ? "relative" : "absolute",
                 pointerEvents: this.onClickHandler || this.Document.ignoreClick ? "none" : undefined,
             }}>
@@ -1086,10 +1086,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         return !showTitle && !showCaption ?
             this.contents :
             <div className="documentView-styleWrapper" >
-                <div className="documentView-styleContentWrapper" style={{ height: showTextTitle ? `calc(100% - ${this.chromeHeight()}px)` : "100%", top: showTextTitle ? this.chromeHeight() : undefined }}>
-                    {this.contents}
-                </div>
-                {titleView}
+                {this.Document.type !== DocumentType.RTF ? <> {this.contents} {titleView} </> : <> {titleView} {this.contents} </>}
                 {captionView}
             </div>;
     }
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 7a05ec3a3..3bedb7127 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -24,7 +24,6 @@
     overflow-y: auto;
     overflow-x: hidden;
     color: initial;
-    height: 100%;
     max-height: 100%;
     display: flex;
     flex-direction: row;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 815b8b3ae..425af8ccf 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -194,7 +194,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
 
             const tsel = this._editorView.state.selection.$from;
             tsel.marks().filter(m => m.type === this._editorView!.state.schema.marks.user_mark).map(m => AudioBox.SetScrubTime(Math.max(0, m.attrs.modified * 1000)));
-            const curText = state.doc.textBetween(0, state.doc.content.size, "\n\n");
+            const curText = state.doc.textBetween(0, state.doc.content.size, " \n");
             const curTemp = Cast(this.props.Document[this.props.fieldKey + "-textTemplate"], RichTextField);
             if (!this._applyingChange) {
                 this._applyingChange = true;
@@ -1211,7 +1211,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         return (
             <div className={`formattedTextBox-cont`} ref={this._ref}
                 style={{
-                    height: this.layoutDoc._autoHeight && this.props.renderDepth ? "max-content" : undefined,
+                    height: this.layoutDoc._autoHeight && this.props.renderDepth ? "max-content" : `calc(100% - ${this.props.ChromeHeight?.() || 0}px`,
                     background: this.props.hideOnLeave ? "rgba(0,0,0 ,0.4)" : StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"]),
                     opacity: this.props.hideOnLeave ? (this._entered ? 1 : 0.1) : 1,
                     color: this.props.hideOnLeave ? "white" : "inherit",
diff --git a/src/client/views/nodes/LabelBox.scss b/src/client/views/nodes/LabelBox.scss
index 56dd86ff9..7c7e92379 100644
--- a/src/client/views/nodes/LabelBox.scss
+++ b/src/client/views/nodes/LabelBox.scss
@@ -18,8 +18,6 @@
 
 .labelBox-mainButtonCenter {
     overflow: hidden;
-    text-overflow: ellipsis;
-    white-space: nowrap;
     display: inline;
     align-items: center;
     margin: auto;
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index a41e4fac4..59c695f21 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -74,7 +74,13 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps, LabelDocument
                     color: StrCast(this.layoutDoc.color, "inherit"),
                     fontSize: NumCast(this.layoutDoc.fontSize) || "inherit",
                     letterSpacing: StrCast(this.layoutDoc.letterSpacing),
-                    textTransform: StrCast(this.layoutDoc.textTransform) as any
+                    textTransform: StrCast(this.layoutDoc.textTransform) as any,
+                    paddingLeft: NumCast(this.layoutDoc._xPadding),
+                    paddingRight: NumCast(this.layoutDoc._xPadding),
+                    paddingTop: NumCast(this.layoutDoc._yPadding),
+                    paddingBottom: NumCast(this.layoutDoc._yPadding),
+                    textOverflow: this.layoutDoc._singleLine ? "ellipsis" : undefined,
+                    whiteSpace: this.layoutDoc._singleLine ? "nowrap" : "pre-wrap"
                 }} >
                     <div className="labelBox-mainButtonCenter">
                         {StrCast(this.rootDoc.text, StrCast(this.rootDoc.title))}
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index afde524b6..25775edef 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -167,7 +167,7 @@ export class CurrentUserUtils {
             doc["template-icon-view"] = new PrefetchProxy(iconView);
         }
         if (doc["template-icon-view-rtf"] === undefined) {
-            const iconRtfView = Docs.Create.LabelDocument({ title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", _width: 150, _height: 30, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") });
+            const iconRtfView = Docs.Create.LabelDocument({ title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") });
             iconRtfView.isTemplateDoc = makeTemplate(iconRtfView, true, "icon_" + DocumentType.RTF);
             doc["template-icon-view-rtf"] = new PrefetchProxy(iconRtfView);
         }
@@ -214,7 +214,7 @@ export class CurrentUserUtils {
             { title: "Drag a screenshot", label: "Grab", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' },
             { title: "Drag a webcam", label: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' },
             { title: "Drag a audio recorder", label: "Audio", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` },
-            { title: "Drag a clickable button", label: "Btn", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' },
+            { title: "Drag a clickable button", label: "Btn", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding:10, _yPadding: 10, title: "Button" })' },
             { title: "Drag a presentation view", label: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc },
             { title: "Drag a search box", label: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' },
             { title: "Drag a scripting box", label: "Script", icon: "terminal", ignoreClick: true, drag: 'Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250 title: "untitled script" })' },
-- 
cgit v1.2.3-70-g09d2


From 63985ba64dc4a3a94bac75a9120cd8a5ca791fec Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Sun, 26 Apr 2020 11:28:03 -0700
Subject: buxton tweaks

---
 src/client/views/collections/CollectionTreeView.tsx | 7 ++++---
 src/scraping/buxton/final/BuxtonImporter.ts         | 4 ++--
 2 files changed, 6 insertions(+), 5 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 ddd7474bd..7f5dc98f1 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -727,7 +727,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                         }
                     });
                 });
-                const { TextDocument, ImageDocument, CarouselDocument, TreeDocument } = Docs.Create;
+                const { TextDocument, ImageDocument, CarouselDocument } = Docs.Create;
                 const { Document } = this.props;
                 const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
                 const detailedTemplate = `{ "doc": { "type": "doc", "content": [  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] },  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] }  ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`;
@@ -735,9 +735,10 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                 const textDoc = TextDocument("", { title: "details", _autoHeight: true });
                 const detailView = Docs.Create.StackingDocument([
                     CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
-                    textDoc,
+                    // textDoc,
                     TextDocument("", { title: "shortDescription", _autoHeight: true }),
-                    TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true })
+                    // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
+                    TextDocument("", { title: "longDescription", _height: 350 })
                 ], { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" });
                 textDoc.data = new RichTextField(detailedTemplate, "year company");
                 detailView.isTemplateDoc = makeTemplate(detailView);
diff --git a/src/scraping/buxton/final/BuxtonImporter.ts b/src/scraping/buxton/final/BuxtonImporter.ts
index e7a0d367d..122415460 100644
--- a/src/scraping/buxton/final/BuxtonImporter.ts
+++ b/src/scraping/buxton/final/BuxtonImporter.ts
@@ -275,8 +275,8 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont
 
     for (let i = 3; i < captionTargets.length; i += 3) {
         const row = captionTargets.slice(i, i + 3);
-        captions.push(row[1]);
-        embeddedFileNames.push(row[2]);
+        embeddedFileNames.push(row[1]);
+        captions.push(row[2]);
     }
 
     // extract all hyperlinks embedded in the document
-- 
cgit v1.2.3-70-g09d2


From 492e203d95ce9b5aa5e2b2bd7feaf542415a3579 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 26 Apr 2020 21:22:51 -0400
Subject: fixed multi/col/row views to work with templates.  fixed context menu
 subitems to appear on screen. fixed tree view display of text nodes.

---
 src/client/views/ContextMenu.scss                  | 47 +++++++++++++++++-----
 src/client/views/ContextMenuItem.tsx               | 16 +++++---
 .../views/collections/CollectionStackingView.tsx   |  4 +-
 .../views/collections/CollectionTreeView.tsx       | 20 +++++----
 .../CollectionMulticolumnView.tsx                  | 31 +++++++++-----
 .../CollectionMultirowView.tsx                     | 31 +++++++++-----
 src/client/views/nodes/RadialMenu.scss             | 13 ------
 src/client/views/nodes/RadialMenu.tsx              |  9 ++---
 .../authentication/models/current_user_utils.ts    | 28 ++++++++++++-
 9 files changed, 133 insertions(+), 66 deletions(-)

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

diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 8f112de0c..30938688d 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -61,6 +61,42 @@
     letter-spacing: 2px;
     text-transform: uppercase;
     padding-right: 30px;
+
+    .icon-background {
+        pointer-events: all;
+        background-color: transparent;
+        width: 35px;
+        text-align: center;
+        font-size: 20px;
+        margin-left: 5px;
+        margin-top: 5px;
+        margin-bottom: 5px;
+        height: 20px;
+    }
+}
+.contextMenu-description {
+    // width: 11vw; //10vw
+    background: whitesmoke;
+    display: flex; //comment out to allow search icon to be inline with search text
+    justify-content: left;
+    -webkit-touch-callout: none;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    transition: all .1s;
+    border-style: none;
+    // padding: 10px 0px 10px 0px;
+    white-space: nowrap;
+    font-size: 13px;
+    color: grey;
+    letter-spacing: 2px;
+    text-transform: uppercase;
+    padding-right: 30px;
+    margin-top: 5px;
+    height: 20px;
+    margin-bottom: 5px;
 }
 
 .contextMenu-item:hover {
@@ -121,15 +157,4 @@
     padding-left: 10px;
     border: solid black 1px;
     border-radius: 5px;
-}
-
-.icon-background {
-    pointer-events: all;
-    height:100%;
-    margin-top: 15px;
-    background-color: transparent;
-    width: 35px;
-    text-align: center;
-    font-size: 20px;
-    margin-left: 5px;
 }
\ No newline at end of file
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index fef9e5f60..99840047f 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -51,7 +51,8 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
 
     currentTimeout?: any;
     static readonly timeout = 300;
-    onPointerEnter = () => {
+    _overPosY = 0;
+    onPointerEnter = (e: React.MouseEvent) => {
         if (this.currentTimeout) {
             clearTimeout(this.currentTimeout);
             this.currentTimeout = undefined;
@@ -59,6 +60,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
         if (this.overItem) {
             return;
         }
+        this._overPosY = e.clientY;
         this.currentTimeout = setTimeout(action(() => this.overItem = true), ContextMenuItem.timeout);
     }
 
@@ -88,18 +90,22 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
                 </div>
             );
         } else if ("subitems" in this.props) {
+            const where = !this.overItem ? "" : this._overPosY < window.innerHeight / 3 ? "flex-start" : this._overPosY > window.innerHeight * 2 / 3 ? "flex-end" : "center";
+            const marginTop = !this.overItem ? "" : this._overPosY < window.innerHeight / 3 ? "20px" : this._overPosY > window.innerHeight * 2 / 3 ? "-20px" : "";
             const submenu = !this.overItem ? (null) :
-                <div className="contextMenu-subMenu-cont" style={{ marginLeft: "25%", left: "0px" }}>
+                <div className="contextMenu-subMenu-cont" style={{ marginLeft: "25%", left: "0px", marginTop }}>
                     {this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />)}
                 </div>;
             return (
-                <div className={"contextMenu-item" + (this.props.selected ? " contextMenu-itemSelected" : "")} onMouseLeave={this.onPointerLeave} onMouseEnter={this.onPointerEnter}>
+                <div className={"contextMenu-item" + (this.props.selected ? " contextMenu-itemSelected" : "")} style={{ alignItems: where }}
+                    onMouseLeave={this.onPointerLeave} onMouseEnter={this.onPointerEnter}>
                     {this.props.icon ? (
-                        <span className="icon-background" onMouseEnter={this.onPointerLeave}>
+                        <span className="icon-background" onMouseEnter={this.onPointerLeave} style={{ alignItems: "center" }}>
                             <FontAwesomeIcon icon={this.props.icon} size="sm" />
                         </span>
                     ) : null}
-                    <div className="contextMenu-description" onMouseEnter={this.onPointerEnter} >
+                    <div className="contextMenu-description" onMouseEnter={this.onPointerEnter}
+                        style={{ alignItems: "center" }} >
                         {this.props.description}
                         <FontAwesomeIcon icon={faAngleRight} size="lg" style={{ position: "absolute", right: "10px" }} />
                     </div>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 24a3119cc..799bc7f67 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -189,8 +189,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             active={this.props.active}
             whenActiveChanged={this.props.whenActiveChanged}
             addDocTab={this.addDocTab}
-            pinToPres={this.props.pinToPres}>
-        </ContentFittingDocumentView>;
+            pinToPres={this.props.pinToPres}
+        />;
     }
 
     getDocWidth(d?: Doc) {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 7f5dc98f1..218c5705d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -348,7 +348,9 @@ class TreeView extends React.Component<TreeViewProps> {
             </div></ul>;
         } else {
             const layoutDoc = Doc.Layout(this.props.document);
-            return <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id] + this.props.document.title}>
+            const panelHeight = layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight;
+            const panelWidth = layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth;
+            return <div ref={this._dref} style={{ display: "inline-block", height: panelHeight() }} key={this.props.document[Id] + this.props.document.title}>
                 <ContentFittingDocumentView
                     Document={layoutDoc}
                     DataDocument={this.templateDataDoc}
@@ -360,8 +362,8 @@ class TreeView extends React.Component<TreeViewProps> {
                     FreezeDimensions={true}
                     NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
                     NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined}
-                    PanelWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth}
-                    PanelHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight}
+                    PanelWidth={panelWidth}
+                    PanelHeight={panelHeight}
                     getTransform={this.docTransform}
                     CollectionDoc={this.props.containingCollection}
                     CollectionView={undefined}
@@ -727,7 +729,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                         }
                     });
                 });
-                const { TextDocument, ImageDocument, CarouselDocument } = Docs.Create;
+                const { TextDocument, ImageDocument, CarouselDocument, TreeDocument } = Docs.Create;
                 const { Document } = this.props;
                 const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
                 const detailedTemplate = `{ "doc": { "type": "doc", "content": [  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] },  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] }  ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`;
@@ -735,10 +737,12 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                 const textDoc = TextDocument("", { title: "details", _autoHeight: true });
                 const detailView = Docs.Create.StackingDocument([
                     CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
-                    // textDoc,
-                    TextDocument("", { title: "shortDescription", _autoHeight: true }),
-                    // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
-                    TextDocument("", { title: "longDescription", _height: 350 })
+                    TreeDocument([
+                        // textDoc,
+                        TextDocument("", { title: "shortDescription", _autoHeight: true }),
+                        // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
+                        TextDocument("", { title: "longDescription", _height: 350 })
+                    ], { title: "stuff", _height: 100 })
                 ], { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" });
                 textDoc.data = new RichTextField(detailedTemplate, "year company");
                 detailView.isTemplateDoc = makeTemplate(detailView);
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 0e1cc2010..9d09ecc3b 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -5,7 +5,7 @@ import { Doc } from '../../../../new_fields/Doc';
 import { documentSchema } from '../../../../new_fields/documentSchemas';
 import { makeInterface } from '../../../../new_fields/Schema';
 import { BoolCast, NumCast, ScriptCast, StrCast, Cast } from '../../../../new_fields/Types';
-import { DragManager } from '../../../util/DragManager';
+import { DragManager, dropActionType } from '../../../util/DragManager';
 import { Transform } from '../../../util/Transform';
 import { undoBatch } from '../../../util/UndoManager';
 import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView';
@@ -214,21 +214,32 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
     }
     getDisplayDoc(layout: Doc, dxf: () => Transform, width: () => number, height: () => number) {
         return <ContentFittingDocumentView
-            {...this.props}
             Document={layout}
             DataDocument={layout.resolvedDataDoc as Doc}
-            NativeHeight={returnZero}
-            NativeWidth={returnZero}
-            addDocTab={this.addDocTab}
-            fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
-            FreezeDimensions={BoolCast(this.props.Document._freezeChildDimensions)}
             backgroundColor={this.props.backgroundColor}
-            CollectionDoc={this.props.Document}
+            LayoutDoc={this.props.childLayoutTemplate}
+            LibraryPath={this.props.LibraryPath}
+            FreezeDimensions={this.props.freezeChildDimensions}
+            renderDepth={this.props.renderDepth + 1}
             PanelWidth={width}
             PanelHeight={height}
-            getTransform={dxf}
+            NativeHeight={returnZero}
+            NativeWidth={returnZero}
+            fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
+            rootSelected={this.rootSelected}
+            dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
             onClick={this.onChildClickHandler}
-            renderDepth={this.props.renderDepth + 1}
+            getTransform={dxf}
+            focus={this.props.focus}
+            CollectionDoc={this.props.CollectionView?.props.Document}
+            CollectionView={this.props.CollectionView}
+            addDocument={this.props.addDocument}
+            moveDocument={this.props.moveDocument}
+            removeDocument={this.props.removeDocument}
+            active={this.props.active}
+            whenActiveChanged={this.props.whenActiveChanged}
+            addDocTab={this.addDocTab}
+            pinToPres={this.props.pinToPres}
         />;
     }
     /**
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 1eb486c4f..af0cc3b5c 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -13,7 +13,7 @@ import { Transform } from '../../../util/Transform';
 import HeightLabel from './MultirowHeightLabel';
 import ResizeBar from './MultirowResizer';
 import { undoBatch } from '../../../util/UndoManager';
-import { DragManager } from '../../../util/DragManager';
+import { DragManager, dropActionType } from '../../../util/DragManager';
 import { List } from '../../../../new_fields/List';
 
 type MultirowDocument = makeInterface<[typeof documentSchema]>;
@@ -214,21 +214,32 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
     }
     getDisplayDoc(layout: Doc, dxf: () => Transform, width: () => number, height: () => number) {
         return <ContentFittingDocumentView
-            {...this.props}
             Document={layout}
             DataDocument={layout.resolvedDataDoc as Doc}
-            NativeHeight={returnZero}
-            NativeWidth={returnZero}
-            addDocTab={this.addDocTab}
-            fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
-            FreezeDimensions={BoolCast(this.props.Document._freezeChildDimensions)}
             backgroundColor={this.props.backgroundColor}
-            CollectionDoc={this.props.Document}
+            LayoutDoc={this.props.childLayoutTemplate}
+            LibraryPath={this.props.LibraryPath}
+            FreezeDimensions={this.props.freezeChildDimensions}
+            renderDepth={this.props.renderDepth + 1}
             PanelWidth={width}
             PanelHeight={height}
-            getTransform={dxf}
+            NativeHeight={returnZero}
+            NativeWidth={returnZero}
+            fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
+            rootSelected={this.rootSelected}
+            dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
             onClick={this.onChildClickHandler}
-            renderDepth={this.props.renderDepth + 1}
+            getTransform={dxf}
+            focus={this.props.focus}
+            CollectionDoc={this.props.CollectionView?.props.Document}
+            CollectionView={this.props.CollectionView}
+            addDocument={this.props.addDocument}
+            moveDocument={this.props.moveDocument}
+            removeDocument={this.props.removeDocument}
+            active={this.props.active}
+            whenActiveChanged={this.props.whenActiveChanged}
+            addDocTab={this.addDocTab}
+            pinToPres={this.props.pinToPres}
         />;
     }
     /**
diff --git a/src/client/views/nodes/RadialMenu.scss b/src/client/views/nodes/RadialMenu.scss
index ce0c263ef..daa620d12 100644
--- a/src/client/views/nodes/RadialMenu.scss
+++ b/src/client/views/nodes/RadialMenu.scss
@@ -67,17 +67,4 @@ s
     margin-left: 5px;
     text-align: left;
     display: inline; //need this?
-}
-
-
-
-.icon-background {
-    pointer-events: all;
-    height:100%;
-    margin-top: 15px;
-    background-color: transparent;
-    width: 35px;
-    text-align: center;
-    font-size: 20px;
-    margin-left: 5px;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/RadialMenu.tsx b/src/client/views/nodes/RadialMenu.tsx
index 0ffed78de..ddfdb67b4 100644
--- a/src/client/views/nodes/RadialMenu.tsx
+++ b/src/client/views/nodes/RadialMenu.tsx
@@ -1,12 +1,9 @@
 import React = require("react");
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { action, observable, computed, IReactionDisposer, reaction, runInAction } from "mobx";
-import { RadialMenuItem, RadialMenuProps } from "./RadialMenuItem";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import Measure from "react-measure";
-import "./RadialMenu.scss";
-import MobileInkOverlay from "../../../mobile/MobileInkOverlay";
 import MobileInterface from "../../../mobile/MobileInterface";
+import "./RadialMenu.scss";
+import { RadialMenuItem, RadialMenuProps } from "./RadialMenuItem";
 
 @observer
 export class RadialMenu extends React.Component {
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 25775edef..76aa51f63 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -82,8 +82,34 @@ export class CurrentUserUtils {
             });
         }
 
+        if (doc["template-button-detail"] === undefined) {
+            const { TextDocument, ImageDocument, CarouselDocument, TreeDocument } = Docs.Create;
+            const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
+            const detailedTemplate = `{ "doc": { "type": "doc", "content": [  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] },  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] }  ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`;
+
+            const textDoc = TextDocument("", { title: "details", _autoHeight: true });
+            const detailView = Docs.Create.MultirowDocument([
+                CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
+                TreeDocument([
+                    // textDoc,
+                    TextDocument("", { title: "short description", _autoHeight: true }),
+                    // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
+                    TextDocument("", { title: "long description", _height: 350 })
+                ], { title: "stuff", _height: 100 })
+            ], { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" });
+            textDoc.data = new RichTextField(detailedTemplate, "year company");
+            detailView.isTemplateDoc = makeTemplate(detailView);
+
+            doc["template-button-detail"] = CurrentUserUtils.ficon({
+                onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
+                dragFactory: new PrefetchProxy(detailView) as any as Doc,
+                removeDropProperties: new List<string>(["dropAction"]), title: "detail view", icon: "window-maximize"
+            });
+        }
+
         if (doc["template-buttons"] === undefined) {
-            doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument([doc["template-button-slides"] as Doc, doc["template-button-description"] as Doc, doc["template-button-query"] as Doc], {
+            doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument([doc["template-button-slides"] as Doc, doc["template-button-description"] as Doc,
+            doc["template-button-query"] as Doc, doc["template-button-detail"] as Doc], {
                 title: "Compound Item Creators", _xMargin: 0, _showTitle: "title",
                 _autoHeight: true, _width: 500, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
-- 
cgit v1.2.3-70-g09d2


From c75ffd4900acea74c55b6bf275a5e8082c15d573 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Sun, 26 Apr 2020 19:29:50 -0700
Subject: formatted textbox disposers refactor, paragraph chunked rich text
 initialization and buxton importer updates

---
 src/client/documents/Documents.ts                  |  1 +
 .../views/collections/CollectionTreeView.tsx       | 21 ++++++--
 src/client/views/nodes/FormattedTextBox.tsx        | 60 ++++++++--------------
 src/scraping/buxton/final/BuxtonImporter.ts        | 17 +++---
 4 files changed, 49 insertions(+), 50 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1268c97b0..6bd2eee3c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -407,6 +407,7 @@ export namespace Docs {
                     const doc = StackingDocument(deviceImages, { title: device.title, _LODdisable: true });
                     const deviceProto = Doc.GetProto(doc);
                     deviceProto.hero = new ImageField(constructed[0].url);
+                    deviceProto.fontFamily = "Arial";
                     Docs.Get.FromJson({ data: device, appendToExisting: { targetDoc: deviceProto } });
                     Doc.AddDocToList(parentProto, "data", doc);
                 } else if (errors) {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 7f5dc98f1..49eb90bc2 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -730,18 +730,31 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                 const { TextDocument, ImageDocument, CarouselDocument } = Docs.Create;
                 const { Document } = this.props;
                 const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
-                const detailedTemplate = `{ "doc": { "type": "doc", "content": [  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] },  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] }  ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`;
 
                 const textDoc = TextDocument("", { title: "details", _autoHeight: true });
                 const detailView = Docs.Create.StackingDocument([
                     CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
-                    // textDoc,
+                    textDoc,
                     TextDocument("", { title: "shortDescription", _autoHeight: true }),
-                    // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
                     TextDocument("", { title: "longDescription", _height: 350 })
+                    // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
                 ], { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" });
-                textDoc.data = new RichTextField(detailedTemplate, "year company");
+                // const detailView = Cast(Cast(Doc.UserDoc()["template-button-detail"], Doc, null)?.dragFactor, Doc, null);
                 detailView.isTemplateDoc = makeTemplate(detailView);
+                detailView.fontFamily = "Arial";
+
+                const buxtonFieldKeys = ["year", "originalPrice", "degreesOfFreedom", "company", "attribute", "primaryKey", "secondaryKey", "dimensions"];
+                const detailedTemplate = {
+                    doc: {
+                        type: "doc", content: buxtonFieldKeys.map(fieldKey => ({
+                            type: "paragraph",
+                            content: [{ type: "dashField", attrs: { fieldKey } }]
+                        }))
+                    },
+                    selection: { type: "text", anchor: 1, head: 1 },
+                    storedMarks: []
+                };
+                textDoc.data = new RichTextField(JSON.stringify(detailedTemplate), buxtonFieldKeys.join(" "));
 
                 const heroView = ImageDocument(fallbackImg, { title: "heroView", isTemplateDoc: true, isTemplateForField: "hero", }); // this acts like a template doc and a template field ... a little weird, but seems to work?
                 heroView.proto!.layout = ImageBox.LayoutString("hero");
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 425af8ccf..dd0df9f3f 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -83,17 +83,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     private _lastX = 0;
     private _lastY = 0;
     private _undoTyping?: UndoManager.Batch;
-    private _searchReactionDisposer?: Lambda;
-    private _recordReactionDisposer: Opt<IReactionDisposer>;
-    private _scrollToRegionReactionDisposer: Opt<IReactionDisposer>;
-    private _reactionDisposer: Opt<IReactionDisposer>;
-    private _heightReactionDisposer: Opt<IReactionDisposer>;
-    private _proxyReactionDisposer: Opt<IReactionDisposer>;
-    private _pullReactionDisposer: Opt<IReactionDisposer>;
-    private _pushReactionDisposer: Opt<IReactionDisposer>;
-    private _buttonBarReactionDisposer: Opt<IReactionDisposer>;
-    private _linkMakerDisposer: Opt<IReactionDisposer>;
-    private _scrollDisposer: Opt<IReactionDisposer>;
+    private _disposers: { [name: string]: IReactionDisposer } = {};
     private dropDisposer?: DragManager.DragDropDisposer;
 
     @computed get _recording() { return this.dataDoc.audioState === "recording"; }
@@ -564,7 +554,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         }
     }
     componentDidMount() {
-        this._buttonBarReactionDisposer = reaction(
+        this._disposers.buttonBar = reaction(
             () => DocumentButtonBar.Instance,
             instance => {
                 if (instance) {
@@ -573,7 +563,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 }
             }
         );
-        this._linkMakerDisposer = reaction(
+        this._disposers.linkMaker = reaction(
             () => this.props.makeLink?.(),
             (linkDoc: Opt<Doc>) => {
                 if (linkDoc) {
@@ -584,8 +574,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             },
             { fireImmediately: true }
         );
-
-        this._reactionDisposer = reaction(
+        this._disposers.editorState = reaction(
             () => {
                 if (this.dataDoc[this.props.fieldKey + "-noTemplate"] || !this.props.Document[this.props.fieldKey + "-textTemplate"]) {
                     return Cast(this.dataDoc[this.props.fieldKey], RichTextField, null)?.Data;
@@ -600,8 +589,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 }
             }
         );
-
-        this._pullReactionDisposer = reaction(
+        this._disposers.pullDoc = reaction(
             () => this.props.Document[Pulls],
             () => {
                 if (!DocumentButtonBar.hasPulledHack) {
@@ -611,8 +599,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 }
             }
         );
-
-        this._pushReactionDisposer = reaction(
+        this._disposers.pushDoc = reaction(
             () => this.props.Document[Pushes],
             () => {
                 if (!DocumentButtonBar.hasPushedHack) {
@@ -621,19 +608,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 }
             }
         );
-
-        this._heightReactionDisposer = reaction(
+        this._disposers.height = reaction(
             () => [this.layoutDoc[WidthSym](), this.layoutDoc._autoHeight],
             () => this.tryUpdateHeight()
         );
 
         this.setupEditor(this.config, this.props.fieldKey);
 
-        this._searchReactionDisposer = reaction(() => this.rootDoc.searchMatch,
+        this._disposers.search = reaction(() => this.rootDoc.searchMatch,
             search => search ? this.highlightSearchTerms([Doc.SearchQuery()]) : this.unhighlightSearchTerms(),
             { fireImmediately: true });
 
-        this._recordReactionDisposer = reaction(() => this._recording,
+        this._disposers.record = reaction(() => this._recording,
             () => {
                 if (this._recording) {
                     setTimeout(action(() => {
@@ -643,8 +629,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 } else setTimeout(() => this.stopDictation(true), 0);
             }
         );
-
-        this._scrollToRegionReactionDisposer = reaction(
+        this._disposers.scrollToRegion = reaction(
             () => StrCast(this.layoutDoc.scrollToLinkID),
             async (scrollToLinkID) => {
                 const findLinkFrag = (frag: Fragment, editor: EditorView) => {
@@ -689,8 +674,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             },
             { fireImmediately: true }
         );
-
-        this._scrollDisposer = reaction(() => NumCast(this.props.Document.scrollPos),
+        this._disposers.scroll = reaction(() => NumCast(this.props.Document.scrollPos),
             pos => this._scrollRef.current && this._scrollRef.current.scrollTo({ top: pos }), { fireImmediately: true }
         );
 
@@ -876,7 +860,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             });
             const startupText = !rtfField && this._editorView && Field.toString(this.dataDoc[fieldKey] as Field);
             if (startupText) {
-                this._editorView.dispatch(this._editorView.state.tr.insertText(startupText));
+                const paragraphSegments = startupText.split("\n\n");
+                const { state: { tr }, dispatch } = this._editorView;
+                if (paragraphSegments.length) {
+                    for (const paragraph of paragraphSegments) {
+                        dispatch(tr.insertText(paragraph));
+                    }
+                } else {
+                    dispatch(tr.insertText(startupText));
+                }
             }
         }
 
@@ -906,17 +898,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     componentWillUnmount() {
-        this._scrollDisposer?.();
-        this._scrollToRegionReactionDisposer?.();
-        this._reactionDisposer?.();
-        this._proxyReactionDisposer?.();
-        this._pushReactionDisposer?.();
-        this._pullReactionDisposer?.();
-        this._heightReactionDisposer?.();
-        this._searchReactionDisposer?.();
-        this._recordReactionDisposer?.();
-        this._buttonBarReactionDisposer?.();
-        this._linkMakerDisposer?.();
+        Object.values(this._disposers).forEach(disposer => disposer?.());
         this._editorView?.destroy();
     }
 
diff --git a/src/scraping/buxton/final/BuxtonImporter.ts b/src/scraping/buxton/final/BuxtonImporter.ts
index 122415460..64b988610 100644
--- a/src/scraping/buxton/final/BuxtonImporter.ts
+++ b/src/scraping/buxton/final/BuxtonImporter.ts
@@ -16,6 +16,7 @@ interface DocumentContents {
     hyperlinks: string[];
     captions: string[];
     embeddedFileNames: string[];
+    longDescriptionParagraphs: string[];
 }
 
 export interface DeviceDocument {
@@ -186,10 +187,6 @@ const RegexMap = new Map<keyof DeviceDocument, Processor<any>>([
         exp: /Short Description:\s+(.*)Bill Buxton[’']s Notes/,
         transformer: Utilities.correctSentences
     }],
-    ["longDescription", {
-        exp: /Bill Buxton[’']s Notes(.*)Device Details/,
-        transformer: Utilities.correctSentences
-    }],
 ]);
 
 const sourceDir = path.resolve(__dirname, "source");
@@ -267,7 +264,12 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont
     const body = document.root()?.text() ?? "No body found. Check the import script's XML parser.";
     const captions: string[] = [];
     const embeddedFileNames: string[] = [];
-    const captionTargets = document.find(tableCellXPath).map(node => node.text());
+    const captionTargets = document.find(tableCellXPath).map(node => node.text().trim());
+
+    const paragraphs = document.find('//*[name()="w:p"]').map(node => Utilities.correctSentences(node.text()).transformed!);
+    const start = paragraphs.indexOf(paragraphs.find(el => /Bill Buxton[’']s Notes/.test(el))!) + 1;
+    const end = paragraphs.indexOf("Device Details");
+    const longDescriptionParagraphs = paragraphs.slice(start, end);
 
     const { length } = captionTargets;
     strictEqual(length > 3, true, "No captions written.");
@@ -290,7 +292,7 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont
 
     zip.close();
 
-    return { body, imageData, captions, embeddedFileNames, hyperlinks };
+    return { body, longDescriptionParagraphs, imageData, captions, embeddedFileNames, hyperlinks };
 }
 
 const imageEntry = /^word\/media\/\w+\.(jpeg|jpg|png|gif)/;
@@ -337,7 +339,7 @@ async function writeImages(zip: any): Promise<ImageData[]> {
 }
 
 function analyze(fileName: string, contents: DocumentContents): AnalysisResult {
-    const { body, imageData, captions, hyperlinks, embeddedFileNames } = contents;
+    const { body, imageData, captions, hyperlinks, embeddedFileNames, longDescriptionParagraphs } = contents;
     const device: any = {
         hyperlinks,
         captions,
@@ -376,6 +378,7 @@ function analyze(fileName: string, contents: DocumentContents): AnalysisResult {
         return { errors };
     }
 
+    device.longDescription = longDescriptionParagraphs.join("\n\n");
     return { device };
 }
 
-- 
cgit v1.2.3-70-g09d2


From fc470b25759e8f051dc527066f9bebcaf5e7707d Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Sun, 26 Apr 2020 23:55:23 -0700
Subject: various buxton fixes

---
 src/client/documents/Documents.ts                  |  1 -
 .../views/collections/CollectionTreeView.tsx       | 24 ++++++++--------
 src/client/views/nodes/DocumentContentsView.tsx    |  8 +++---
 src/client/views/nodes/FormattedTextBox.tsx        |  9 +-----
 src/scraping/buxton/final/BuxtonImporter.ts        | 32 ++++++++++++----------
 5 files changed, 36 insertions(+), 38 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1651a6d55..5e0890e76 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -408,7 +408,6 @@ export namespace Docs {
                     const doc = StackingDocument(deviceImages, { title: device.title, _LODdisable: true });
                     const deviceProto = Doc.GetProto(doc);
                     deviceProto.hero = new ImageField(constructed[0].url);
-                    deviceProto.fontFamily = "Arial";
                     Docs.Get.FromJson({ data: device, appendToExisting: { targetDoc: deviceProto } });
                     Doc.AddDocToList(parentProto, "data", doc);
                 } else if (errors) {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 362d43ee7..dcb5e116c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -733,19 +733,21 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                 const { Document } = this.props;
                 const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
 
+                const carousel = CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" });
                 const textDoc = TextDocument("", { title: "details", _autoHeight: true });
-                const detailView = Docs.Create.StackingDocument([
-                    CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
-                    TreeDocument([
-                        // textDoc,
-                        TextDocument("", { title: "shortDescription", _autoHeight: true }),
-                        // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
-                        TextDocument("", { title: "longDescription", _height: 350 })
-                    ], { title: "stuff", _height: 100 })
-                ], { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" });
-                // const detailView = Cast(Cast(Doc.UserDoc()["template-button-detail"], Doc, null)?.dragFactor, Doc, null);
+                const short = TextDocument("", { title: "shortDescription", _autoHeight: true });
+                const long = TextDocument("", { title: "longDescription", _height: 350 });
+                long.treeViewExpandedView = "layout";
+                const long_wrapper = TreeDocument([long], { title: "Descriptions", _height: 350 });
+
+                // const narratives = TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
+                // const detailView = Cast(Cast(Doc.UserDoc()["template-button-detail"], Doc, null)?.dragFactory, Doc, null);
+
+                textDoc.fontFamily = short.fontFamily = long.fontFamily = carousel.fontFamily = "Arial";
+
+                const detailViewOpts = { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" };
+                const detailView = Docs.Create.StackingDocument([carousel, textDoc, short, long_wrapper], detailViewOpts);
                 detailView.isTemplateDoc = makeTemplate(detailView);
-                detailView.fontFamily = "Arial";
 
                 const buxtonFieldKeys = ["year", "originalPrice", "degreesOfFreedom", "company", "attribute", "primaryKey", "secondaryKey", "dimensions"];
                 const detailedTemplate = {
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 8582f92ed..cd78ac7b3 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -78,7 +78,7 @@ export class HTMLtag extends React.Component<HTMLtagProps> {
         const style: { [key: string]: any } = {};
         const divKeys = OmitKeys(this.props, ["children", "htmltag", "RootDoc", "Document", "key", "onInput", "onClick", "__proto__"]).omit;
         Object.keys(divKeys).map((prop: string) => {
-            let p = (this.props as any)[prop] as string;
+            const p = (this.props as any)[prop] as string;
             const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a propery expression string:  { script }  into a value
                 return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ self: this.props.RootDoc, this: this.props.Document }).result as string || "";
             };
@@ -178,9 +178,9 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
             }
             return undefined;
             // add input function to props
-        }
-        let onClick = makeFuncProp("onClick");
-        let onInput = makeFuncProp("onInput");
+        };
+        const onClick = makeFuncProp("onClick");
+        const onInput = makeFuncProp("onInput");
 
         const bindings = this.CreateBindings(onClick, onInput);
         //  layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 8d4b90c41..d98172823 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -860,15 +860,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             });
             const startupText = !rtfField && this._editorView && Field.toString(this.dataDoc[fieldKey] as Field);
             if (startupText) {
-                const paragraphSegments = startupText.split("\n\n");
                 const { state: { tr }, dispatch } = this._editorView;
-                if (paragraphSegments.length) {
-                    for (const paragraph of paragraphSegments) {
-                        dispatch(tr.insertText(paragraph));
-                    }
-                } else {
-                    dispatch(tr.insertText(startupText));
-                }
+                dispatch(tr.insertText(startupText));
             }
         }
 
diff --git a/src/scraping/buxton/final/BuxtonImporter.ts b/src/scraping/buxton/final/BuxtonImporter.ts
index 64b988610..713207a07 100644
--- a/src/scraping/buxton/final/BuxtonImporter.ts
+++ b/src/scraping/buxton/final/BuxtonImporter.ts
@@ -16,7 +16,7 @@ interface DocumentContents {
     hyperlinks: string[];
     captions: string[];
     embeddedFileNames: string[];
-    longDescriptionParagraphs: string[];
+    longDescription: string;
 }
 
 export interface DeviceDocument {
@@ -269,7 +269,7 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont
     const paragraphs = document.find('//*[name()="w:p"]').map(node => Utilities.correctSentences(node.text()).transformed!);
     const start = paragraphs.indexOf(paragraphs.find(el => /Bill Buxton[’']s Notes/.test(el))!) + 1;
     const end = paragraphs.indexOf("Device Details");
-    const longDescriptionParagraphs = paragraphs.slice(start, end);
+    const longDescription = paragraphs.slice(start, end).filter(paragraph => paragraph.length).join("\n\n");
 
     const { length } = captionTargets;
     strictEqual(length > 3, true, "No captions written.");
@@ -292,7 +292,7 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont
 
     zip.close();
 
-    return { body, longDescriptionParagraphs, imageData, captions, embeddedFileNames, hyperlinks };
+    return { body, longDescription, imageData, captions, embeddedFileNames, hyperlinks };
 }
 
 const imageEntry = /^word\/media\/\w+\.(jpeg|jpg|png|gif)/;
@@ -308,26 +308,30 @@ async function writeImages(zip: any): Promise<ImageData[]> {
     const imageEntries = allEntries.filter(name => imageEntry.test(name));
 
     const imageUrls: ImageData[] = [];
-    for (const mediaPath of imageEntries) {
-        const getImageStream = () => new Promise<Readable>((resolve, reject) => {
-            zip.stream(mediaPath, (error: any, stream: any) => error ? reject(error) : resolve(stream));
-        });
+    const valid: any[] = [];
+
+    const getImageStream = (mediaPath: string) => new Promise<Readable>((resolve, reject) => {
+        zip.stream(mediaPath, (error: any, stream: any) => error ? reject(error) : resolve(stream));
+    });
 
+    for (const mediaPath of imageEntries) {
         const { width, height, type } = await new Promise<Dimensions>(async resolve => {
             const sizeStream = (createImageSizeStream() as PassThrough).on('size', (dimensions: Dimensions) => {
                 readStream.destroy();
                 resolve(dimensions);
             }).on("error", () => readStream.destroy());
-            const readStream = await getImageStream();
+            const readStream = await getImageStream(mediaPath);
             readStream.pipe(sizeStream);
         });
-        if (Math.abs(width - height) < 10) {
-            continue;
+
+        if (Math.abs(width - height) > 10) {
+            valid.push({ width, height, type, mediaPath });
         }
+    }
 
+    for (const { type, width, height, mediaPath } of valid) {
         const generatedFileName = `upload_${Utils.GenerateGuid()}.${type.toLowerCase()}`;
-        await DashUploadUtils.outputResizedImages(getImageStream, generatedFileName, imageDir);
-
+        await DashUploadUtils.outputResizedImages(() => getImageStream(mediaPath), generatedFileName, imageDir);
         imageUrls.push({
             url: `/files/images/buxton/${generatedFileName}`,
             nativeWidth: width,
@@ -339,11 +343,12 @@ async function writeImages(zip: any): Promise<ImageData[]> {
 }
 
 function analyze(fileName: string, contents: DocumentContents): AnalysisResult {
-    const { body, imageData, captions, hyperlinks, embeddedFileNames, longDescriptionParagraphs } = contents;
+    const { body, imageData, captions, hyperlinks, embeddedFileNames, longDescription } = contents;
     const device: any = {
         hyperlinks,
         captions,
         embeddedFileNames,
+        longDescription,
         __images: imageData
     };
     const errors: { [key: string]: string } = { fileName };
@@ -378,7 +383,6 @@ function analyze(fileName: string, contents: DocumentContents): AnalysisResult {
         return { errors };
     }
 
-    device.longDescription = longDescriptionParagraphs.join("\n\n");
     return { device };
 }
 
-- 
cgit v1.2.3-70-g09d2


From 436719e0d5f37a46a981287f4c3e903563663567 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Mon, 27 Apr 2020 00:44:23 -0700
Subject: merged detailView templates, now only exists in current_user_utils

---
 .../views/collections/CollectionTreeView.tsx       | 33 +---------------
 .../authentication/models/current_user_utils.ts    | 44 ++++++++++++++--------
 2 files changed, 30 insertions(+), 47 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 dcb5e116c..d938bd7ad 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -729,39 +729,10 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                         }
                     });
                 });
-                const { TextDocument, ImageDocument, CarouselDocument, TreeDocument } = Docs.Create;
+                const { ImageDocument } = Docs.Create;
                 const { Document } = this.props;
                 const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif";
-
-                const carousel = CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" });
-                const textDoc = TextDocument("", { title: "details", _autoHeight: true });
-                const short = TextDocument("", { title: "shortDescription", _autoHeight: true });
-                const long = TextDocument("", { title: "longDescription", _height: 350 });
-                long.treeViewExpandedView = "layout";
-                const long_wrapper = TreeDocument([long], { title: "Descriptions", _height: 350 });
-
-                // const narratives = TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
-                // const detailView = Cast(Cast(Doc.UserDoc()["template-button-detail"], Doc, null)?.dragFactory, Doc, null);
-
-                textDoc.fontFamily = short.fontFamily = long.fontFamily = carousel.fontFamily = "Arial";
-
-                const detailViewOpts = { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" };
-                const detailView = Docs.Create.StackingDocument([carousel, textDoc, short, long_wrapper], detailViewOpts);
-                detailView.isTemplateDoc = makeTemplate(detailView);
-
-                const buxtonFieldKeys = ["year", "originalPrice", "degreesOfFreedom", "company", "attribute", "primaryKey", "secondaryKey", "dimensions"];
-                const detailedTemplate = {
-                    doc: {
-                        type: "doc", content: buxtonFieldKeys.map(fieldKey => ({
-                            type: "paragraph",
-                            content: [{ type: "dashField", attrs: { fieldKey } }]
-                        }))
-                    },
-                    selection: { type: "text", anchor: 1, head: 1 },
-                    storedMarks: []
-                };
-                textDoc.data = new RichTextField(JSON.stringify(detailedTemplate), buxtonFieldKeys.join(" "));
-
+                const detailView = Cast(Cast(Doc.UserDoc()["template-button-detail"], Doc, null)?.dragFactory, Doc, null);
                 const heroView = ImageDocument(fallbackImg, { title: "heroView", isTemplateDoc: true, isTemplateForField: "hero", }); // this acts like a template doc and a template field ... a little weird, but seems to work?
                 heroView.proto!.layout = ImageBox.LayoutString("hero");
                 heroView._showTitle = "title";
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 627f3b324..5535f4bcf 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -83,23 +83,35 @@ export class CurrentUserUtils {
         }
 
         if (doc["template-button-detail"] === undefined) {
-            const { TextDocument, ImageDocument, MasonryDocument, StackingDocument, CarouselDocument, TreeDocument } = Docs.Create;
-            const detailedTemplate = `{ "doc": { "type": "doc", "content": [  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] },  { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] }  ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`;
-
-            const textDoc1 = TextDocument("", { title: "shortDescription", treeViewOpen: true, treeViewExpandedView: "layout", _height: 50 });
-            const textDoc2 = TextDocument("", { title: "longDescription", treeViewOpen: false, treeViewExpandedView: "layout", _height: 350 });
-            const detailView = Docs.Create.StackingDocument([
-                CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
-                MasonryDocument([
-                    textDoc1,
-                    textDoc2,
-                    // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
-                ], { title: "stuff", _height: 300, _xMargin: 0, _autoHeight: true, columnWidth: -1, _chromeStatus: "disabled", treeViewHideTitle: true, _pivotField: "title" })
-            ], { _chromeStatus: "disabled", _width: 300, _autoHeight: true, _xMargin: 0, _fontFamily: "Comic Sans MS", _fontSize: 12, title: "detailView" });
-            textDoc1.text = new RichTextField(detailedTemplate, "year company");
+            const { TextDocument, MasonryDocument, CarouselDocument } = Docs.Create;
+
+            const carousel = CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" });
+
+            const short = TextDocument("", { title: "shortDescription", treeViewOpen: true, treeViewExpandedView: "layout", _height: 50 });
+            const long = TextDocument("", { title: "longDescription", treeViewOpen: false, treeViewExpandedView: "layout", _height: 350 });
+            short.title = "A Short Description";
+            long.title = "Long Description";
+
+            const shared = { _chromeStatus: "disabled", _autoHeight: true, _xMargin: 0 };
+            const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: 12 };
+            const descriptionWrapperOpts = { title: "descriptions", _height: 300, columnWidth: -1, treeViewHideTitle: true, _pivotField: "title" };
+
+            const descriptionWrapper = MasonryDocument([short, long], { ...shared, ...descriptionWrapperOpts });
+            const detailView = Docs.Create.StackingDocument([carousel, descriptionWrapper], { ...shared, ...detailViewOpts });
             detailView.isTemplateDoc = makeTemplate(detailView);
-            textDoc1.title = "A Short Description";
-            textDoc2.title = "Long Description";
+
+            const buxtonFieldKeys = ["year", "originalPrice", "degreesOfFreedom", "company", "attribute", "primaryKey", "secondaryKey", "dimensions"];
+            const detailedTemplate = {
+                doc: {
+                    type: "doc", content: buxtonFieldKeys.map(fieldKey => ({
+                        type: "paragraph",
+                        content: [{ type: "dashField", attrs: { fieldKey } }]
+                    }))
+                },
+                selection: { type: "text", anchor: 1, head: 1 },
+                storedMarks: []
+            };
+            short.text = new RichTextField(JSON.stringify(detailedTemplate), buxtonFieldKeys.join(" "));
 
             doc["template-button-detail"] = CurrentUserUtils.ficon({
                 onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
-- 
cgit v1.2.3-70-g09d2

