From 1c5c84c91742ff7822194519f536338bf96e6453 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Mon, 29 Jul 2019 13:58:36 -0400
Subject: fixed things to chrome and stacking view styling

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

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

diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 387e189e7..c45b0c60a 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -266,7 +266,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
                     style={{
-                        padding: singleColumn ? `${style.yMargin}px ${0}px ${style.yMargin}px ${0}px` : `${style.yMargin}px ${0}px`,
+                        padding: singleColumn ? `${style.yMargin}px ${5}px ${style.yMargin}px ${5}px` : `${style.yMargin}px ${0}px`,
                         margin: "auto",
                         width: "max-content", //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
                         height: 'max-content',
-- 
cgit v1.2.3-70-g09d2


From 5fff8155b3102e76feb718c4f67c6e85050aab6e Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Mon, 29 Jul 2019 14:50:43 -0400
Subject: stacking view background color to inherit

---
 src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index c45b0c60a..30177ebd7 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -34,7 +34,7 @@ interface CSVFieldColumnProps {
 
 @observer
 export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldColumnProps> {
-    @observable private _background = "white";
+    @observable private _background = "inherit";
 
     private _dropRef: HTMLDivElement | null = null;
     private dropDisposer?: DragManager.DragDropDisposer;
@@ -158,7 +158,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
 
     @action
     pointerLeave = () => {
-        this._background = "white";
+        this._background = "inherit";
     }
 
     @action
-- 
cgit v1.2.3-70-g09d2


From 93df48fe22f4152878e3a74e0366668fbbab895e Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Mon, 29 Jul 2019 14:51:50 -0400
Subject: fixed document decorations when chrome expanded on stacking view

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

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

diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 30177ebd7..aa86d9a54 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -111,7 +111,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         let outerXf = Utils.GetScreenTransform(this.props.parent._masonryGridRef!);
         let offset = this.props.parent.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
         return this.props.parent.props.ScreenToLocalTransform().
-            translate(offset[0], offset[1] - (this.props.parent.chromeCollapsed ? 0 : 100)).
+            translate(offset[0], offset[1]).
             scale(NumCast(doc.width, 1) / this.props.parent.columnWidth);
     }
 
-- 
cgit v1.2.3-70-g09d2


From 1b672029cdcbd56b312891b5f0d78eaaa8c78b28 Mon Sep 17 00:00:00 2001
From: kimdahey <claire_kim1@brown.edu>
Date: Mon, 29 Jul 2019 14:56:05 -0400
Subject: + ADD / ADD GROUP does not show if chromeStatus is disabled

---
 src/client/views/collections/CollectionStackingView.tsx          | 2 +-
 .../views/collections/CollectionStackingViewFieldColumn.tsx      | 9 +++++----
 2 files changed, 6 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 287c8a461..85aa322a2 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -287,7 +287,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
                     map(section => this.section(section[0], section[1])) :
                     this.section(undefined, this.filteredChildren)}
-                {this.props.Document.sectionFilter ?
+                {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
                     <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
                         style={{ width: (this.columnWidth / (headings.length + 1)) - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index c45b0c60a..6b94efb1c 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -279,10 +279,11 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                     {this.children(this.props.docList)}
                     {singleColumn ? (null) : this.props.parent.columnDragger}
                 </div>
-                <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
-                    style={{ width: style.columnWidth / (uniqueHeadings.length + 1) }}>
-                    <EditableView {...newEditableViewProps} />
-                </div>
+                {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+                    <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
+                        style={{ width: style.columnWidth / (uniqueHeadings.length + 1) }}>
+                        <EditableView {...newEditableViewProps} />
+                    </div> : null}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From c19fc89ebbaec30ff284988b7234815d822bbe0a Mon Sep 17 00:00:00 2001
From: kimdahey <claire_kim1@brown.edu>
Date: Mon, 29 Jul 2019 15:40:30 -0400
Subject: fixed column width not adjusting with omitted + ADD NEW / NEW GROUP

---
 src/client/views/collections/CollectionStackingView.tsx            | 4 ++--
 src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 85aa322a2..5e4d8bda5 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -287,9 +287,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
                     map(section => this.section(section[0], section[1])) :
                     this.section(undefined, this.filteredChildren)}
-                {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+                {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ?
                     <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
-                        style={{ width: (this.columnWidth / (headings.length + 1)) - 10, marginTop: 10 }}>
+                        style={{ width: (this.columnWidth / (headings.length + (this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0))) - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
                     </div> : null}
             </div>
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 6b94efb1c..9e39d5383 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -261,7 +261,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             </div> : (null);
         for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `;
         return (
-            <div key={heading} style={{ width: `${100 / (uniqueHeadings.length + 1)}%`, background: this._background }}
+            <div key={heading} style={{ width: `${100 / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0))}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
@@ -281,7 +281,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 </div>
                 {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
                     <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
-                        style={{ width: style.columnWidth / (uniqueHeadings.length + 1) }}>
+                        style={{ width: style.columnWidth / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) }}>
                         <EditableView {...newEditableViewProps} />
                     </div> : null}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 6079237a6a18bf63d18a9f471baadc9b48d9f105 Mon Sep 17 00:00:00 2001
From: kimdahey <claire_kim1@brown.edu>
Date: Mon, 29 Jul 2019 15:46:27 -0400
Subject: fixed column width not adjusting with omitted + ADD NEW / NEW GROUP

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

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

diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 9e39d5383..7727a23c7 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -239,7 +239,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         };
         let headingView = this.props.headingObject ?
             <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef}
-                style={{ width: (style.columnWidth) / (uniqueHeadings.length + 1) }}>
+                style={{ width: (style.columnWidth) / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) }}>
                 {/* the default bucket (no key value) has a tooltip that describes what it is.
                     Further, it does not have a color and cannot be deleted. */}
                 <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown}
-- 
cgit v1.2.3-70-g09d2


From 06dfb537826e8b1642783a9c4ab2514fd7da2fe3 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Mon, 29 Jul 2019 16:53:52 -0400
Subject: More fixes

---
 src/client/views/collections/CollectionDockingView.tsx             | 2 +-
 src/client/views/collections/CollectionStackingView.scss           | 1 +
 src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 4 ++--
 src/client/views/nodes/ImageBox.tsx                                | 2 +-
 4 files changed, 5 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 1859ebee7..d7b5262b1 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -561,7 +561,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         }
         return Transform.Identity();
     }
-    get previewPanelCenteringOffset() { return this.nativeWidth && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
+    get previewPanelCenteringOffset() { return this.nativeWidth && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth()) / 2 : 0; }
 
     addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => {
         if (doc.dockingConfig) {
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 004b57eff..2bb36c825 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -74,6 +74,7 @@
         transform-origin: top left;
         grid-column-end: span 1;
         height: 100%;
+        margin: auto;
     }
 
     .collectionStackingView-sectionHeader {
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 71c4d9f0c..b5dbc1a22 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -239,7 +239,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         };
         let headingView = this.props.headingObject ?
             <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef}
-                style={{ width: (style.columnWidth) / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) }}>
+                style={{ width: (style.columnWidth) / ((uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1) }}>
                 {/* the default bucket (no key value) has a tooltip that describes what it is.
                     Further, it does not have a color and cannot be deleted. */}
                 <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown}
@@ -261,7 +261,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             </div> : (null);
         for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `;
         return (
-            <div key={heading} style={{ width: `${100 / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0))}%`, background: this._background }}
+            <div key={heading} style={{ width: `${100 / ((uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1)}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 82af4b4ca..d4e0eaf98 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -291,7 +291,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
                 let aspect = size.height / size.width;
                 let rotation = NumCast(this.dataDoc.rotation) % 180;
                 if (rotation === 90 || rotation === 270) aspect = 1 / aspect;
-                if (Math.abs(layoutdoc[HeightSym]() / layoutdoc[WidthSym]() - aspect) > 0.01) {
+                if (Math.abs(NumCast(layoutdoc.height) - size.height) > 1 || Math.abs(NumCast(layoutdoc.width) - size.width) > 1) {
                     setTimeout(action(() => {
                         layoutdoc.height = layoutdoc[WidthSym]() * aspect;
                         layoutdoc.nativeHeight = size.height;
-- 
cgit v1.2.3-70-g09d2


From ba2c6a9f3cd6d68bcf28ff3dc880b4f8b4635747 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Mon, 29 Jul 2019 23:48:35 -0400
Subject: styling changes to stacking

---
 src/client/views/collections/CollectionStackingView.scss          | 5 +++--
 .../views/collections/CollectionStackingViewFieldColumn.tsx       | 8 ++++++--
 src/client/views/pdf/Annotation.tsx                               | 2 +-
 3 files changed, 10 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 2bb36c825..0cb01dc9d 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -135,9 +135,9 @@
 
     .collectionStackingView-addDocumentButton,
     .collectionStackingView-addGroupButton {
-        display: inline-block;
-        margin: 0 5px;
+        display: flex;
         overflow: hidden;
+        margin: auto;
         width: 90%;
         color: lightgrey;
         overflow: ellipses;
@@ -146,6 +146,7 @@
         .editableView-container-editing {
             color: grey;
             padding: 10px;
+            width: 100%;
         }
 
         .editableView-input:hover,
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index b5dbc1a22..d8bed7e88 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -239,7 +239,11 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         };
         let headingView = this.props.headingObject ?
             <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef}
-                style={{ width: (style.columnWidth) / ((uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1) }}>
+                style={{
+                    width: (style.columnWidth) /
+                        ((uniqueHeadings.length +
+                            (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1)
+                }}>
                 {/* the default bucket (no key value) has a tooltip that describes what it is.
                     Further, it does not have a color and cannot be deleted. */}
                 <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown}
@@ -266,7 +270,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
                     style={{
-                        padding: singleColumn ? `${style.yMargin}px ${5}px ${style.yMargin}px ${5}px` : `${style.yMargin}px ${0}px`,
+                        padding: singleColumn ? `${style.yMargin}px ${0}px ${style.yMargin}px ${0}px` : `${style.yMargin}px ${0}px`,
                         margin: "auto",
                         width: "max-content", //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
                         height: 'max-content',
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index e8d1da94b..513f9fed6 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -119,7 +119,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
                 let context = await Cast(targetDoc.targetContext, Doc);
                 if (context) {
                     DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined,
-                        ((doc) => this.props.parent.props.parent.props.addDocTab(context, context.proto, e.ctrlKey ? "onRight" : "inTab")));
+                        ((doc) => this.props.parent.props.parent.props.addDocTab(context!, context!.proto, e.ctrlKey ? "onRight" : "inTab")));
                 }
             }
         }
-- 
cgit v1.2.3-70-g09d2


From 1d8c80a366c743479a8eb1c8c21ecad21942da73 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Tue, 30 Jul 2019 12:45:57 -0400
Subject: stacking column dragging has slight delay

---
 .../views/collections/CollectionStackingView.tsx   |  5 ++-
 .../CollectionStackingViewFieldColumn.tsx          | 42 ++++++++++++++--------
 2 files changed, 31 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index f647da8f0..089cd3866 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -248,7 +248,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             docList={docList}
             parent={this}
             type={type}
-            createDropTarget={this.createDropTarget} />;
+            createDropTarget={this.createDropTarget}
+            screenToLocalTransform={this.props.ScreenToLocalTransform}
+        />;
+
     }
 
     @action
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 387e189e7..6edfe55e5 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -19,6 +19,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { ScriptField } from "../../../new_fields/ScriptField";
 import { CompileScript } from "../../util/Scripting";
 import { RichTextField } from "../../../new_fields/RichTextField";
+import { Transform } from "../../util/Transform";
 
 
 interface CSVFieldColumnProps {
@@ -30,6 +31,7 @@ interface CSVFieldColumnProps {
     parent: CollectionStackingView;
     type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined;
     createDropTarget: (ele: HTMLDivElement) => void;
+    screenToLocalTransform: () => Transform;
 }
 
 @observer
@@ -39,6 +41,8 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
     private _dropRef: HTMLDivElement | null = null;
     private dropDisposer?: DragManager.DragDropDisposer;
     private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
+    private _startDragPosition: { x: number, y: number } = { x: 0, y: 0 };
+    private _sensitivity: number = 16;
 
     @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading;
 
@@ -159,6 +163,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
     @action
     pointerLeave = () => {
         this._background = "white";
+        document.removeEventListener("pointermove", this.startDrag);
     }
 
     @action
@@ -180,22 +185,26 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
     }
 
     startDrag = (e: PointerEvent) => {
-        let alias = Doc.MakeAlias(this.props.parent.props.Document);
-        let key = StrCast(this.props.parent.props.Document.sectionFilter);
-        let value = this.getValue(this._heading);
-        value = typeof value === "string" ? `"${value}"` : value;
-        let script = `return doc.${key} === ${value}`;
-        let compiled = CompileScript(script, { params: { doc: Doc.name } });
-        if (compiled.compiled) {
-            let scriptField = new ScriptField(compiled);
-            alias.viewSpecScript = scriptField;
-            let dragData = new DragManager.DocumentDragData([alias], [alias.proto]);
-            DragManager.StartDocumentDrag([this._headerRef.current!], dragData, e.clientX, e.clientY);
-        }
+        let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y);
+        if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) {
+            console.log("start stack drag");
+            let alias = Doc.MakeAlias(this.props.parent.props.Document);
+            let key = StrCast(this.props.parent.props.Document.sectionFilter);
+            let value = this.getValue(this._heading);
+            value = typeof value === "string" ? `"${value}"` : value;
+            let script = `return doc.${key} === ${value}`;
+            let compiled = CompileScript(script, { params: { doc: Doc.name } });
+            if (compiled.compiled) {
+                let scriptField = new ScriptField(compiled);
+                alias.viewSpecScript = scriptField;
+                let dragData = new DragManager.DocumentDragData([alias], [alias.proto]);
+                DragManager.StartDocumentDrag([this._headerRef.current!], dragData, e.clientX, e.clientY);
+            }
 
-        e.stopPropagation();
-        document.removeEventListener("pointermove", this.startDrag);
-        document.removeEventListener("pointerup", this.pointerUp);
+            e.stopPropagation();
+            document.removeEventListener("pointermove", this.startDrag);
+            document.removeEventListener("pointerup", this.pointerUp);
+        }
     }
 
     pointerUp = (e: PointerEvent) => {
@@ -210,6 +219,9 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         e.stopPropagation();
         e.preventDefault();
 
+        let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY);
+        this._startDragPosition = { x: dx, y: dy };
+
         document.removeEventListener("pointermove", this.startDrag);
         document.addEventListener("pointermove", this.startDrag);
         document.removeEventListener("pointerup", this.pointerUp);
-- 
cgit v1.2.3-70-g09d2


From 49355364b418ceb8f04ee79132dedc5885a9bbe5 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Tue, 30 Jul 2019 13:15:19 -0400
Subject: schema column widths get saved

---
 .../CollectionSchemaMovableTableHOC.tsx            |  2 -
 .../views/collections/CollectionSchemaView.tsx     | 44 ++++++++++++++--------
 .../CollectionStackingViewFieldColumn.tsx          |  1 -
 src/new_fields/SchemaHeaderField.ts                |  5 ++-
 4 files changed, 32 insertions(+), 20 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 2e4f276bf..483463c2b 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -81,7 +81,6 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
             document.removeEventListener('pointerup', onRowUp);
             let dragData = new DragManager.ColumnDragData(this.props.columnValue);
             DragManager.StartColumnDrag(this._dragRef.current!, dragData, e.x, e.y);
-            console.log("SETUP DRAG");
         };
         let onRowUp = (): void => {
             document.removeEventListener("pointermove", onRowMove);
@@ -89,7 +88,6 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
         };
         if (e.buttons === 1) {
             let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y);
-            console.log("moving this much", Math.abs(dx), Math.abs(dy));
             if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) {
                 document.removeEventListener("pointermove", this.onPointerMove);
                 e.stopPropagation();
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 26b19474a..722d8b1f9 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -4,10 +4,10 @@ import { faCog, faPlus, faTable, faSortUp, faSortDown } from '@fortawesome/free-
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
-import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column, RowInfo } from "react-table";
+import ReactTable, { CellInfo, ComponentPropsGetterR, Column, RowInfo, ResizedChangeFunction, Resize } from "react-table";
 import "react-table/react-table.css";
-import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils";
-import { Doc, DocListCast, DocListCastAsync, Field, FieldResult, Opt } from "../../../new_fields/Doc";
+import { emptyFunction, returnOne } from "../../../Utils";
+import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
@@ -17,28 +17,21 @@ import { Gateway } from "../../northstar/manager/Gateway";
 import { SetupDrag, DragManager } from "../../util/DragManager";
 import { CompileScript, ts, Transformer } from "../../util/Scripting";
 import { Transform } from "../../util/Transform";
-import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss';
+import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss';
 import { ContextMenu } from "../ContextMenu";
-import { anchorPoints, Flyout } from "../DocumentDecorations";
 import '../DocumentDecorations.scss';
-import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
-import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { CollectionPDFView } from "./CollectionPDFView";
 import "./CollectionSchemaView.scss";
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionVideoView } from "./CollectionVideoView";
 import { CollectionView } from "./CollectionView";
 import { undoBatch } from "../../util/UndoManager";
-import { timesSeries } from "async";
 import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders";
 import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell } from "./CollectionSchemaCells";
 import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC";
-import { SelectionManager } from "../../util/SelectionManager";
-import { DocumentManager } from "../../util/DocumentManager";
-import { ImageBox } from "../nodes/ImageBox";
 import { ComputedField } from "../../../new_fields/ScriptField";
-import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 
 
 library.add(faCog, faPlus, faSortUp, faSortDown);
@@ -314,6 +307,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this.props.Document.textwrappedSchemaRows = new List<string>(textWrappedRows);
     }
 
+    @computed get resized(): { "id": string, "value": number }[] {
+        let columns = this.columns;
+        return columns.reduce((resized, shf) => {
+            if (shf.width > -1) {
+                resized.push({ "id": shf.heading, "value": shf.width });
+            }
+            return resized;
+        }, [] as { "id": string, "value": number }[]);
+    }
+
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1);
@@ -658,15 +661,12 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     setColumnColor = (columnField: SchemaHeaderField, color: string): void => {
-        // console.log("setting color", key);
         let columns = this.columns;
         let index = columns.indexOf(columnField);
         if (index > -1) {
-            // let column = columns[index];
             columnField.color = color;
             columns[index] = columnField;
             this.columns = columns;
-            console.log(columnField, this.columns[index]);
         }
     }
 
@@ -730,7 +730,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     get reactTable() {
         let children = this.childDocs;
 
-        let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
+        // let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
         let expandedRowsList = this._openCollections.map(col => children.findIndex(doc => doc[Id] === col).toString());
         let expanded = {};
@@ -751,6 +751,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             TrComponent={MovableRow}
             sorted={Array.from(this._sortedColumns.values())}
             expanded={expanded}
+            resized={this.resized}
+            onResizedChange={this.onResizedChange}
             SubComponent={hasCollectionChild ?
                 row => {
                     if (row.original.type === "collection") {
@@ -762,6 +764,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         />;
     }
 
+    onResizedChange = (newResized: Resize[], event: any) => {
+        let columns = this.columns;
+        newResized.forEach(resized => {
+            let index = columns.findIndex(c => c.heading === resized.id);
+            let column = columns[index];
+            column.width = resized.value;
+        });
+        this.columns = columns;
+    }
+
     onContextMenu = (e: React.MouseEvent): void => {
         if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB, icon: "table" });
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 6edfe55e5..01938a3b4 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -187,7 +187,6 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
     startDrag = (e: PointerEvent) => {
         let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y);
         if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) {
-            console.log("start stack drag");
             let alias = Doc.MakeAlias(this.props.parent.props.Document);
             let key = StrCast(this.props.parent.props.Document.sectionFilter);
             let value = this.getValue(this._heading);
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index 9f716bf9f..15b497759 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -49,8 +49,10 @@ export class SchemaHeaderField extends ObjectField {
     color: string;
     @serializable(primitive())
     type: number;
+    @serializable(primitive())
+    width: number;
 
-    constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) {
+    constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType, width?: number) {
         super();
 
         this.heading = heading;
@@ -61,6 +63,7 @@ export class SchemaHeaderField extends ObjectField {
         else {
             this.type = 0;
         }
+        this.width = width ? width : -1;
     }
 
     setHeading(heading: string) {
-- 
cgit v1.2.3-70-g09d2


From f03f94accabc2336d1c143fcb80bb0c3f5b70d99 Mon Sep 17 00:00:00 2001
From: kimdahey <claire_kim1@brown.edu>
Date: Tue, 30 Jul 2019 13:29:27 -0400
Subject: added toggle button

---
 package.json                                       |  2 +
 .../views/collections/CollectionStackingView.scss  | 53 +++++++++++++++++++++-
 .../views/collections/CollectionStackingView.tsx   | 21 ++++++++-
 .../CollectionStackingViewFieldColumn.tsx          |  8 ++--
 .../views/collections/CollectionViewChromes.tsx    |  4 +-
 5 files changed, 78 insertions(+), 10 deletions(-)

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

diff --git a/package.json b/package.json
index 37052fde3..ae3a9d964 100644
--- a/package.json
+++ b/package.json
@@ -91,6 +91,7 @@
         "@types/prosemirror-transform": "^1.1.0",
         "@types/prosemirror-view": "^1.3.1",
         "@types/pug": "^2.0.4",
+        "@types/rc-switch": "^1.8.0",
         "@types/react": "^16.8.7",
         "@types/react-autosuggest": "^9.3.9",
         "@types/react-color": "^2.14.1",
@@ -170,6 +171,7 @@
         "pug": "^2.0.3",
         "query-string": "^6.8.1",
         "raw-loader": "^1.0.0",
+        "rc-switch": "^1.9.0",
         "react": "^16.8.4",
         "react-anime": "^2.2.0",
         "react-autosuggest": "^9.4.3",
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 0cb01dc9d..3fcec265f 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -79,8 +79,8 @@
 
     .collectionStackingView-sectionHeader {
         text-align: center;
-        margin-left: 5px;
-        margin-right: 5px;
+        margin-left: 2px;
+        margin-right: 2px;
         margin-top: 10px;
         overflow: hidden;
 
@@ -102,6 +102,7 @@
             font-size: 75%;
             transition: transform 0.2s;
             position: relative;
+            width: 98%;
 
             .editableView-container-editing-oneLine,
             .editableView-container-editing {
@@ -184,4 +185,52 @@
         letter-spacing: 2px;
         height: fit-content;
     }
+
+    .rc-switch {
+        position: absolute;
+        display: inline-block;
+        bottom: 15px;
+        right: 15px;
+        width: 125px;
+        height: 54px;
+        border-radius: 40px 40px;
+    }
+
+    .rc-switch:after {
+        position: absolute;
+        width: 36px;
+        height: 36px;
+        left: 7px;
+        top: 9px;
+        border-radius: 50% 50%;
+        background-color: #fff;
+        content: " ";
+        cursor: pointer;
+        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
+        -webkit-transform: scale(1);
+        transform: scale(1);
+        transition: left 0.3s cubic-bezier(0.35, 0, 0.25, 1);
+        -webkit-animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1);
+        animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1);
+        -webkit-animation-duration: 0.3s;
+        animation-duration: 0.3s;
+    }
+
+    .rc-switch-checked:after {
+        left: 80px;
+    }
+
+    .rc-switch-inner {
+        color: #fff;
+        font-size: 22px;
+        position: absolute;
+        left: 50px;
+        top: 14px;
+    }
+
+    .rc-switch-checked .rc-switch-inner {
+        left: 17px;
+    }
+
+
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index bcf3a85d7..c6e889bb5 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -20,6 +20,7 @@ import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeade
 import { List } from "../../../new_fields/List";
 import { EditableView } from "../EditableView";
 import { CollectionViewProps } from "./CollectionBaseView";
+import Switch from 'rc-switch';
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -29,6 +30,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     _sectionFilterDisposer?: IReactionDisposer;
     _docXfs: any[] = [];
     _columnStart: number = 0;
+    _toggleTitle: string = "author mode";
     @observable private cursor: CursorProperty = "grab";
     get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); }
     @computed get chromeCollapsed() { return this.props.chromeCollapsed; }
@@ -269,6 +271,14 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return firstEntry[0].heading > secondEntry[0].heading ? 1 : -1;
     }
 
+    onToggle = (checked: Boolean) => {
+        if (checked) {
+            this.props.CollectionView.props.Document.chromeStatus = 'collapsed';
+        } else {
+            this.props.CollectionView.props.Document.chromeStatus = 'view-mode';
+        }
+    }
+
     render() {
         let headings = Array.from(this.Sections.keys());
         let editableViewProps = {
@@ -289,11 +299,18 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
                     map(section => this.section(section[0], section[1])) :
                     this.section(undefined, this.filteredChildren)}
-                {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+                {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'view-mode') ?
                     <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
-                        style={{ width: (this.columnWidth / (headings.length + (this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0))) - 10, marginTop: 10 }}>
+                        style={{ width: (this.columnWidth / (headings.length + (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0))) - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
                     </div> : null}
+                {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? <Switch
+                    onChange={this.onToggle}
+                    onClick={this.onToggle}
+                    defaultChecked={this.props.CollectionView.props.Document.chromeStatus !== 'view-mode'}
+                    checkedChildren="edit"
+                    unCheckedChildren="view"
+                /> : null}
             </div>
         );
     }
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index d8bed7e88..4f7de0c24 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -242,7 +242,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 style={{
                     width: (style.columnWidth) /
                         ((uniqueHeadings.length +
-                            (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1)
+                            (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0)) || 1)
                 }}>
                 {/* the default bucket (no key value) has a tooltip that describes what it is.
                     Further, it does not have a color and cannot be deleted. */}
@@ -265,7 +265,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             </div> : (null);
         for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `;
         return (
-            <div key={heading} style={{ width: `${100 / ((uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) || 1)}%`, background: this._background }}
+            <div key={heading} style={{ width: `${100 / ((uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0)) || 1)}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
@@ -283,9 +283,9 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                     {this.children(this.props.docList)}
                     {singleColumn ? (null) : this.props.parent.columnDragger}
                 </div>
-                {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
+                {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode') ?
                     <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
-                        style={{ width: style.columnWidth / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? 1 : 0)) }}>
+                        style={{ width: style.columnWidth / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0)) }}>
                         <EditableView {...newEditableViewProps} />
                     </div> : null}
             </div>
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 2bffe3cc0..9c751c4df 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -185,11 +185,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
 
     render() {
         return (
-            <div className="collectionViewChrome-cont" style={{ marginTop: this._collapsed ? -70 : 0, height: 70 }}>
+            <div className="collectionViewChrome-cont" style={{ top: this._collapsed ? -100 : 0 }}>
                 <div className="collectionViewChrome">
                     <div className="collectionViewBaseChrome">
                         <button className="collectionViewBaseChrome-collapse"
-                            style={{ marginTop: this._collapsed ? 60 : 0, transform: `rotate(${this._collapsed ? 180 : 0}deg)` }}
+                            style={{ top: this._collapsed ? 90 : 10, transform: `rotate(${this._collapsed ? 180 : 0}deg)` }}
                             title="Collapse collection chrome" onClick={this.toggleCollapse}>
                             <FontAwesomeIcon icon="caret-up" size="2x" />
                         </button>
-- 
cgit v1.2.3-70-g09d2


From c953c50fee4eaa578e74249dab0f40af3f268802 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Tue, 30 Jul 2019 17:49:36 -0400
Subject: added color picker to stacking view columns

---
 .../views/collections/CollectionStackingView.scss  | 39 ++++++++++++++-
 .../CollectionStackingViewFieldColumn.tsx          | 58 ++++++++++++++++++++--
 src/new_fields/SchemaHeaderField.ts                |  3 +-
 3 files changed, 95 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 0cb01dc9d..669b3170a 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -82,7 +82,7 @@
         margin-left: 5px;
         margin-right: 5px;
         margin-top: 10px;
-        overflow: hidden;
+        // overflow: hidden; overflow is visible so the color menu isn't hidden -ftong
 
         .editableView-input {
             color: black;
@@ -125,6 +125,43 @@
             }
         }
 
+        .collectionStackingView-sectionColor {
+            position: absolute;
+            left: 0;
+            top: 0;
+            height: 100%;
+
+            [class*="css"] {
+                max-width: 102px;
+            }
+
+            .collectionStackingView-sectionColorButton {
+                height: 35px;
+            }
+
+            .collectionStackingView-colorPicker {
+                width: 78px;
+                
+                .colorOptions {
+                    display: flex;
+                    flex-wrap: wrap;
+                }
+
+                .colorPicker {
+                    cursor: pointer;
+                    width: 20px;
+                    height: 20px;
+                    border-radius: 10px;
+                    margin: 3px;
+        
+                    &.active {
+                        border: 2px solid white;
+                        box-shadow: 0 0 0 2px lightgray;
+                    }
+                }
+            }
+        }
+
         .collectionStackingView-sectionDelete {
             position: absolute;
             right: 0;
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 38cc7fc50..668ba901b 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -14,12 +14,17 @@ import { DocumentManager } from "../../util/DocumentManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import "./CollectionStackingView.scss";
 import { Docs } from "../../documents/Documents";
-import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { ScriptField } from "../../../new_fields/ScriptField";
 import { CompileScript } from "../../util/Scripting";
 import { RichTextField } from "../../../new_fields/RichTextField";
 import { Transform } from "../../util/Transform";
+import { Flyout, anchorPoints } from "../DocumentDecorations";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faPalette } from '@fortawesome/free-solid-svg-icons';
+
+library.add(faPalette);
 
 
 interface CSVFieldColumnProps {
@@ -45,6 +50,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
     private _sensitivity: number = 16;
 
     @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading;
+    @observable _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
 
     createColumnDropRef = (ele: HTMLDivElement | null) => {
         this._dropRef = ele;
@@ -153,6 +159,14 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         return false;
     }
 
+    @action
+    changeColumnColor = (color: string) => {
+        if (this.props.headingObject) {
+            this.props.headingObject.setColor(color);
+            this._color = color;
+        }
+    }
+
     @action
     pointerEntered = () => {
         if (SelectionManager.GetIsDragging()) {
@@ -227,6 +241,36 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         document.addEventListener("pointerup", this.pointerUp);
     }
 
+    renderColorPicker = () => {
+        let selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+
+        let pink = PastelSchemaPalette.get("pink2");
+        let purple = PastelSchemaPalette.get("purple4");
+        let blue = PastelSchemaPalette.get("bluegreen1");
+        let yellow = PastelSchemaPalette.get("yellow4");
+        let red = PastelSchemaPalette.get("red2");
+        let green = PastelSchemaPalette.get("bluegreen7");
+        let cyan = PastelSchemaPalette.get("bluegreen5");
+        let orange = PastelSchemaPalette.get("orange1");
+        let gray = "#f1efeb";
+
+        return (
+            <div className="collectionStackingView-colorPicker">
+                <div className="colorOptions">
+                    <div className={"colorPicker" + (selected === pink ? " active" : "")} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)}></div>
+                    <div className={"colorPicker" + (selected === purple ? " active" : "")} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)}></div>
+                    <div className={"colorPicker" + (selected === blue ? " active" : "")} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)}></div>
+                    <div className={"colorPicker" + (selected === yellow ? " active" : "")} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)}></div>
+                    <div className={"colorPicker" + (selected === red ? " active" : "")} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)}></div>
+                    <div className={"colorPicker" + (selected === gray ? " active" : "")} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)}></div>
+                    <div className={"colorPicker" + (selected === green ? " active" : "")} style={{ backgroundColor: green }} onClick={() => this.changeColumnColor(green!)}></div>
+                    <div className={"colorPicker" + (selected === cyan ? " active" : "")} style={{ backgroundColor: cyan }} onClick={() => this.changeColumnColor(cyan!)}></div>
+                    <div className={"colorPicker" + (selected === orange ? " active" : "")} style={{ backgroundColor: orange }} onClick={() => this.changeColumnColor(orange!)}></div>
+                </div>
+            </div>
+        );
+    }
+
     render() {
         let cols = this.props.cols();
         let key = StrCast(this.props.parent.props.Document.sectionFilter);
@@ -262,11 +306,19 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                         `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
                     style={{
                         width: "100%",
-                        background: this.props.headingObject && evContents !== `NO ${key.toUpperCase()} VALUE` ?
-                            this.props.headingObject.color : "lightgrey",
+                        background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this._color : "lightgrey",
                         color: "grey"
                     }}>
                     <EditableView {...headerEditableViewProps} />
+                    {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
+                        <div className="collectionStackingView-sectionColor">
+                            <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderColorPicker()}>
+                                <button className="collectionStackingView-sectionColorButton">
+                                    <FontAwesomeIcon icon="palette" size="sm" />
+                                </button>
+                            </ Flyout >
+                        </div>
+                    }
                     {evContents === `NO ${key.toUpperCase()} VALUE` ?
                         (null) :
                         <button className="collectionStackingView-sectionDelete" onClick={this.deleteColumn}>
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index 0c19d211a..23605cfb0 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -25,7 +25,7 @@ export const PastelSchemaPalette = new Map<string, string>([
     ["bluegreen3", "#c4faf8"],
     ["bluegreen4", "#85e3ff"],
     ["bluegreen5", "#ace7ff"],
-    ["bluegreen6", "#6eb5ff"],
+    // ["bluegreen6", "#6eb5ff"],
     ["bluegreen7", "#bffcc6"],
     ["bluegreen8", "#dbffd6"],
     ["yellow1", "#f3ffe3"],
@@ -36,6 +36,7 @@ export const PastelSchemaPalette = new Map<string, string>([
     ["red2", "#ffabab"],
     ["red3", "#ffbebc"],
     ["red4", "#ffcbc1"],
+    ["orange1", "#ffd5b3"],
 ]);
 
 export const RandomPastel = () => Array.from(PastelSchemaPalette.values())[Math.floor(Math.random() * PastelSchemaPalette.size)];
-- 
cgit v1.2.3-70-g09d2


From cf32a37355e1d4a55e276e2ee25ef9cd89e0cd16 Mon Sep 17 00:00:00 2001
From: kimdahey <claire_kim1@brown.edu>
Date: Wed, 31 Jul 2019 11:16:35 -0400
Subject: disabled does not show ADD NEW / GROUP buttons

---
 src/client/views/collections/CollectionStackingView.tsx           | 4 ++--
 .../views/collections/CollectionStackingViewFieldColumn.tsx       | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 5cfcc3d4b..9741b9e89 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -301,9 +301,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
                     map(section => this.section(section[0], section[1])) :
                     this.section(undefined, this.filteredChildren)}
-                {(this.props.Document.sectionFilter && this.props.CollectionView.props.Document.chromeStatus !== 'view-mode') ?
+                {(this.props.Document.sectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')) ?
                     <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
-                        style={{ width: (this.columnWidth / (headings.length + (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0))) - 10, marginTop: 10 }}>
+                        style={{ width: (this.columnWidth / (headings.length + ((this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0))) - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
                     </div> : null}
                 {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? <Switch
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 460359908..36c8c8a8d 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -297,7 +297,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 style={{
                     width: (style.columnWidth) /
                         ((uniqueHeadings.length +
-                            (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0)) || 1)
+                            ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)
                 }}>
                 {/* the default bucket (no key value) has a tooltip that describes what it is.
                     Further, it does not have a color and cannot be deleted. */}
@@ -328,7 +328,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             </div> : (null);
         for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `;
         return (
-            <div key={heading} style={{ width: `${100 / ((uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0)) || 1)}%`, background: this._background }}
+            <div key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
@@ -346,9 +346,9 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                     {this.children(this.props.docList)}
                     {singleColumn ? (null) : this.props.parent.columnDragger}
                 </div>
-                {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode') ?
+                {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
                     <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
-                        style={{ width: style.columnWidth / (uniqueHeadings.length + (this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' ? 1 : 0)) }}>
+                        style={{ width: style.columnWidth / (uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) }}>
                         <EditableView {...newEditableViewProps} />
                     </div> : null}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 023c08d621488dfaa18a61f50611c612b2a6feb5 Mon Sep 17 00:00:00 2001
From: kimdahey <claire_kim1@brown.edu>
Date: Wed, 31 Jul 2019 11:37:03 -0400
Subject: some QoL css changes

---
 .../views/collections/CollectionStackingView.scss  | 31 +++++++++++-----------
 .../CollectionStackingViewFieldColumn.tsx          |  2 +-
 2 files changed, 17 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 14c7f5edd..015955816 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -141,7 +141,7 @@
 
             .collectionStackingView-colorPicker {
                 width: 78px;
-                
+
                 .colorOptions {
                     display: flex;
                     flex-wrap: wrap;
@@ -153,7 +153,7 @@
                     height: 20px;
                     border-radius: 10px;
                     margin: 3px;
-        
+
                     &.active {
                         border: 2px solid white;
                         box-shadow: 0 0 0 2px lightgray;
@@ -225,19 +225,20 @@
     .rc-switch {
         position: absolute;
         display: inline-block;
-        bottom: 15px;
-        right: 15px;
-        width: 125px;
-        height: 54px;
+        bottom: 4px;
+        right: 4px;
+        width: 70px;
+        height: 30px;
         border-radius: 40px 40px;
+        background-color: lightslategrey;
     }
 
     .rc-switch:after {
         position: absolute;
-        width: 36px;
-        height: 36px;
-        left: 7px;
-        top: 9px;
+        width: 22px;
+        height: 22px;
+        left: 3px;
+        top: 4px;
         border-radius: 50% 50%;
         background-color: #fff;
         content: " ";
@@ -253,19 +254,19 @@
     }
 
     .rc-switch-checked:after {
-        left: 80px;
+        left: 44px;
     }
 
     .rc-switch-inner {
         color: #fff;
-        font-size: 22px;
+        font-size: 12px;
         position: absolute;
-        left: 50px;
-        top: 14px;
+        left: 28px;
+        top: 8px;
     }
 
     .rc-switch-checked .rc-switch-inner {
-        left: 17px;
+        left: 8px;
     }
 
 
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 36c8c8a8d..df03da376 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -348,7 +348,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 </div>
                 {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
                     <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
-                        style={{ width: style.columnWidth / (uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) }}>
+                        style={{ width: style.columnWidth / (uniqueHeadings.length + 1) }}>
                         <EditableView {...newEditableViewProps} />
                     </div> : null}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 87e79b5d230cee0d3f5df399b4fee0c62ccb5385 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 13 Aug 2019 00:11:52 -0400
Subject: fixed stacking layouts.  added image cross fading.

---
 src/client/util/DragManager.ts                     |  2 +-
 .../views/collections/CollectionSchemaView.scss    | 48 +++++++++++-----------
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../CollectionStackingViewFieldColumn.tsx          |  2 +-
 src/client/views/nodes/ImageBox.scss               | 21 +++++++++-
 src/client/views/nodes/ImageBox.tsx                | 26 ++++++++----
 6 files changed, 65 insertions(+), 36 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index a7aaaed7c..0b6d9b5e5 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -490,7 +490,7 @@ export namespace DragManager {
                         x: e.x,
                         y: e.y,
                         data: dragData,
-                        mods: e.altKey ? "AltKey" : e.ctrlKey ? "CtrlKey" : ""
+                        mods: e.altKey ? "AltKey" : e.ctrlKey ? "CtrlKey" : e.metaKey ? "MetaKey" : ""
                     }
                 })
             );
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 01744fb34..e0cedc210 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -22,30 +22,6 @@
         overflow: scroll;
     }
 
-    .collectionSchemaView-previewRegion {
-        position: relative;
-        background: $light-color;
-        height: 100%;
-
-        .collectionSchemaView-previewDoc {
-            height: 100%;
-            width: 100%;
-            position: absolute;
-        }
-
-        .collectionSchemaView-input {
-            position: absolute;
-            max-width: 150px;
-            width: 100%;
-            bottom: 0px;
-        }
-
-        .documentView-node:first-child {
-            position: relative;
-            background: $light-color;
-        }
-    }
-
     .collectionSchemaView-dividerDragger {
         position: relative;
         height: 100%;
@@ -62,6 +38,30 @@
     }
 }
 
+.collectionSchemaView-previewRegion {
+    position: relative;
+    background: $light-color;
+    height: auto !important;
+
+    .collectionSchemaView-previewDoc {
+        height: 100%;
+        width: 100%;
+        position: absolute;
+    }
+
+    .collectionSchemaView-input {
+        position: absolute;
+        max-width: 150px;
+        width: 100%;
+        bottom: 0px;
+    }
+
+    .documentView-node:first-child {
+        position: relative;
+        background: $light-color;
+    }
+}
+
 .ReactTable {
     width: 100%;
     background: white;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9bb0d787d..4537dcc85 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -899,7 +899,7 @@ interface CollectionSchemaPreviewProps {
     height: () => number;
     showOverlays?: (doc: Doc) => { title?: string, caption?: string };
     CollectionView?: CollectionView | CollectionPDFView | CollectionVideoView;
-    onClick?: () => void | ScriptField;
+    onClick?: ScriptField;
     getTransform: () => Transform;
     addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
     moveDocument: (document: Doc, target: Doc, addDoc: ((doc: Doc) => boolean)) => boolean;
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index df03da376..0a872cfb8 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -328,7 +328,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             </div> : (null);
         for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `;
         return (
-            <div key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
+            <div className="collectionStackingViewFieldColumn" key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
                 {headingView}
                 <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index 697f19f0d..497ce96c9 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -56,4 +56,23 @@
         left: 5%;
         top: 15%;
     }
-}
\ No newline at end of file
+}
+
+#cf {
+    position:relative;
+    width:100%;
+    margin:0 auto;
+  }
+  
+  #cf img {
+    position:absolute;
+    left:0;
+    -webkit-transition: opacity 1s ease-in-out;
+    -moz-transition: opacity 1s ease-in-out;
+    -o-transition: opacity 1s ease-in-out;
+    transition: opacity 1s ease-in-out;
+  }
+  
+  #cf img.fadeaway:hover {
+    opacity:0;
+  }
\ No newline at end of file
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 78a6ec66f..582a50637 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -95,7 +95,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
                 } else if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) {
                     Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url);
                     e.stopPropagation();
-                } else if (de.mods === "CtrlKey") {
+                } else if (de.mods === "MetaKey") {
                     if (this.extensionDoc !== this.dataDoc) {
                         let layout = StrCast(drop.backgroundLayout);
                         if (layout.indexOf(ImageBox.name) !== -1) {
@@ -404,6 +404,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
         let aspect = (rotation % 180) ? this.dataDoc[HeightSym]() / this.dataDoc[WidthSym]() : 1;
         let shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0;
         let srcpath = paths[Math.min(paths.length - 1, this.Document.curPage || 0)];
+        let fadepath = paths[Math.min(paths.length - 1, 1)];
 
         if (!this.props.Document.ignoreAspect && !this.props.leaveNativeSize) this.resize(srcpath, this.props.Document);
 
@@ -411,13 +412,22 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
             <div id={id} className={`imageBox-cont${interactive}`} style={{ background: "transparent" }}
                 onPointerDown={this.onPointerDown}
                 onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
-                <img id={id}
-                    key={this._smallRetryCount + (this._mediumRetryCount << 4) + (this._largeRetryCount << 8)} // force cache to update on retrys
-                    src={srcpath}
-                    style={{ transform: `translate(0px, ${shift}px) rotate(${rotation}deg) scale(${aspect})` }}
-                    width={nativeWidth}
-                    ref={this._imgRef}
-                    onError={this.onError} />
+                <div id="cf">
+                    <img id={id}
+                        key={this._smallRetryCount + (this._mediumRetryCount << 4) + (this._largeRetryCount << 8)} // force cache to update on retrys
+                        src={srcpath}
+                        style={{ transform: `translate(0px, ${shift}px) rotate(${rotation}deg) scale(${aspect})` }}
+                        width={nativeWidth}
+                        ref={this._imgRef}
+                        onError={this.onError} />
+                    {fadepath === srcpath ? (null) : <img id="fadeaway" className="fadeaway"
+                        key={"fadeaway" + this._smallRetryCount + (this._mediumRetryCount << 4) + (this._largeRetryCount << 8)} // force cache to update on retrys
+                        src={fadepath}
+                        style={{ transform: `translate(0px, ${shift}px) rotate(${rotation}deg) scale(${aspect})` }}
+                        width={nativeWidth}
+                        ref={this._imgRef}
+                        onError={this.onError} />}
+                </div>
                 {paths.length > 1 ? this.dots(paths) : (null)}
                 <div className="imageBox-audioBackground"
                     onPointerDown={this.audioDown}
-- 
cgit v1.2.3-70-g09d2


From 73dbd95e2f70bec212d766b2c6545fe59227b82a Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 13 Aug 2019 10:17:00 -0400
Subject: added fillColumn to stacking views

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

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

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 58548660c..9d2671356 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -139,9 +139,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     getDocHeight(d: Doc, columnScale: number = 1) {
         let nw = NumCast(d.nativeWidth);
         let nh = NumCast(d.nativeHeight);
-        if (!BoolCast(d.ignoreAspect) && nw && nh) {
+        if (!d.ignoreAspect && nw && nh) {
             let aspect = nw && nh ? nh / nw : 1;
-            let wid = Math.min(d[WidthSym](), this.columnWidth / columnScale);
+            let wid = this.props.Document.fillColumn ? this.columnWidth / columnScale : Math.min(d[WidthSym](), this.columnWidth / columnScale);
             return wid * aspect;
         }
         return d[HeightSym]();
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 0a872cfb8..817f9f4cb 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -84,7 +84,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             let headings = this.props.headings();
             let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
             let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d);
-            let width = () => (d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1);
+            let width = () => (d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? Math.min(NumCast(d.nativeWidth), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1);
             let height = () => parent.getDocHeight(pair.layout, uniqueHeadings.length + 1);// / (d.nativeWidth && !BoolCast(d.ignoreAspect) ? uniqueHeadings.length + 1 : 1);
             let dref = React.createRef<HTMLDivElement>();
             // if (uniqueHeadings.length > 0) {
-- 
cgit v1.2.3-70-g09d2


From afec8d91ec6de13de33e2a31c987727b4cc7101d Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 13 Aug 2019 15:42:05 -0400
Subject: changes to fix stacking layouts used with templates. rearrangement of
 menu options.

---
 src/client/util/TooltipTextMenu.tsx                |   2 +-
 src/client/views/DocumentDecorations.tsx           |   4 +-
 src/client/views/InkingCanvas.tsx                  |  20 ++--
 src/client/views/ScriptBox.tsx                     |  30 +++++-
 .../views/collections/CollectionDockingView.tsx    |   4 +-
 .../views/collections/CollectionStackingView.tsx   |  57 +++++++----
 .../CollectionStackingViewFieldColumn.tsx          |   2 +-
 src/client/views/collections/CollectionView.tsx    |  19 ++--
 .../views/collections/CollectionViewChromes.tsx    |  19 ++--
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  64 ++-----------
 src/client/views/nodes/DocumentContentsView.tsx    |   3 +-
 src/client/views/nodes/DocumentView.tsx            | 105 ++++++++++++---------
 src/client/views/nodes/FormattedTextBox.tsx        |  15 +--
 src/new_fields/Doc.ts                              |   7 ++
 src/new_fields/Types.ts                            |   4 +
 15 files changed, 193 insertions(+), 162 deletions(-)

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

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 8dc5cdb2a..48f02d38a 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -963,7 +963,7 @@ export class TooltipTextMenu {
                 });
             }
         }
-        if (!ref_node.isLeaf) {
+        if (!ref_node.isLeaf && ref_node.childCount > 0) {
             ref_node = ref_node.child(0);
         }
         return ref_node;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 6616d5d58..d537e2dac 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -537,12 +537,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 doc.x = (doc.x || 0) + dX * (actualdW - width);
                 doc.y = (doc.y || 0) + dY * (actualdH - height);
                 let proto = doc.isTemplate ? doc : Doc.GetProto(element.props.Document); // bcz: 'doc' didn't work here...
-                let fixedAspect = e.ctrlKey || (!BoolCast(proto.ignoreAspect) && nwidth && nheight);
+                let fixedAspect = e.ctrlKey || (!BoolCast(doc.ignoreAspect) && nwidth && nheight);
                 if (fixedAspect && (!nwidth || !nheight)) {
                     proto.nativeWidth = nwidth = doc.width || 0;
                     proto.nativeHeight = nheight = doc.height || 0;
                 }
-                if (nwidth > 0 && nheight > 0 && !BoolCast(proto.ignoreAspect)) {
+                if (nwidth > 0 && nheight > 0 && !BoolCast(doc.ignoreAspect)) {
                     if (Math.abs(dW) > Math.abs(dH)) {
                         if (!fixedAspect) {
                             Doc.SetInPlace(element.props.Document, "nativeWidth", actualdW / (doc.width || 1) * (doc.nativeWidth || 0), true);
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
index 1c221e3df..b08133d80 100644
--- a/src/client/views/InkingCanvas.tsx
+++ b/src/client/views/InkingCanvas.tsx
@@ -165,14 +165,18 @@ export class InkingCanvas extends React.Component<InkCanvasProps> {
             }
             return paths;
         }, [] as JSX.Element[]);
-        return [<svg className={`inkingCanvas-paths-ink`} key="Pens"
-            style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }} >
-            {paths.filter(path => path.props.tool !== InkTool.Highlighter)}
-        </svg>,
-        <svg className={`inkingCanvas-paths-markers`} key="Markers"
-            style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }}>
-            {paths.filter(path => path.props.tool === InkTool.Highlighter)}
-        </svg>];
+        let markerPaths = paths.filter(path => path.props.tool === InkTool.Highlighter);
+        let penPaths = paths.filter(path => path.props.tool !== InkTool.Highlighter);
+        return [!penPaths.length ? (null) :
+            <svg className={`inkingCanvas-paths-ink`} key="Pens"
+                style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }} >
+                {}
+            </svg>,
+        !markerPaths.length ? (null) :
+            <svg className={`inkingCanvas-paths-markers`} key="Markers"
+                style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }}>
+                {}
+            </svg>];
     }
 
     render() {
diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx
index d073945e5..2b862a81e 100644
--- a/src/client/views/ScriptBox.tsx
+++ b/src/client/views/ScriptBox.tsx
@@ -5,7 +5,11 @@ import { observable, action } from "mobx";
 import "./ScriptBox.scss";
 import { OverlayView } from "./OverlayView";
 import { DocumentIconContainer } from "./nodes/DocumentIcon";
-import { Opt } from "../../new_fields/Doc";
+import { Opt, Doc } from "../../new_fields/Doc";
+import { emptyFunction } from "../../Utils";
+import { ScriptCast } from "../../new_fields/Types";
+import { CompileScript } from "../util/Scripting";
+import { ScriptField } from "../../new_fields/ScriptField";
 
 export interface ScriptBoxProps {
     onSave: (text: string, onError: (error: string) => void) => void;
@@ -62,4 +66,26 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
             </div>
         );
     }
-}
\ No newline at end of file
+    public static EditClickScript(doc: Doc, fieldKey: string) {
+        let overlayDisposer: () => void = emptyFunction;
+        const script = ScriptCast(doc[fieldKey]);
+        let originalText: string | undefined = undefined;
+        if (script) originalText = script.script.originalScript;
+        // tslint:disable-next-line: no-unnecessary-callback-wrapper
+        let scriptingBox = <ScriptBox initialText={originalText} onCancel={() => overlayDisposer()} onSave={(text, onError) => {
+            const script = CompileScript(text, {
+                params: { this: Doc.name },
+                typecheck: false,
+                editable: true,
+                transformer: DocumentIconContainer.getTransformer()
+            });
+            if (!script.compiled) {
+                onError(script.errors.map(error => error.messageText).join("\n"));
+                return;
+            }
+            doc[fieldKey] = new ScriptField(script);
+            overlayDisposer();
+        }} showDocumentIcons />;
+        overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${doc.title || ""} OnClick` });
+    }
+}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index c0c82a44e..13bb34037 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -555,8 +555,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     panelWidth = () => this._document!.ignoreAspect ? this._panelWidth : Math.min(this._panelWidth, Math.max(NumCast(this._document!.width), this.nativeWidth()));
     panelHeight = () => this._document!.ignoreAspect ? this._panelHeight : Math.min(this._panelHeight, Math.max(NumCast(this._document!.height), NumCast(this._document!.nativeHeight, this._panelHeight)));
 
-    nativeWidth = () => !BoolCast(this._document!.ignoreAspect) ? NumCast(this._document!.nativeWidth, this._panelWidth) : 0;
-    nativeHeight = () => !BoolCast(this._document!.ignoreAspect) ? NumCast(this._document!.nativeHeight, this._panelHeight) : 0;
+    nativeWidth = () => !this._document!.ignoreAspect ? NumCast(this._document!.nativeWidth) || this._panelWidth : 0;
+    nativeHeight = () => !this._document!.ignoreAspect ? NumCast(this._document!.nativeHeight) || this._panelHeight : 0;
 
     contentScaling = () => {
         const nativeH = this.nativeHeight();
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 9d2671356..ba3d8e6a7 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -9,7 +9,7 @@ import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
 import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from "../../../new_fields/Types";
 import { emptyFunction } from "../../../Utils";
 import { DocumentType } from "../../documents/Documents";
 import { DragManager } from "../../util/DragManager";
@@ -20,6 +20,9 @@ import { CollectionSchemaPreview } from "./CollectionSchemaView";
 import "./CollectionStackingView.scss";
 import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
 import { CollectionSubView } from "./CollectionSubView";
+import { ContextMenu } from "../ContextMenu";
+import { ContextMenuProps } from "../ContextMenuItem";
+import { ScriptBox } from "../ScriptBox";
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -76,17 +79,24 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
 
     componentDidMount() {
         // is there any reason this needs to exist? -syip
-        this._heightDisposer = reaction(() => [this.props.Document.autoHeight, this.yMargin, this.props.Document[WidthSym](), this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])],
-            () => {
-                if (this.singleColumn && BoolCast(this.props.Document.autoHeight)) {
-                    let hgt = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => {
-                        let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d);
-                        return height + this.getDocHeight(pair.layout) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap);
-                    }, this.yMargin);
-                    (this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc)
-                        .height = hgt * (this.props as any).ContentScaling();
+        this._heightDisposer = reaction(() => {
+            if (this.singleColumn && BoolCast(this.props.Document.autoHeight)) {
+                let hgt = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => {
+                    let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d);
+                    return height + this.getDocHeight(pair.layout) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap);
+                }, this.yMargin);
+                return hgt * this.props.ContentScaling();
+            }
+            return -1;
+        },
+            (hgt: number) => {
+                if (hgt !== -1) {
+                    let doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
+                    doc.height = hgt;
                 }
-            }, { fireImmediately: true });
+            },
+            { fireImmediately: true }
+        );
 
         // reset section headers when a new filter is inputted
         this._sectionFilterDisposer = reaction(
@@ -109,9 +119,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     overlays = (doc: Doc) => {
-        return doc.type === DocumentType.IMG || doc.type === DocumentType.VID ? { title: "title", caption: "caption" } : {};
+        return doc.type === DocumentType.IMG || doc.type === DocumentType.VID ? { title: StrCast(this.props.Document.showTitles), caption: StrCast(this.props.Document.showCaptions) } : {};
     }
 
+    @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); }
+    @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : ScriptCast(this.Document.onChildClick); }
+
     getDisplayDoc(layoutDoc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) {
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
@@ -121,7 +134,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             showOverlays={this.overlays}
             renderDepth={this.props.renderDepth}
             fitToBox={this.props.fitToBox}
-            onClick={this.props.onClick}
+            onClick={layoutDoc.isTemplate ? this.onClickHandler : this.onChildClickHandler}
             width={width}
             height={height}
             getTransform={finalDxf}
@@ -141,7 +154,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         let nh = NumCast(d.nativeHeight);
         if (!d.ignoreAspect && nw && nh) {
             let aspect = nw && nh ? nh / nw : 1;
-            let wid = this.props.Document.fillColumn ? this.columnWidth / columnScale : Math.min(d[WidthSym](), this.columnWidth / columnScale);
+            let wid = this.props.Document.fillColumn ? this.columnWidth / columnScale : Math.min(Math.min(d[WidthSym](), NumCast(d.nativeWidth)), this.columnWidth / columnScale);
             return wid * aspect;
         }
         return d[HeightSym]();
@@ -267,7 +280,19 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     onToggle = (checked: Boolean) => {
-        this.props.CollectionView.props.Document.chromeSatus = checked ? "collapsed" : "view-mode";
+        this.props.CollectionView.props.Document.chromeStatus = checked ? "collapsed" : "view-mode";
+    }
+
+    onContextMenu = (e: React.MouseEvent): void => {
+        // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
+        if (!e.isPropagationStopped()) {
+            let subItems: ContextMenuProps[] = [];
+            subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" });
+            subItems.push({ description: `${this.props.Document.showTitles ? "Hide Titles" : "Show Titles"}`, event: () => this.props.Document.showTitles = !this.props.Document.showTitles ? "title" : "", icon: "plus" });
+            subItems.push({ description: `${this.props.Document.showCaptions ? "Hide Captions" : "Show Captions"}`, event: () => this.props.Document.showCaptions = !this.props.Document.showCaptions ? "caption" : "", icon: "plus" });
+            subItems.push({ description: "Edit onChildClick script", icon: "edit", event: () => ScriptBox.EditClickScript(this.props.Document, "onChildClick") });
+            ContextMenu.Instance.addItem({ description: "Stacking Options ...", subitems: subItems, icon: "eye" });
+        }
     }
 
     render() {
@@ -282,7 +307,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
         return (
             <div className="collectionStackingView"
-                ref={this.createRef} onDrop={this.onDrop.bind(this)} onWheel={(e: React.WheelEvent) => e.stopPropagation()} >
+                ref={this.createRef} onDrop={this.onDrop.bind(this)} onContextMenu={this.onContextMenu} onWheel={(e: React.WheelEvent) => e.stopPropagation()} >
                 {this.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
                     map((section: [SchemaHeaderField, Doc[]]) => this.section(section[0], section[1])) :
                     this.section(undefined, this.filteredChildren)}
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 817f9f4cb..9824a501b 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -84,7 +84,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             let headings = this.props.headings();
             let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
             let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d);
-            let width = () => (d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? Math.min(NumCast(d.nativeWidth), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1);
+            let width = () => (d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? Math.min(Math.min(d[WidthSym](), NumCast(d.nativeWidth)), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1);
             let height = () => parent.getDocHeight(pair.layout, uniqueHeadings.length + 1);// / (d.nativeWidth && !BoolCast(d.ignoreAspect) ? uniqueHeadings.length + 1 : 1);
             let dref = React.createRef<HTMLDivElement>();
             // if (uniqueHeadings.length > 0) {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 8b939259c..aaaa623fb 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -30,7 +30,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
 
     public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); }
 
-    constructor(props:any) {
+    constructor(props: any) {
         super(props);
     }
 
@@ -69,7 +69,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
     @action
     private collapse = (value: boolean) => {
         this._collapsed = value;
-        this.props.Document.chromeStatus = value ? "collapsed" : "visible";
+        this.props.Document.chromeStatus = value ? "collapsed" : "enabled";
     }
 
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
@@ -90,12 +90,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
     onContextMenu = (e: React.MouseEvent): void => {
         if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             let subItems: ContextMenuProps[] = [];
-            subItems.push({
-                description: "Freeform", event: () => {
-                    this.props.Document.viewType = CollectionViewType.Freeform;
-                    delete this.props.Document.usePivotLayout;
-                }, icon: "signature"
-            });
+            subItems.push({ description: "Freeform", event: () => { this.props.Document.viewType = CollectionViewType.Freeform; delete this.props.Document.usePivotLayout; }, icon: "signature" });
             if (CollectionBaseView.InSafeMode()) {
                 ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => this.props.Document.viewType = CollectionViewType.Invalid, icon: "project-diagram" });
             }
@@ -111,10 +106,10 @@ export class CollectionView extends React.Component<FieldViewProps> {
                 }
             }
             ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" });
-            ContextMenu.Instance.addItem({ description: "Apply Template", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" });
-            ContextMenu.Instance.addItem({
-                description: this.props.Document.chromeStatus !== "disabled" ? "Hide Chrome" : "Show Chrome", event: () => this.props.Document.chromeStatus = (this.props.Document.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram"
-            });
+            let existing = ContextMenu.Instance.findByDescription("Layout...");
+            let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
+            layoutItems.push({ description: "Create Layout Instance", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" });
+            !existing && ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "hand-point-right" });
         }
     }
 
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 52c47e7e8..bccc0a5b2 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -37,7 +37,6 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     @observable private _dateWithinValue: string = "";
     @observable private _dateValue: Date | string = "";
     @observable private _keyRestrictions: [JSX.Element, string][] = [];
-    @observable private _collapsed: boolean = false;
     @computed private get filterValue() { return Cast(this.props.CollectionView.props.Document.viewSpecScript, ScriptField); }
 
     private _picker: any;
@@ -61,7 +60,6 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
                     throw new Error("how did you get here, if chrome status is 'disabled' on a collection, a chrome shouldn't even be instantiated!");
                 }
                 else if (chromeStatus === "collapsed") {
-                    this._collapsed = true;
                     if (this.props.collapse) {
                         this.props.collapse(true);
                     }
@@ -163,9 +161,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
 
     @action
     toggleCollapse = () => {
-        this._collapsed = !this._collapsed;
+        this.props.CollectionView.props.Document.chromeStatus = this.props.CollectionView.props.Document.chromeStatus === "enabled" ? "collapsed" : "enabled";
         if (this.props.collapse) {
-            this.props.collapse(this._collapsed);
+            this.props.collapse(this.props.CollectionView.props.Document.chromeStatus !== "enabled");
         }
     }
 
@@ -218,16 +216,17 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     }
 
     render() {
+        let collapsed = this.props.CollectionView.props.Document.chromeStatus !== "enabled";
         return (
-            <div className="collectionViewChrome-cont" style={{ top: this._collapsed ? -70 : 0 }}>
+            <div className="collectionViewChrome-cont" style={{ top: collapsed ? -70 : 0 }}>
                 <div className="collectionViewChrome">
                     <div className="collectionViewBaseChrome">
                         <button className="collectionViewBaseChrome-collapse"
                             style={{
-                                top: this._collapsed ? 70 : 10,
-                                transform: `rotate(${this._collapsed ? 180 : 0}deg) scale(${this._collapsed ? 0.5 : 1}) translate(${this._collapsed ? "-100%, -100%" : "0, 0"})`,
-                                opacity: (this._collapsed && !this.props.CollectionView.props.isSelected()) ? 0 : 0.9,
-                                left: (this._collapsed ? 0 : "unset"),
+                                top: collapsed ? 70 : 10,
+                                transform: `rotate(${collapsed ? 180 : 0}deg) scale(${collapsed ? 0.5 : 1}) translate(${collapsed ? "-100%, -100%" : "0, 0"})`,
+                                opacity: (collapsed && !this.props.CollectionView.props.isSelected()) ? 0 : 0.9,
+                                left: (collapsed ? 0 : "unset"),
                             }}
                             title="Collapse collection chrome" onClick={this.toggleCollapse}>
                             <FontAwesomeIcon icon="caret-up" size="2x" />
@@ -243,7 +242,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
                             <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="5">Stacking View</option>
                             <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="6">Masonry View</option>
                         </select>
-                        <div className="collectionViewBaseChrome-viewSpecs" style={{ display: this._collapsed ? "none" : "grid" }}>
+                        <div className="collectionViewBaseChrome-viewSpecs" style={{ display: collapsed ? "none" : "grid" }}>
                             <input className="collectionViewBaseChrome-viewSpecsInput"
                                 placeholder="FILTER DOCUMENTS"
                                 value={this.filterValue ? this.filterValue.script.originalScript : ""}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 30010e826..0501bf929 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -816,17 +816,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     onContextMenu = (e: React.MouseEvent) => {
         let layoutItems: ContextMenuProps[] = [];
-        layoutItems.push({
-            description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`,
-            event: this.fitToContainer,
-            icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt"
-        });
-        layoutItems.push({
-            description: "reset view", event: () => {
-                this.props.Document.panX = this.props.Document.panY = 0;
-                this.props.Document.scale = 1;
-            }, icon: "compress-arrows-alt"
-        });
+        layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
+        layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
         layoutItems.push({
             description: `${this.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`,
             event: async () => {
@@ -841,50 +832,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             event: async () => this.props.Document.clusterOverridesDefaultBackground = !this.props.Document.clusterOverridesDefaultBackground,
             icon: !this.props.Document.useClusters ? "chalkboard" : "chalkboard"
         });
-        layoutItems.push({
-            description: "Arrange contents in grid",
-            event: this.arrangeContents,
-            icon: "table"
-        });
-        ContextMenu.Instance.addItem({
-            description: "Layout...",
-            subitems: layoutItems,
-            icon: "compass"
-        });
-        ContextMenu.Instance.addItem({
-            description: "Analyze Strokes",
-            event: this.analyzeStrokes,
-            icon: "paint-brush"
-        });
-        ContextMenu.Instance.addItem({
-            description: "Import document", icon: "upload", event: () => {
-                const input = document.createElement("input");
-                input.type = "file";
-                input.accept = ".zip";
-                input.onchange = async _e => {
-                    const files = input.files;
-                    if (!files) return;
-                    const file = files[0];
-                    let formData = new FormData();
-                    formData.append('file', file);
-                    formData.append('remap', "true");
-                    const upload = Utils.prepend("/uploadDoc");
-                    const response = await fetch(upload, { method: "POST", body: formData });
-                    const json = await response.json();
-                    if (json === "error") {
-                        return;
-                    }
-                    const doc = await DocServer.GetRefField(json);
-                    if (!doc || !(doc instanceof Doc)) {
-                        return;
-                    }
-                    const [x, y] = this.props.ScreenToLocalTransform().transformPoint(e.pageX, e.pageY);
-                    doc.x = x, doc.y = y;
-                    this.addDocument(doc, false);
-                };
-                input.click();
-            }
-        });
+        layoutItems.push({ description: "Arrange contents in grid", event: this.arrangeContents, icon: "table" });
+        ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" });
+
+        let existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers...");
+        let analyzers: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : [];
+        analyzers.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
+        !existingAnalyze && ContextMenu.Instance.addItem({ description: "Analyzers...", subitems: analyzers, icon: "hand-point-right" });
     }
 
 
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 2466f13f6..c73e960d8 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -85,8 +85,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         let list = {
             ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit,
             Document: this.layoutDoc,
-            DataDoc: this.dataDoc,
-            onClick: this.props.onClick
+            DataDoc: this.dataDoc
         };
         return { props: list };
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b8e2eb436..a702ab80e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -8,13 +8,15 @@ import { Copy, Id } from '../../../new_fields/FieldSymbols';
 import { List } from "../../../new_fields/List";
 import { ObjectField } from "../../../new_fields/ObjectField";
 import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema";
-import { BoolCast, Cast, FieldValue, NumCast, StrCast, PromiseValue } from "../../../new_fields/Types";
+import { ScriptField } from '../../../new_fields/ScriptField';
+import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { RouteStore } from '../../../server/RouteStore';
 import { emptyFunction, returnTrue, Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { Docs, DocUtils } from "../../documents/Documents";
 import { ClientUtils } from '../../util/ClientUtils';
+import { DictationManager } from '../../util/DictationManager';
 import { DocumentManager } from "../../util/DocumentManager";
 import { DragManager, dropActionType } from "../../util/DragManager";
 import { LinkManager } from '../../util/LinkManager';
@@ -29,20 +31,16 @@ import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from '../ContextMenuItem';
 import { DocComponent } from "../DocComponent";
 import { EditableView } from '../EditableView';
+import { MainView } from '../MainView';
 import { OverlayView } from '../OverlayView';
 import { PresentationView } from "../presentationview/PresentationView";
+import { ScriptBox } from '../ScriptBox';
 import { ScriptingRepl } from '../ScriptingRepl';
 import { Template } from "./../Templates";
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
 import { FormattedTextBox } from './FormattedTextBox';
 import React = require("react");
-import { DictationManager } from '../../util/DictationManager';
-import { MainView } from '../MainView';
-import { ScriptBox } from '../ScriptBox';
-import { CompileScript } from '../../util/Scripting';
-import { DocumentIconContainer } from './DocumentIcon';
-import { ScriptField } from '../../../new_fields/ScriptField';
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 library.add(fa.faTrash);
@@ -297,8 +295,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     onClick = async (e: React.MouseEvent) => {
         if (e.nativeEvent.cancelBubble) return; // needed because EditableView may stopPropagation which won't apparently stop this event from firing.
         e.stopPropagation();
-        if (this.onClickHandler) {
-            this.onClickHandler.script.run({ this: this.props.Document });
+        if (this.onClickHandler && this.onClickHandler.script) {
+            this.onClickHandler.script.run({ this: this.props.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document });
             e.preventDefault();
             return;
         }
@@ -573,37 +571,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" });
         subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" });
         cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" });
-        cm.addItem({ description: BoolCast(this.props.Document.ignoreAspect, false) || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" });
-        cm.addItem({ description: "Pin to Presentation", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
-        cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
-        cm.addItem({ description: "Transcribe Speech", event: this.listen, icon: "microphone" });
-        cm.addItem({
-            description: "Edit OnClick script", icon: "edit", event: () => {
-                let overlayDisposer: () => void = emptyFunction;
-                const script = this.Document.onClick;
-                let originalText: string | undefined = undefined;
-                if (script) originalText = script.script.originalScript;
-                // tslint:disable-next-line: no-unnecessary-callback-wrapper
-                let scriptingBox = <ScriptBox initialText={originalText} onCancel={() => overlayDisposer()} onSave={(text, onError) => {
-                    const script = CompileScript(text, {
-                        params: { this: Doc.name },
-                        typecheck: false,
-                        editable: true,
-                        transformer: DocumentIconContainer.getTransformer()
-                    });
-                    if (!script.compiled) {
-                        onError(script.errors.map(error => error.messageText).join("\n"));
-                        return;
-                    }
-                    this.Document.onClick = new ScriptField(script);
-                    overlayDisposer();
-                }} showDocumentIcons />;
-                overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${this.Document.title || ""} OnClick` });
-            }
-        });
-        let makes: ContextMenuProps[] = [];
+        let existingMake = ContextMenu.Instance.findByDescription("Make...");
+        let makes: ContextMenuProps[] = existingMake && "subitems" in existingMake ? existingMake.subitems : [];
         makes.push({ description: this.props.Document.isBackground ? "Remove Background" : "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
         makes.push({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" });
+        makes.push({ description: "Edit OnClick script", icon: "edit", event: () => ScriptBox.EditClickScript(this.props.Document, "onClick") });
         makes.push({
             description: "Make Portal", event: () => {
                 let portal = Docs.Create.FreeformDocument([], { width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: this.props.Document.title + ".portal" });
@@ -618,15 +590,19 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
             }, icon: "window-restore"
         });
-        cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" });
-        if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) {
-            cm.addItem({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" });
-        }
-        cm.addItem({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) });
+        !existingMake && cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" });
         let existing = ContextMenu.Instance.findByDescription("Layout...");
         let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
+
+        layoutItems.push({ description: `${this.props.Document.chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.props.Document.chromeStatus = (this.props.Document.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
+        layoutItems.push({ description: `${this.props.Document.autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.props.Document.autoHeight = !this.props.Document.autoHeight, icon: "plus" });
+        layoutItems.push({ description: BoolCast(this.props.Document.ignoreAspect, false) || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" });
+        layoutItems.push({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
         layoutItems.push({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" });
         layoutItems.push({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" });
+        if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) {
+            layoutItems.push({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" });
+        }
         !existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" });
         if (!ClientUtils.RELEASE) {
             let copies: ContextMenuProps[] = [];
@@ -634,6 +610,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             copies.push({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
             cm.addItem({ description: "Copy...", subitems: copies, icon: "copy" });
         }
+        let existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers...");
+        let analyzers: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : [];
+        analyzers.push({ description: "Transcribe Speech", event: this.listen, icon: "microphone" });
+        !existingAnalyze && cm.addItem({ description: "Analyzers...", subitems: analyzers, icon: "hand-point-right" });
+        cm.addItem({ description: "Pin to Presentation", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
+        cm.addItem({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) });
         cm.addItem({
             description: "Download document", icon: "download", event: () => {
                 const a = document.createElement("a");
@@ -643,6 +625,36 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 a.click();
             }
         });
+
+        cm.addItem({
+            description: "Import document", icon: "upload", event: () => {
+                const input = document.createElement("input");
+                input.type = "file";
+                input.accept = ".zip";
+                input.onchange = async _e => {
+                    const files = input.files;
+                    if (!files) return;
+                    const file = files[0];
+                    let formData = new FormData();
+                    formData.append('file', file);
+                    formData.append('remap', "true");
+                    const upload = Utils.prepend("/uploadDoc");
+                    const response = await fetch(upload, { method: "POST", body: formData });
+                    const json = await response.json();
+                    if (json === "error") {
+                        return;
+                    }
+                    const doc = await DocServer.GetRefField(json);
+                    if (!doc || !(doc instanceof Doc)) {
+                        return;
+                    }
+                    const [x, y] = this.props.ScreenToLocalTransform().transformPoint(e.pageX, e.pageY);
+                    doc.x = x, doc.y = y;
+                    this.props.addDocument && this.props.addDocument(doc, false);
+                };
+                input.click();
+            }
+        });
         cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
         type User = { email: string, userDocumentId: string };
         let usersMenu: ContextMenuProps[] = [];
@@ -715,7 +727,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
     }
 
+    @computed get brushedDegree() { return Doc.IsBrushedDegree(this.layoutDoc); }
+
     render() {
+        trace();
         let backgroundColor = this.layoutDoc.isBackground || (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground && this.layoutDoc.backgroundColor === this.layoutDoc.defaultBackgroundColor) ?
             this.props.backgroundColor(this.layoutDoc) || StrCast(this.layoutDoc.backgroundColor) :
             StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc);
@@ -733,7 +748,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             });
         }
         let showTextTitle = showTitle && StrCast(this.layoutDoc.layout).startsWith("<FormattedTextBox") ? showTitle : undefined;
-        let brushDegree = Doc.IsBrushedDegree(this.layoutDoc);
+        let brushDegree = 0;//this.brushedDegree;
         return (
             <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
@@ -779,7 +794,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                                     height={72}
                                     fontSize={12}
                                     GetValue={() => StrCast((this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle!])}
-                                    SetValue={(value: string) => (Doc.GetProto(this.layoutDoc)[showTitle!] = value) ? true : true}
+                                    SetValue={(value: string) => ((this.layoutDoc.isTemplate ? this.layoutDoc : Doc.GetProto(this.layoutDoc))[showTitle!] = value) ? true : true}
                                 />
                             </div>
                         }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index cf4f7f668..732576328 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -475,6 +475,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     }
 
     onPointerDown = (e: React.PointerEvent): void => {
+        if (this.onClick && e.button === 0) {
+            e.preventDefault();
+        }
         if (e.button === 0 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
             e.stopPropagation();
             if (FormattedTextBox._toolTipTextMenu && FormattedTextBox._toolTipTextMenu.tooltip) {
@@ -643,12 +646,12 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     }
 
     specificContextMenu = (e: React.MouseEvent): void => {
-        let subitems: ContextMenuProps[] = [];
-        subitems.push({
-            description: BoolCast(this.props.Document.autoHeight) ? "Manual Height" : "Auto Height",
-            event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight)), icon: "expand-arrows-alt"
-        });
-        ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems, icon: "text-height" });
+        // let subitems: ContextMenuProps[] = [];
+        // subitems.push({
+        //     description: BoolCast(this.props.Document.autoHeight) ? "Manual Height" : "Auto Height",
+        //     event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight)), icon: "expand-arrows-alt"
+        // });
+        // ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems, icon: "text-height" });
     }
     render() {
         let self = this;
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 4cfd7929b..564446bb8 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -516,6 +516,8 @@ export namespace Doc {
         otherdoc.miniLayout = StrCast(templateDoc.miniLayout);
         otherdoc.detailedLayout = otherdoc.layout;
         otherdoc.type = DocumentType.TEMPLATE;
+        !templateDoc.nativeWidth && (otherdoc.nativeWidth = 0);
+        !templateDoc.nativeHeight && (otherdoc.nativeHeight = 0);
         return otherdoc;
     }
     export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetData?: Doc) {
@@ -534,6 +536,8 @@ export namespace Doc {
             target.miniLayout = StrCast(templateDoc.miniLayout);
             target.detailedLayout = target.layout;
         }
+        !templateDoc.nativeWidth && (target.nativeWidth = 0);
+        !templateDoc.nativeHeight && (target.nativeHeight = 0);
     }
 
     export function MakeTemplate(fieldTemplate: Doc, metaKey: string, templateDataDoc: Doc) {
@@ -610,4 +614,7 @@ export namespace Doc {
 }
 Scripting.addGlobal(function renameAlias(doc: any, n: any) {
     return StrCast(doc.title).replace(/\([0-9]*\)/, "") + `(${n})`;
+});
+Scripting.addGlobal(function getProto(doc: any) {
+    return Doc.GetProto(doc);
 });
\ No newline at end of file
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 09cbff25e..0ca35fab2 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -2,6 +2,7 @@ import { Field, Opt, FieldResult, Doc } from "./Doc";
 import { List } from "./List";
 import { RefField } from "./RefField";
 import { DateField } from "./DateField";
+import { ScriptField } from "./ScriptField";
 
 export type ToType<T extends InterfaceValue> =
     T extends "string" ? string :
@@ -86,6 +87,9 @@ export function BoolCast(field: FieldResult, defaultVal: boolean | null = false)
 export function DateCast(field: FieldResult) {
     return Cast(field, DateField, null);
 }
+export function ScriptCast(field: FieldResult) {
+    return Cast(field, ScriptField, null);
+}
 
 type WithoutList<T extends Field> = T extends List<infer R> ? (R extends RefField ? (R | Promise<R>)[] : R[]) : T;
 
-- 
cgit v1.2.3-70-g09d2


From 01cf655111df11f21da2d0e66eb2f4b70b0827f5 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 13 Aug 2019 21:18:57 -0400
Subject: more layout fixes for masonry/stacking

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

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

diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 695c7951f..4efd8e050 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -154,7 +154,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         let nh = NumCast(d.nativeHeight);
         if (!d.ignoreAspect && nw && nh) {
             let aspect = nw && nh ? nh / nw : 1;
-            let wid = this.props.Document.fillColumn ? this.columnWidth / columnScale : Math.min(Math.min(d[WidthSym](), NumCast(d.nativeWidth)), this.columnWidth / columnScale);
+            let wid = d.nativeWidth && !d.ignoreAspect && this.props.Document.fillColumn ? this.columnWidth / columnScale : Math.min(d[WidthSym](), this.columnWidth / columnScale);
             return wid * aspect;
         }
         return d[HeightSym]();
@@ -276,7 +276,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         this._docXfs.length = 0;
         return docs.map((d, i) => {
             let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc);
-            let width = () => (d.nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? Math.min(Math.min(d[WidthSym](), NumCast(d.nativeWidth)), this.columnWidth) : this.columnWidth);/// (uniqueHeadings.length + 1);
+            let width = () => (d.nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth);/// (uniqueHeadings.length + 1);
             let height = () => this.getDocHeight(layoutDoc);
             let dref = React.createRef<HTMLDivElement>();
             let dxf = () => this.getDocTransform(layoutDoc, dref.current!);
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 9824a501b..4a8d7debd 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -84,7 +84,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             let headings = this.props.headings();
             let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
             let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d);
-            let width = () => (d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? Math.min(Math.min(d[WidthSym](), NumCast(d.nativeWidth)), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1);
+            let width = () => (d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? Math.min(d[WidthSym](), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1);
             let height = () => parent.getDocHeight(pair.layout, uniqueHeadings.length + 1);// / (d.nativeWidth && !BoolCast(d.ignoreAspect) ? uniqueHeadings.length + 1 : 1);
             let dref = React.createRef<HTMLDivElement>();
             // if (uniqueHeadings.length > 0) {
-- 
cgit v1.2.3-70-g09d2


From c357ef923eafc17210f278d36a0693fe902b21fb Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 14 Aug 2019 13:41:23 -0400
Subject: fixed more sizing issues with stacking/masonry views

---
 .../views/collections/CollectionDockingView.tsx    |  2 +-
 .../views/collections/CollectionStackingView.tsx   | 90 +++++++++-------------
 .../CollectionStackingViewFieldColumn.tsx          | 66 +++++-----------
 3 files changed, 60 insertions(+), 98 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 13bb34037..7332a490a 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -389,7 +389,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 const stack = tab.contentItem.parent;
                 // shifts the focus to this tab when another tab is dragged over it
                 tab.element[0].onmouseenter = (e: any) => {
-                    if (!this._isPointerDown) return;
+                    if (!this._isPointerDown || !SelectionManager.GetIsDragging()) return;
                     var activeContentItem = tab.header.parent.getActiveContentItem();
                     if (tab.contentItem !== activeContentItem) {
                         tab.header.parent.setActiveContentItem(tab.contentItem);
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index d68ef2bbd..4e49e368b 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -10,7 +10,7 @@ import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
 import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from "../../../new_fields/Types";
-import { emptyFunction, Utils } from "../../../Utils";
+import { emptyFunction, Utils, numberRange } from "../../../Utils";
 import { DocumentType } from "../../documents/Documents";
 import { DragManager } from "../../util/DragManager";
 import { Transform } from "../../util/Transform";
@@ -33,14 +33,21 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     _docXfs: any[] = [];
     _columnStart: number = 0;
     @observable private cursor: CursorProperty = "grab";
-    get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); }
+    @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); }
+    @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); }
+    @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); }
     @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); }
     @computed get yMargin() { return NumCast(this.props.Document.yMargin, 2 * this.gridGap); }
     @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); }
-    @computed get singleColumn() { return BoolCast(this.props.Document.singleColumn, true); }
-    @computed get columnWidth() { return this.singleColumn ? (this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin) : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.props.Document.columnWidth, 250)); }
-    @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); }
-    @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); }
+    @computed get isStackingView() { return BoolCast(this.props.Document.singleColumn, true); }
+    @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; }
+    @computed get showAddAGroup() { return (this.sectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')); }
+    @computed get columnWidth() {
+        return Math.min(this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin,
+            this.isStackingView ? Number.MAX_VALUE : NumCast(this.props.Document.columnWidth, 250));
+    }
+
+    childDocHeight(child: Doc) { return this.getDocHeight(Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, child).layout); }
 
     get layoutDoc() {
         // if this document's layout field contains a document (ie, a rendering template), then we will use that
@@ -48,7 +55,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
     }
 
-
     get Sections() {
         if (!this.sectionFilter) return new Map<SchemaHeaderField, Doc[]>();
 
@@ -78,33 +84,19 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     componentDidMount() {
-        // is there any reason this needs to exist? -syip
+        // is there any reason this needs to exist? -syip.  yes, it handles autoHeight for stacking views (masonry isn't yet supported).
         this._heightDisposer = reaction(() => {
-            if (this.singleColumn && BoolCast(this.props.Document.autoHeight)) {
-                let maxHght = 0;
-                Array.from(this.Sections.values()).map(s => {
-                    let hgt = 50 + s.reduce((height, d, i) => {
-                        let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d);
-                        return height + this.getDocHeight(pair.layout, this.Sections.size) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap);
-                    }, this.yMargin);
-                    maxHght = Math.max(hgt, maxHght);
-                })
-                if (!maxHght) {
-                    let hgt = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => {
-                        let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d);
-                        return height + this.getDocHeight(pair.layout) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap);
-                    }, this.yMargin);
-                    maxHght = hgt * this.props.ContentScaling();
-                }
-                return maxHght * this.props.ContentScaling();
+            if (this.isStackingView && BoolCast(this.props.Document.autoHeight)) {
+                let sectionsList = Array.from(this.Sections.size ? this.Sections.values() : [this.filteredChildren]);
+                return this.props.ContentScaling() * sectionsList.reduce((maxHght, s) => Math.max(maxHght,
+                    50 + s.reduce((height, d, i) => height + this.childDocHeight(d) + (i === s.length - 1 ? this.yMargin : this.gridGap), this.yMargin)
+                ), 0);
             }
             return -1;
         },
             (hgt: number) => {
-                if (hgt !== -1) {
-                    let doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
-                    doc.height = hgt;
-                }
+                let doc = hgt === -1 ? undefined : this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
+                doc && (doc.height = hgt);
             },
             { fireImmediately: true }
         );
@@ -137,7 +129,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : ScriptCast(this.Document.onChildClick); }
 
     getDisplayDoc(layoutDoc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) {
-        let height = () => this.getDocHeight(layoutDoc, this.singleColumn ? this.Sections.size : 1);
+        let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
         return <CollectionSchemaPreview
             Document={layoutDoc}
@@ -160,12 +152,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             previewScript={undefined}>
         </CollectionSchemaPreview>;
     }
-    getDocHeight(d: Doc, columnScale: number = 1) {
+    getDocHeight(d: Doc) {
         let nw = NumCast(d.nativeWidth);
         let nh = NumCast(d.nativeHeight);
         if (!d.ignoreAspect && nw && nh) {
             let aspect = nw && nh ? nh / nw : 1;
-            let wid = d.nativeWidth && !d.ignoreAspect && this.props.Document.fillColumn ? this.columnWidth / columnScale : Math.min(d[WidthSym](), this.columnWidth / columnScale);
+            let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1);
+            if (!(d.nativeWidth && !d.ignoreAspect && this.props.Document.fillColumn)) wid = Math.min(d[WidthSym](), wid);
             return wid * aspect;
         }
         return d[HeightSym]();
@@ -251,15 +244,14 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         });
     }
     headings = () => Array.from(this.Sections.keys());
-    section = (heading: SchemaHeaderField | undefined, docList: Doc[]) => {
-        if (!this.singleColumn) return this.sectionMasonry(heading, docList);
+    sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => {
         let key = this.sectionFilter;
         let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
         let types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]);
         if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) {
             type = types[0];
         }
-        let cols = () => this.singleColumn ? 1 : Math.max(1, Math.min(this.filteredChildren.length,
+        let cols = () => this.isStackingView ? 1 : Math.max(1, Math.min(this.filteredChildren.length,
             Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
         return <CollectionStackingViewFieldColumn
             key={heading ? heading.heading : ""}
@@ -283,13 +275,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             translate(offset[0], offset[1]).
             scale(NumCast(doc.width, 1) / this.columnWidth);
     }
-    children(docs: Doc[]) {
+    masonryChildren(docs: Doc[]) {
         this._docXfs.length = 0;
         return docs.map((d, i) => {
+            let dref = React.createRef<HTMLDivElement>();
             let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc);
             let width = () => (d.nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth);/// (uniqueHeadings.length + 1);
             let height = () => this.getDocHeight(layoutDoc);
-            let dref = React.createRef<HTMLDivElement>();
             let dxf = () => this.getDocTransform(layoutDoc, dref.current!);
             let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
             this._docXfs.push({ dxf: dxf, width: width, height: height });
@@ -302,8 +294,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     sectionMasonry(heading: SchemaHeaderField | undefined, docList: Doc[]) {
         let cols = Math.max(1, Math.min(docList.length,
             Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
-        let templatecols = "";
-        for (let i = 0; i < cols; i++) templatecols += `${this.columnWidth}px `;
         return <div key={heading ? heading.heading : "empty"} className="collectionStackingView-masonrySection">
             {!heading ? (null) :
                 <div key={`${heading.heading}`} className="collectionStackingView-sectionHeader" style={{ background: heading.color }}>
@@ -314,10 +304,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                     padding: `${this.yMargin}px ${this.xMargin}px`,
                     width: `${cols * (this.columnWidth + this.gridGap) + 2 * this.xMargin - this.gridGap}px`,
                     gridGap: this.gridGap,
-                    gridTemplateColumns: templatecols,
-                }}
-            >
-                {this.children(docList)}
+                    gridTemplateColumns: numberRange(cols).reduce((list, i) => list + ` ${this.columnWidth}px`, ""),
+                }}>
+                {this.masonryChildren(docList)}
                 {this.columnDragger}
             </div>
         </div>;
@@ -356,7 +345,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     render() {
-        let headings = Array.from(this.Sections.keys());
         let editableViewProps = {
             GetValue: () => "",
             SetValue: this.addGroup,
@@ -364,18 +352,16 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         };
         Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
 
-        // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
+        let sections = (this.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc) : [[undefined, this.filteredChildren] as [SchemaHeaderField | undefined, Doc[]]])
         return (
-            <div className={this.singleColumn ? "collectionStackingView" : "collectionMasonryView"}
+            <div className={this.isStackingView ? "collectionStackingView" : "collectionMasonryView"}
                 ref={this.createRef} onDrop={this.onDrop.bind(this)} onContextMenu={this.onContextMenu} onWheel={(e: React.WheelEvent) => e.stopPropagation()} >
-                {this.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
-                    map((section: [SchemaHeaderField, Doc[]]) => this.section(section[0], section[1])) :
-                    this.section(undefined, this.filteredChildren)}
-                {(this.sectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')) ?
+                {sections.map(section => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1]))}
+                {!this.showAddAGroup ? (null) :
                     <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
-                        style={{ width: (this.columnWidth / (headings.length + ((this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0))) - 10, marginTop: 10 }}>
+                        style={{ width: this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
-                    </div> : null}
+                    </div>}
                 {this.props.CollectionView.props.Document.chromeStatus !== 'disabled' ? <Switch
                     onChange={this.onToggle}
                     onClick={this.onToggle}
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 4a8d7debd..74c7ef305 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -1,28 +1,25 @@
 import React = require("react");
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faPalette } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, observable } from "mobx";
 import { observer } from "mobx-react";
-import { number } from "prop-types";
 import { Doc, WidthSym } from "../../../new_fields/Doc";
-import { CollectionStackingView } from "./CollectionStackingView";
 import { Id } from "../../../new_fields/FieldSymbols";
+import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { ScriptField } from "../../../new_fields/ScriptField";
+import { NumCast, StrCast } from "../../../new_fields/Types";
 import { Utils } from "../../../Utils";
-import { NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
-import { EditableView } from "../EditableView";
-import { action, observable, computed } from "mobx";
-import { undoBatch } from "../../util/UndoManager";
-import { DragManager } from "../../util/DragManager";
-import { DocumentManager } from "../../util/DocumentManager";
-import { SelectionManager } from "../../util/SelectionManager";
-import "./CollectionStackingView.scss";
 import { Docs } from "../../documents/Documents";
-import { SchemaHeaderField, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { ScriptField } from "../../../new_fields/ScriptField";
+import { DragManager } from "../../util/DragManager";
 import { CompileScript } from "../../util/Scripting";
-import { RichTextField } from "../../../new_fields/RichTextField";
+import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
-import { Flyout, anchorPoints } from "../DocumentDecorations";
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faPalette } from '@fortawesome/free-solid-svg-icons';
+import { undoBatch } from "../../util/UndoManager";
+import { anchorPoints, Flyout } from "../DocumentDecorations";
+import { EditableView } from "../EditableView";
+import { CollectionStackingView } from "./CollectionStackingView";
+import "./CollectionStackingView.scss";
 
 library.add(faPalette);
 
@@ -81,38 +78,17 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         let parent = this.props.parent;
         parent._docXfs.length = 0;
         return docs.map((d, i) => {
-            let headings = this.props.headings();
-            let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
             let pair = Doc.GetLayoutDataDocPair(parent.props.Document, parent.props.DataDoc, parent.props.fieldKey, d);
-            let width = () => (d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? Math.min(d[WidthSym](), parent.columnWidth / (uniqueHeadings.length + 1)) : parent.columnWidth / (uniqueHeadings.length + 1));/// (uniqueHeadings.length + 1);
-            let height = () => parent.getDocHeight(pair.layout, uniqueHeadings.length + 1);// / (d.nativeWidth && !BoolCast(d.ignoreAspect) ? uniqueHeadings.length + 1 : 1);
+            let width = () => Math.min(d.nativeWidth && !d.ignoreAspect && !parent.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, parent.columnWidth / parent.numGroupColumns);
+            let height = () => parent.getDocHeight(pair.layout);
             let dref = React.createRef<HTMLDivElement>();
-            // if (uniqueHeadings.length > 0) {
             let dxf = () => this.getDocTransform(pair.layout, dref.current!);
             this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height });
-            // }
-            // else {
-            //     //have to add the height of all previous single column sections or the doc decorations will be in the wrong place.
-            //     let dxf = () => this.getDocTransform(layoutDoc, i, width());
-            //     this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height });
-            // }
-            let rowHgtPcnt = height();
             let rowSpan = Math.ceil((height() + parent.gridGap) / parent.gridGap);
-            let style = parent.singleColumn ? { width: width(), margin: "auto", marginTop: i === 0 ? 0 : parent.gridGap, height: `${rowHgtPcnt}` } : { gridRowEnd: `span ${rowSpan}` };
-            return <div className={`collectionStackingView-${parent.singleColumn ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} >
+            let style = parent.isStackingView ? { width: width(), margin: "auto", marginTop: i === 0 ? 0 : parent.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` };
+            return <div className={`collectionStackingView-${parent.isStackingView ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} >
                 {this.props.parent.getDisplayDoc(pair.layout, pair.data, dxf, width)}
             </div>;
-            // } else {
-            // let dref = React.createRef<HTMLDivElement>();
-            // let dxf = () => this.getDocTransform(layoutDoc, dref.current!);
-            // this.props.parent._docXfs.push({ dxf: dxf, width: width, height: height });
-            // let rowHgtPcnt = height();
-            // let rowSpan = Math.ceil((height() + parent.gridGap) / parent.gridGap);
-            // let divStyle = parent.singleColumn ? { width: width(), marginTop: i === 0 ? 0 : parent.gridGap, height: `${rowHgtPcnt}` } : { gridRowEnd: `span ${rowSpan}` };
-            // return <div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} style={divStyle} >
-            //     {this.props.parent.getDisplayDoc(layoutDoc, d, dxf, width)}
-            // </div>;
-            // }
         });
     }
 
@@ -278,7 +254,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         let headings = this.props.headings();
         let heading = this._heading;
         let style = this.props.parent;
-        let singleColumn = style.singleColumn;
+        let singleColumn = style.isStackingView;
         let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
         let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`;
         let headerEditableViewProps = {
@@ -326,7 +302,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                         </button>}
                 </div>
             </div> : (null);
-        for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth}px `;
+        for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `;
         return (
             <div className="collectionStackingViewFieldColumn" key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
@@ -348,7 +324,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 </div>
                 {(this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.CollectionView.props.Document.chromeStatus !== 'disabled') ?
                     <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
-                        style={{ width: style.columnWidth / (uniqueHeadings.length + 1) }}>
+                        style={{ width: style.columnWidth / style.numGroupColumns }}>
                         <EditableView {...newEditableViewProps} />
                     </div> : null}
             </div>
-- 
cgit v1.2.3-70-g09d2

