From 6d25848a9e8614c1debc8550e42fc706f77883db Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 23 Jul 2019 19:07:08 -0400
Subject: more template stuff

---
 src/client/views/collections/CollectionTreeView.tsx | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index f98629c5b..ca5812eba 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -74,9 +74,10 @@ class TreeView extends React.Component<TreeViewProps> {
     @observable _collapsed: boolean = true;
 
     @computed get fieldKey() {
-        let keys = Array.from(Object.keys(this.dataDoc));  // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
-        if (this.dataDoc.proto instanceof Doc) {
-            let arr = Array.from(Object.keys(this.dataDoc.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
+        let target = this.props.document.layout && this.dataDoc ? this.dataDoc : this.props.document;
+        let keys = Array.from(Object.keys(target));  // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
+        if (target.proto instanceof Doc) {
+            let arr = Array.from(Object.keys(target.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
             keys.push(...arr);
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
@@ -191,16 +192,17 @@ class TreeView extends React.Component<TreeViewProps> {
     />)
 
     @computed get keyList() {
-        let keys = Array.from(Object.keys(this.dataDoc));
-        if (this.dataDoc.proto instanceof Doc) {
-            keys.push(...Array.from(Object.keys(this.dataDoc.proto)));
+        let target = this.props.document.layout && this.dataDoc ? this.dataDoc : this.props.document;
+        let keys = Array.from(Object.keys(target));
+        if (target.proto instanceof Doc) {
+            keys.push(...Array.from(Object.keys(target.proto)));
         }
         let keyList: string[] = keys.reduce((l, key) => {
-            let listspec = DocListCast(this.dataDoc[key]);
+            let listspec = DocListCast(target[key]);
             if (listspec && listspec.length) return [...l, key];
             return l;
         }, [] as string[]);
-        keys.map(key => Cast(this.dataDoc[key], Doc) instanceof Doc && (Cast(this.dataDoc[key], Doc) as Doc).type !== undefined && keyList.push(key));
+        keys.map(key => Cast(target[key], Doc) instanceof Doc && keyList.push(key));
         if (LinkManager.Instance.getAllRelatedLinks(this.props.document).length > 0) keyList.push("links");
         if (keyList.indexOf(this.fieldKey) !== -1) {
             keyList.splice(keyList.indexOf(this.fieldKey), 1);
@@ -361,7 +363,7 @@ class TreeView extends React.Component<TreeViewProps> {
         let docList = Cast(this.dataDoc[this._chosenKey], listSpec(Doc));
         let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
         let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this._chosenKey, doc, addBefore, before);
-        let doc = Cast(this.dataDoc[this._chosenKey], Doc);
+        let doc = Cast((this.props.document.layout ? this.dataDoc : this.props.document)[this._chosenKey], Doc);
 
         if (!this._collapsed) {
             if (!this.props.document.embed) {
-- 
cgit v1.2.3-70-g09d2


From 2bba7deec5e16671b4a1bbed6eac6008ca01ff7c Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 23 Jul 2019 22:28:58 -0400
Subject: cleanup of templates for treeview

---
 src/client/views/collections/CollectionTreeView.tsx |  8 ++++----
 src/client/views/nodes/FieldView.tsx                |  3 ++-
 src/new_fields/Doc.ts                               | 21 +++++++++++++++------
 3 files changed, 21 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ca5812eba..2ff9e43fe 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -74,7 +74,7 @@ class TreeView extends React.Component<TreeViewProps> {
     @observable _collapsed: boolean = true;
 
     @computed get fieldKey() {
-        let target = this.props.document.layout && this.dataDoc ? this.dataDoc : this.props.document;
+        let target = this.props.document;
         let keys = Array.from(Object.keys(target));  // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
         if (target.proto instanceof Doc) {
             let arr = Array.from(Object.keys(target.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
@@ -89,7 +89,7 @@ class TreeView extends React.Component<TreeViewProps> {
             }
         });
         let layout = StrCast(this.props.document.layout);
-        if (layout.indexOf("fieldKey={\"") !== -1) {
+        if (layout.indexOf("fieldKey={\"") !== -1 && layout.indexOf("fieldExt=") === -1) {
             return layout.split("fieldKey={\"")[1].split("\"")[0];
         }
         return keyList.length ? keyList[0] : "data";
@@ -192,7 +192,7 @@ class TreeView extends React.Component<TreeViewProps> {
     />)
 
     @computed get keyList() {
-        let target = this.props.document.layout && this.dataDoc ? this.dataDoc : this.props.document;
+        let target = this.props.document;
         let keys = Array.from(Object.keys(target));
         if (target.proto instanceof Doc) {
             keys.push(...Array.from(Object.keys(target.proto)));
@@ -363,10 +363,10 @@ class TreeView extends React.Component<TreeViewProps> {
         let docList = Cast(this.dataDoc[this._chosenKey], listSpec(Doc));
         let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
         let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this._chosenKey, doc, addBefore, before);
-        let doc = Cast((this.props.document.layout ? this.dataDoc : this.props.document)[this._chosenKey], Doc);
 
         if (!this._collapsed) {
             if (!this.props.document.embed) {
+                let doc = Cast(this.props.document[this._chosenKey], Doc);
                 contentElement = <ul key={this._chosenKey + "more"}>
                     {this._chosenKey === "links" ? this.renderLinks() :
                         TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.resolvedDataDoc, this._chosenKey, addDoc, remDoc, this.move,
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index ea6730cd0..ffaee8042 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -87,7 +87,8 @@ export class FieldView extends React.Component<FieldViewProps> {
             return <p>{field.date.toLocaleString()}</p>;
         }
         else if (field instanceof Doc) {
-            return <p><b>{field.title + " : id= " + field[Id]}</b></p>;
+            return <p><b>{field.title}</b></p>;
+            //return <p><b>{field.title + " : id= " + field[Id]}</b></p>;
             // let returnHundred = () => 100;
             // return (
             //     <DocumentContentsView Document={field}
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index e4bf4a6c1..5a9a0eab4 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -318,7 +318,7 @@ export namespace Doc {
         if (extensionDoc === undefined) {
             setTimeout(() => {
                 let docExtensionForField = new Doc(doc[Id] + fieldKey, true);
-                docExtensionForField.title = doc.title + ":" + fieldKey + ".ext";
+                docExtensionForField.title = fieldKey + "[" + StrCast(doc.title).match(/\.\.\.[0-9]*/) + "].ext";
                 docExtensionForField.extendsDoc = doc;
                 let proto: Doc | undefined = doc;
                 while (proto && !Doc.IsPrototype(proto)) {
@@ -337,9 +337,16 @@ export namespace Doc {
         return Doc.MakeDelegate(doc); // bcz?
     }
 
-    export function WillExpandTemplateLayout(templateLayoutDoc: Doc, dataDoc?: Doc) {
-        let resolvedDataDoc = (templateLayoutDoc !== dataDoc) ? dataDoc : undefined;
-        if (!dataDoc || !(templateLayoutDoc && !(Cast(templateLayoutDoc.layout, Doc) instanceof Doc) && resolvedDataDoc && resolvedDataDoc !== templateLayoutDoc)) {
+    //
+    // Determines whether the combination of the layoutDoc and dataDoc represents
+    // a template relationship.  If so, the layoutDoc will be expanded into a new
+    // document that inherits the properties of the original layout while allowing
+    // for individual layout properties to be overridden in the expanded layout.
+    //
+    export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) {
+        let resolvedDataDoc = (layoutDoc !== dataDoc) ? dataDoc : undefined;
+        if (!dataDoc || !(layoutDoc && !(Cast(layoutDoc.layout, Doc) instanceof Doc) &&
+            resolvedDataDoc && resolvedDataDoc !== layoutDoc)) {
             return false;
         }
         return true;
@@ -354,16 +361,18 @@ export namespace Doc {
         if (expandedTemplateLayout instanceof Doc) {
             return expandedTemplateLayout;
         }
-        expandedTemplateLayout = dataDoc[templateLayoutDoc.title + templateLayoutDoc[Id]];
+        // expandedTemplateLayout = dataDoc[templateLayoutDoc.title + templateLayoutDoc[Id]];
+        expandedTemplateLayout = dataDoc["Layout[" + templateLayoutDoc[Id] + "]"];
         if (expandedTemplateLayout instanceof Doc) {
             return expandedTemplateLayout;
         }
         if (expandedTemplateLayout === undefined && BoolCast(templateLayoutDoc.isTemplate)) {
             setTimeout(() => {
                 let expandedDoc = Doc.MakeDelegate(templateLayoutDoc);
+                //expandedDoc.title = templateLayoutDoc.title + "[" + StrCast(dataDoc.title).match(/\.\.\.[0-9]*/) + "]";
                 expandedDoc.title = templateLayoutDoc.title + "[" + StrCast(dataDoc.title).match(/\.\.\.[0-9]*/) + "]";
                 expandedDoc.isExpandedTemplate = templateLayoutDoc;
-                dataDoc[templateLayoutDoc.title + templateLayoutDoc[Id]] = expandedDoc;
+                dataDoc["Layout[" + templateLayoutDoc[Id] + "]"] = expandedDoc;
             }, 0);
         }
         return templateLayoutDoc; // use the templateLayout when it's not a template or the expandedTemplate is pending.
-- 
cgit v1.2.3-70-g09d2


From 5bc848bde4f37ec3dc812b22d81ded16f2a86f93 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 24 Jul 2019 00:35:29 -0400
Subject: fixed reordering tree view items.  restored double-click to view
 detail view.

---
 src/client/views/collections/CollectionTreeView.tsx | 2 +-
 src/client/views/nodes/DocumentView.tsx             | 1 +
 src/new_fields/Doc.ts                               | 8 ++++++++
 3 files changed, 10 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 2ff9e43fe..fe636942c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -448,7 +448,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 dataDoc={dataDoc}
                 containingCollection={containingCollection}
                 treeViewId={treeViewId}
-                key={child[Id] + "child " + i}
+                key={child[Id]}
                 indentDocument={indent}
                 renderDepth={renderDepth}
                 deleteDoc={remove}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 09a1b49fe..8d7b3d835 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -295,6 +295,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (this._doubleTap && this.props.renderDepth) {
             let fullScreenAlias = Doc.MakeAlias(this.props.Document);
             fullScreenAlias.templates = new List<string>();
+            Doc.UseDetailLayout(fullScreenAlias);
             this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab");
             SelectionManager.DeselectAll();
             this.props.Document.libraryBrush = undefined;
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 2a697e621..a1241aac3 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -463,4 +463,12 @@ export namespace Doc {
         d.layout !== miniLayout ? miniLayout && (d.layout = d.miniLayout) : detailLayout && (d.layout = detailLayout);
         if (d.layout === detailLayout) Doc.GetProto(d).nativeWidth = Doc.GetProto(d).nativeHeight = undefined;
     }
+    export async function UseDetailLayout(d: Doc) {
+        let miniLayout = await PromiseValue(d.miniLayout);
+        let detailLayout = await PromiseValue(d.detailedLayout);
+        if (miniLayout && d.layout === miniLayout && detailLayout) {
+            d.layout = detailLayout;
+            Doc.GetProto(d).nativeWidth = Doc.GetProto(d).nativeHeight = undefined;
+        }
+    }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From db560a8c43f77b9342e55a48dd96f695813b32ef Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Thu, 25 Jul 2019 12:53:09 -0400
Subject: oof a lot of stuff here

---
 .../views/collections/CollectionSchemaView.scss    |   1 +
 .../views/collections/CollectionSchemaView.tsx     |   2 +
 .../views/collections/CollectionStackingView.tsx   |   5 +-
 .../views/collections/CollectionTreeView.scss      |  27 ++-
 .../views/collections/CollectionTreeView.tsx       |   2 +
 src/client/views/collections/CollectionView.tsx    |  18 +-
 .../views/collections/CollectionViewChromes.scss   | 258 +++++++++++----------
 .../views/collections/CollectionViewChromes.tsx    | 137 ++++++-----
 .../authentication/models/current_user_utils.ts    |   4 +
 9 files changed, 251 insertions(+), 203 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 186e006f3..1e6d1fe99 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -12,6 +12,7 @@
     width: 100%;
     height: 100%;
     overflow: hidden;
+    transition: top 0.5s;
 
     .collectionSchemaView-cellContents {
         height: $MAX_ROW_HEIGHT;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 2cf50e551..bdcedea10 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -69,6 +69,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable _newKeyName: string = "";
     @observable previewScript: string = "";
 
+    @computed get chromeCollapsed() { return this.props.chromeCollapsed; }
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
     @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); }
@@ -390,6 +391,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     render() {
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
+                style={{ top: this.chromeCollapsed ? 0 : "unset" }}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
                 {this.reactTable}
                 {this.dividerDragger}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 31ec80d76..b5c0fb3d6 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -21,8 +21,6 @@ import { List } from "../../../new_fields/List";
 import { EditableView } from "../EditableView";
 import { CollectionViewProps } from "./CollectionBaseView";
 
-let valuesCreated = 1;
-
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
     _masonryGridRef: HTMLDivElement | null = null;
@@ -33,7 +31,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     _columnStart: number = 0;
     @observable private cursor: CursorProperty = "grab";
     get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); }
-    get chromeCollapsed() { return this.props.chromeCollapsed; }
+    @computed get chromeCollapsed() { return this.props.chromeCollapsed; }
     @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); }
@@ -84,7 +82,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             () => StrCast(this.props.Document.sectionFilter),
             () => {
                 this.props.Document.sectionHeaders = new List();
-                valuesCreated = 1;
             }
         )
     }
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 5205f4313..db3652ff6 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -31,6 +31,7 @@
         margin-top: 4px;
         transform: scale(1.3, 1.3);
     }
+
     .editableView-container {
         font-weight: bold;
     }
@@ -43,18 +44,20 @@
         display: inline;
     }
 
-    .editableView-input, .editableView-container-editing {
+    .editableView-input,
+    .editableView-container-editing {
         display: block;
         text-overflow: ellipsis;
         font-size: 24px;
         white-space: nowrap;
     }
 }
+
 .collectionTreeView-keyHeader {
     font-style: italic;
     font-size: 8pt;
     margin-left: 3px;
-    display:none;
+    display: none;
     background: lightgray;
 }
 
@@ -72,28 +75,31 @@
     // width:100%;//width: max-content;
 
 }
+
 .treeViewItem-openRight {
     display: none;
 }
 
 .treeViewItem-border {
-    display:inherit;
+    display: inherit;
     border-left: dashed 1px #00000042;
 }
 
 .treeViewItem-header:hover {
     .collectionTreeView-keyHeader {
-        display:inherit;
+        display: inherit;
     }
+
     .treeViewItem-openRight {
         display: inline-block;
-        height:13px;
-        margin-top:2px;
+        height: 13px;
+        margin-top: 2px;
         margin-left: 5px;
+
         // display: inline;
         svg {
-            display:block;
-            padding:0px;
+            display: block;
+            padding: 0px;
             margin: 0px;
         }
     }
@@ -101,14 +107,17 @@
 
 .treeViewItem-header {
     border: transparent 1px solid;
-    display:flex;
+    display: flex;
 }
+
 .treeViewItem-header-above {
     border-top: black 1px solid;
 }
+
 .treeViewItem-header-below {
     border-bottom: black 1px solid;
 }
+
 .treeViewItem-header-inside {
     border: black 1px solid;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index d05cc375e..cbf32c667 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -456,6 +456,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
     private treedropDisposer?: DragManager.DragDropDisposer;
     private _mainEle?: HTMLDivElement;
 
+    @computed get chromeCollapsed() { return this.props.chromeCollapsed; }
+
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
         this.treedropDisposer && this.treedropDisposer();
         if (this._mainEle = ele) {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e2f652908..1c6dd661d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -18,7 +18,7 @@ import { CollectionTreeView } from "./CollectionTreeView";
 import { StrCast, PromiseValue } from '../../../new_fields/Types';
 import { DocumentType } from '../../documents/Documents';
 import { CollectionStackingViewChrome, CollectionViewBaseChrome } from './CollectionViewChromes';
-import { observable } from 'mobx';
+import { observable, action, runInAction } from 'mobx';
 export const COLLECTION_BORDER_WIDTH = 2;
 
 library.add(faTh);
@@ -37,11 +37,20 @@ export class CollectionView extends React.Component<FieldViewProps> {
 
     public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); }
 
+    componentDidMount = () => {
+        // chrome status is one of disabled, collapsed, or visible. this determines initial state from document
+        let chromeStatus = this.props.Document.chromeStatus;
+        if (chromeStatus && (chromeStatus === "disabled" || chromeStatus === "collapsed")) {
+            runInAction(() => this._collapsed = true);
+        }
+    }
+
     private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
         switch (this.isAnnotationOverlay ? CollectionViewType.Freeform : type) {
             case CollectionViewType.Schema: return (<CollectionSchemaView chromeCollapsed={this._collapsed} key="collview" {...props} CollectionView={this} />);
-            case CollectionViewType.Docking: return (<CollectionDockingView chromeCollapsed={this._collapsed} key="collview" {...props} CollectionView={this} />);
+            // currently cant think of a reason for collection docking view to have a chrome. mind may change if we ever have nested docking views -syip
+            case CollectionViewType.Docking: return (<CollectionDockingView chromeCollapsed={true} key="collview" {...props} CollectionView={this} />);
             case CollectionViewType.Tree: return (<CollectionTreeView chromeCollapsed={this._collapsed} key="collview" {...props} CollectionView={this} />);
             case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (<CollectionStackingView chromeCollapsed={this._collapsed} key="collview" {...props} CollectionView={this} />); }
             case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (<CollectionStackingView chromeCollapsed={this._collapsed} key="collview" {...props} CollectionView={this} />); }
@@ -52,12 +61,15 @@ export class CollectionView extends React.Component<FieldViewProps> {
         return (null);
     }
 
+    @action
     private collapse = (value: boolean) => {
         this._collapsed = value;
+        this.props.Document.chromeStatus = value ? "collapsed" : "visible";
     }
 
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
-        if (this.isAnnotationOverlay || this.props.Document === CurrentUserUtils.UserDocument.sidebar) {
+        // currently cant think of a reason for collection docking view to have a chrome. mind may change if we ever have nested docking views -syip
+        if (this.isAnnotationOverlay || this.props.Document.chromeStatus === "disabled" || type === CollectionViewType.Docking) {
             return [(null), this.SubViewHelper(type, renderProps)];
         }
         else {
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index d37228bde..0faca0607 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -1,167 +1,171 @@
 @import "../globalCssVariables";
 @import '~js-datepicker/dist/datepicker.min.css';
 
-.collectionViewChrome {
-    display: grid;
-    grid-template-columns: 1fr auto;
-    padding-bottom: 10px;
-    border-bottom: .5px solid lightgrey;
-    margin: 10px;
+.collectionViewChrome-cont {
     position: relative;
     z-index: 9001;
     transition: top .5s;
+    background: rgb(238, 238, 238);
+    padding: 10px;
 
-    .collectionViewBaseChrome {
-        display: flex;
+    .collectionViewChrome {
+        display: grid;
+        grid-template-columns: 1fr auto;
+        padding-bottom: 10px;
+        border-bottom: .5px solid lightgrey;
 
-        .collectionViewBaseChrome-viewPicker {
-            font-size: 75%;
-            text-transform: uppercase;
-            letter-spacing: 2px;
-            background: rgb(238, 238, 238);
-            color: grey;
-            outline-color: black;
-            border: none;
-            padding: 12px 10px 11px 10px;
-            margin-left: 50px;
-        }
-
-        .collectionViewBaseChrome-viewPicker:active {
-            outline-color: black;
-        }
-
-        .collectionViewBaseChrome-collapse {
-            transition: all .5s;
-            position: absolute;
-            width: 40px;
-        }
-
-        .collectionViewBaseChrome-viewSpecs {
-            margin-left: 10px;
-            display: grid;
+        .collectionViewBaseChrome {
+            display: flex;
 
-            .collectionViewBaseChrome-viewSpecsInput {
-                padding: 12px 10px 11px 10px;
-                border: 0px;
-                color: grey;
-                text-align: center;
+            .collectionViewBaseChrome-viewPicker {
+                font-size: 75%;
                 text-transform: uppercase;
                 letter-spacing: 2px;
-                outline-color: black;
-                font-size: 75%;
                 background: rgb(238, 238, 238);
-                height: 100%;
-                width: 150px;
+                color: grey;
+                outline-color: black;
+                border: none;
+                padding: 12px 10px 11px 10px;
+                margin-left: 50px;
+            }
+
+            .collectionViewBaseChrome-viewPicker:active {
+                outline-color: black;
             }
 
-            .collectionViewBaseChrome-viewSpecsMenu {
-                overflow: hidden;
-                transition: height .5s, display .5s;
+            .collectionViewBaseChrome-collapse {
+                transition: all .5s;
                 position: absolute;
-                top: 60px;
-                z-index: 100;
-                display: flex;
-                flex-direction: column;
-                background: rgb(238, 238, 238);
-                box-shadow: grey 2px 2px 4px;
+                width: 40px;
+            }
 
-                .qs-datepicker {
-                    left: unset;
-                    right: 0;
+            .collectionViewBaseChrome-viewSpecs {
+                margin-left: 10px;
+                display: grid;
+
+                .collectionViewBaseChrome-viewSpecsInput {
+                    padding: 12px 10px 11px 10px;
+                    border: 0px;
+                    color: grey;
+                    text-align: center;
+                    text-transform: uppercase;
+                    letter-spacing: 2px;
+                    outline-color: black;
+                    font-size: 75%;
+                    background: rgb(238, 238, 238);
+                    height: 100%;
+                    width: 150px;
                 }
 
-                .collectionViewBaseChrome-viewSpecsMenu-row {
-                    display: grid;
-                    grid-template-columns: 150px 200px 150px;
-                    margin-top: 10px;
-                    margin-right: 10px;
-
-                    .collectionViewBaseChrome-viewSpecsMenu-rowLeft,
-                    .collectionViewBaseChrome-viewSpecsMenu-rowMiddle,
-                    .collectionViewBaseChrome-viewSpecsMenu-rowRight {
-                        font-size: 75%;
-                        letter-spacing: 2px;
-                        color: grey;
-                        margin-left: 10px;
-                        padding: 5px;
-                        border: none;
-                        outline-color: black;
+                .collectionViewBaseChrome-viewSpecsMenu {
+                    overflow: hidden;
+                    transition: height .5s, display .5s;
+                    position: absolute;
+                    top: 60px;
+                    z-index: 100;
+                    display: flex;
+                    flex-direction: column;
+                    background: rgb(238, 238, 238);
+                    box-shadow: grey 2px 2px 4px;
+
+                    .qs-datepicker {
+                        left: unset;
+                        right: 0;
                     }
-                }
 
-                .collectionViewBaseChrome-viewSpecsMenu-lastRow {
-                    display: grid;
-                    grid-template-columns: 1fr 1fr;
-                    grid-gap: 10px;
-                    margin: 10px;
+                    .collectionViewBaseChrome-viewSpecsMenu-row {
+                        display: grid;
+                        grid-template-columns: 150px 200px 150px;
+                        margin-top: 10px;
+                        margin-right: 10px;
+
+                        .collectionViewBaseChrome-viewSpecsMenu-rowLeft,
+                        .collectionViewBaseChrome-viewSpecsMenu-rowMiddle,
+                        .collectionViewBaseChrome-viewSpecsMenu-rowRight {
+                            font-size: 75%;
+                            letter-spacing: 2px;
+                            color: grey;
+                            margin-left: 10px;
+                            padding: 5px;
+                            border: none;
+                            outline-color: black;
+                        }
+                    }
+
+                    .collectionViewBaseChrome-viewSpecsMenu-lastRow {
+                        display: grid;
+                        grid-template-columns: 1fr 1fr;
+                        grid-gap: 10px;
+                        margin: 10px;
+                    }
                 }
             }
         }
-    }
 
 
-    .collectionStackingViewChrome-cont {
-        display: flex;
-        justify-content: space-between;
-    }
+        .collectionStackingViewChrome-cont {
+            display: flex;
+            justify-content: space-between;
+        }
 
-    .collectionStackingViewChrome-sort {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
+        .collectionStackingViewChrome-sort {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
 
-        .collectionStackingViewChrome-sortIcon {
-            transition: transform .5s;
-            margin-left: 10px;
+            .collectionStackingViewChrome-sortIcon {
+                transition: transform .5s;
+                margin-left: 10px;
+            }
         }
-    }
-
-    button:hover {
-        transform: scale(1);
-    }
 
+        button:hover {
+            transform: scale(1);
+        }
 
-    .collectionStackingViewChrome-sectionFilter-cont {
-        justify-self: right;
-        display: flex;
-        font-size: 75%;
-        text-transform: uppercase;
-        letter-spacing: 2px;
 
-        .collectionStackingViewChrome-sectionFilter-label {
-            vertical-align: center;
-            padding: 10px;
-        }
+        .collectionStackingViewChrome-sectionFilter-cont {
+            justify-self: right;
+            display: flex;
+            font-size: 75%;
+            text-transform: uppercase;
+            letter-spacing: 2px;
 
-        .collectionStackingViewChrome-sectionFilter {
-            color: white;
-            width: 100px;
-            text-align: center;
-            background: rgb(238, 238, 238);
+            .collectionStackingViewChrome-sectionFilter-label {
+                vertical-align: center;
+                padding: 10px;
+            }
 
-            .editable-view-input,
-            input,
-            .editableView-container-editing-oneLine,
-            .editableView-container-editing {
-                padding: 12px 10px 11px 10px;
-                border: 0px;
-                color: grey;
+            .collectionStackingViewChrome-sectionFilter {
+                color: white;
+                width: 100px;
                 text-align: center;
-                text-transform: uppercase;
-                letter-spacing: 2px;
-                outline-color: black;
-                height: 100%;
-            }
+                background: rgb(238, 238, 238);
 
-            .react-autosuggest__container {
-                margin: 0;
-                color: grey;
-                padding: 0px;
+                .editable-view-input,
+                input,
+                .editableView-container-editing-oneLine,
+                .editableView-container-editing {
+                    padding: 12px 10px 11px 10px;
+                    border: 0px;
+                    color: grey;
+                    text-align: center;
+                    text-transform: uppercase;
+                    letter-spacing: 2px;
+                    outline-color: black;
+                    height: 100%;
+                }
+
+                .react-autosuggest__container {
+                    margin: 0;
+                    color: grey;
+                    padding: 0px;
+                }
             }
         }
-    }
 
-    .collectionStackingViewChrome-sectionFilter:hover {
-        cursor: text;
+        .collectionStackingViewChrome-sectionFilter:hover {
+            cursor: text;
+        }
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 24d13d5cb..4129781f7 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -47,6 +47,20 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
         runInAction(() => {
             this._keyRestrictions.push([<KeyRestrictionRow key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]);
             this._keyRestrictions.push([<KeyRestrictionRow key={Utils.GenerateGuid()} contains={false} script={(value: string) => runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]);
+
+            // chrome status is one of disabled, collapsed, or visible. this determines initial state from document
+            let chromeStatus = this.props.CollectionView.props.Document.chromeStatus;
+            if (chromeStatus) {
+                if (chromeStatus === "disabled") {
+                    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);
+                    }
+                }
+            }
         });
     }
 
@@ -130,11 +144,12 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     @action
     toggleCollapse = () => {
         this._collapsed = !this._collapsed;
-        this.props.collapse(this._collapsed);
+        if (this.props.collapse) {
+            this.props.collapse(this._collapsed);
+        }
     }
 
     subChrome = () => {
-
         switch (this.props.type) {
             case CollectionViewType.Stacking: return (
                 <CollectionStackingViewChrome
@@ -148,71 +163,73 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
 
     render() {
         return (
-            <div className="collectionViewChrome" style={{ top: this._collapsed ? -100 : 0 }}>
-                <div className="collectionViewBaseChrome">
-                    <button className="collectionViewBaseChrome-collapse"
-                        style={{ top: this._collapsed ? 80 : 0, transform: `rotate(${this._collapsed ? 180 : 0}deg)` }}
-                        title="Collapse collection chrome" onClick={this.toggleCollapse}>
-                        <FontAwesomeIcon icon="caret-up" size="2x" />
-                    </button>
-                    <select
-                        className="collectionViewBaseChrome-viewPicker"
-                        onPointerDown={stopPropagation}
-                        onChange={this.viewChanged}
-                        value={NumCast(this.props.CollectionView.props.Document.viewType)}>
-                        <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="1">Freeform View</option>
-                        <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="2">Schema View</option>
-                        <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="4">Tree View</option>
-                        <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">
-                        <input className="collectionViewBaseChrome-viewSpecsInput"
-                            placeholder="Filter Documents"
-                            value={this.filterValue ? this.filterValue.script.originalScript : ""}
-                            onPointerDown={this.openViewSpecs} />
-                        <div className="collectionViewBaseChrome-viewSpecsMenu"
-                            onPointerDown={this.openViewSpecs}
-                            style={{
-                                height: this._viewSpecsOpen ? "fit-content" : "0px",
-                                overflow: this._viewSpecsOpen ? "initial" : "hidden"
-                            }}>
-                            {this._keyRestrictions.map(i => i[0])}
-                            <div className="collectionViewBaseChrome-viewSpecsMenu-row">
-                                <div className="collectionViewBaseChrome-viewSpecsMenu-rowLeft">
-                                    CREATED WITHIN:
-                            </div>
-                                <select className="collectionViewBaseChrome-viewSpecsMenu-rowMiddle"
-                                    style={{ textTransform: "uppercase", textAlign: "center" }}
-                                    value={this._dateWithinValue}
-                                    onChange={(e) => runInAction(() => this._dateWithinValue = e.target.value)}>
-                                    <option value="1d">1 day of</option>
-                                    <option value="3d">3 days of</option>
-                                    <option value="1w">1 week of</option>
-                                    <option value="2w">2 weeks of</option>
-                                    <option value="1m">1 month of</option>
-                                    <option value="2m">2 months of</option>
-                                    <option value="6m">6 months of</option>
-                                    <option value="1y">1 year of</option>
-                                </select>
-                                <input className="collectionViewBaseChrome-viewSpecsMenu-rowRight"
-                                    id={this._datePickerElGuid}
-                                    value={this._dateValue.toLocaleDateString()}
-                                    onPointerDown={this.openDatePicker}
-                                    placeholder="Value" />
+            <div className="collectionViewChrome-cont" style={{ top: this._collapsed ? -100 : 0 }}>
+                <div className="collectionViewChrome">
+                    <div className="collectionViewBaseChrome">
+                        <button className="collectionViewBaseChrome-collapse"
+                            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>
+                        <select
+                            className="collectionViewBaseChrome-viewPicker"
+                            onPointerDown={stopPropagation}
+                            onChange={this.viewChanged}
+                            value={NumCast(this.props.CollectionView.props.Document.viewType)}>
+                            <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="1">Freeform View</option>
+                            <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="2">Schema View</option>
+                            <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value="4">Tree View</option>
+                            <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">
+                            <input className="collectionViewBaseChrome-viewSpecsInput"
+                                placeholder="Filter Documents"
+                                value={this.filterValue ? this.filterValue.script.originalScript : ""}
+                                onPointerDown={this.openViewSpecs} />
+                            <div className="collectionViewBaseChrome-viewSpecsMenu"
+                                onPointerDown={this.openViewSpecs}
+                                style={{
+                                    height: this._viewSpecsOpen ? "fit-content" : "0px",
+                                    overflow: this._viewSpecsOpen ? "initial" : "hidden"
+                                }}>
+                                {this._keyRestrictions.map(i => i[0])}
+                                <div className="collectionViewBaseChrome-viewSpecsMenu-row">
+                                    <div className="collectionViewBaseChrome-viewSpecsMenu-rowLeft">
+                                        CREATED WITHIN:
                             </div>
-                            <div className="collectionViewBaseChrome-viewSpecsMenu-lastRow">
-                                <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.addKeyRestriction}>
-                                    ADD KEY RESTRICTION
+                                    <select className="collectionViewBaseChrome-viewSpecsMenu-rowMiddle"
+                                        style={{ textTransform: "uppercase", textAlign: "center" }}
+                                        value={this._dateWithinValue}
+                                        onChange={(e) => runInAction(() => this._dateWithinValue = e.target.value)}>
+                                        <option value="1d">1 day of</option>
+                                        <option value="3d">3 days of</option>
+                                        <option value="1w">1 week of</option>
+                                        <option value="2w">2 weeks of</option>
+                                        <option value="1m">1 month of</option>
+                                        <option value="2m">2 months of</option>
+                                        <option value="6m">6 months of</option>
+                                        <option value="1y">1 year of</option>
+                                    </select>
+                                    <input className="collectionViewBaseChrome-viewSpecsMenu-rowRight"
+                                        id={this._datePickerElGuid}
+                                        value={this._dateValue.toLocaleDateString()}
+                                        onPointerDown={this.openDatePicker}
+                                        placeholder="Value" />
+                                </div>
+                                <div className="collectionViewBaseChrome-viewSpecsMenu-lastRow">
+                                    <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.addKeyRestriction}>
+                                        ADD KEY RESTRICTION
                             </button>
-                                <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.applyFilter}>
-                                    APPLY FILTER
+                                    <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.applyFilter}>
+                                        APPLY FILTER
                             </button>
+                                </div>
                             </div>
                         </div>
                     </div>
+                    {this.subChrome()}
                 </div>
-                {this.subChrome()}
             </div>
         )
     }
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 1c52a3f11..41eb1aa0c 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -50,6 +50,7 @@ export class CurrentUserUtils {
         if (doc.workspaces === undefined) {
             const workspaces = Docs.Create.TreeDocument([], { title: "Workspaces", height: 100 });
             workspaces.excludeFromLibrary = true;
+            workspaces.chromeStatus = "disabled";
             workspaces.workspaceLibrary = true;
             workspaces.boxShadow = "0 0";
             doc.workspaces = workspaces;
@@ -57,6 +58,7 @@ export class CurrentUserUtils {
         if (doc.recentlyClosed === undefined) {
             const recentlyClosed = Docs.Create.TreeDocument([], { title: "Recently Closed", height: 75 });
             recentlyClosed.excludeFromLibrary = true;
+            recentlyClosed.chromeStatus = "disabled";
             recentlyClosed.boxShadow = "0 0";
             doc.recentlyClosed = recentlyClosed;
         }
@@ -65,11 +67,13 @@ export class CurrentUserUtils {
             sidebar.excludeFromLibrary = true;
             sidebar.gridGap = 5;
             sidebar.xMargin = 5;
+            sidebar.chromeStatus = "disabled";
             sidebar.yMargin = 5;
             Doc.GetProto(sidebar).backgroundColor = "#aca3a6";
             sidebar.boxShadow = "1 1 3";
             doc.sidebar = sidebar;
         }
+        doc.chromeStatus = "disabled";
         StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library");
 
     }
-- 
cgit v1.2.3-70-g09d2


From eceff76609deaa3e7a60c686b62cb4fd15e9699b Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 25 Jul 2019 15:00:16 -0400
Subject: several fixes and added basic fields to treeview display

---
 .vscode/launch.json                                |   4 -
 .../views/collections/CollectionTreeView.tsx       | 106 +++++++++++++--------
 src/client/views/nodes/DocumentView.tsx            |   4 +-
 src/client/views/nodes/ImageBox.tsx                |   2 +-
 src/client/views/search/SearchItem.tsx             |   6 +-
 src/new_fields/Doc.ts                              |   2 +-
 6 files changed, 71 insertions(+), 53 deletions(-)

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

diff --git a/.vscode/launch.json b/.vscode/launch.json
index fd67a7647..822a06024 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -7,10 +7,6 @@
         {
             "type": "chrome",
             "request": "launch",
-            "runtimeArgs": [
-                "--enable-logging",
-                "--v=1"
-            ],
             "name": "Launch Chrome against localhost",
             "sourceMaps": true,
             "breakOnLoad": true,
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 006de0c70..ff3221ada 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -3,7 +3,7 @@ import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaret
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCast, HeightSym, WidthSym, Opt } from '../../../new_fields/Doc';
+import { Doc, DocListCast, HeightSym, WidthSym, Opt, Field } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
 import { List } from '../../../new_fields/List';
 import { Document, listSpec } from '../../../new_fields/Schema';
@@ -26,6 +26,8 @@ import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import React = require("react");
 import { LinkManager } from '../../util/LinkManager';
+import { ComputedField } from '../../../new_fields/ScriptField';
+import { KeyValueBox } from '../nodes/KeyValueBox';
 
 
 export interface TreeViewProps {
@@ -68,8 +70,7 @@ class TreeView extends React.Component<TreeViewProps> {
     private _header?: React.RefObject<HTMLDivElement> = React.createRef();
     private _treedropDisposer?: DragManager.DragDropDisposer;
     private _dref = React.createRef<HTMLDivElement>();
-    @observable __chosenKey: string = "";
-    @computed get _chosenKey() { return this.__chosenKey ? this.__chosenKey : this.fieldKey; }
+    @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, "data"); }
     @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); }
     @observable _collapsed: boolean = true;
 
@@ -125,12 +126,12 @@ class TreeView extends React.Component<TreeViewProps> {
         }
     }
     onPointerLeave = (e: React.PointerEvent): void => {
-        this.props.document.libraryBrush = undefined;
+        this.props.document.libraryBrush = false;
         this._header!.current!.className = "treeViewItem-header";
         document.removeEventListener("pointermove", this.onDragMove, true);
     }
     onDragMove = (e: PointerEvent): void => {
-        this.props.document.libraryBrush = undefined;
+        this.props.document.libraryBrush = false;
         let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
         let rect = this._header!.current!.getBoundingClientRect();
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
@@ -191,25 +192,6 @@ class TreeView extends React.Component<TreeViewProps> {
         OnTab={() => this.props.indentDocument && this.props.indentDocument()}
     />)
 
-    @computed get keyList() {
-        let target = this.props.document;
-        let keys = Array.from(Object.keys(target));
-        if (target.proto instanceof Doc) {
-            keys.push(...Array.from(Object.keys(target.proto)));
-        }
-        let keyList: string[] = keys.reduce((l, key) => {
-            let listspec = DocListCast(target[key]);
-            if (listspec && listspec.length) return [...l, key];
-            return l;
-        }, [] as string[]);
-        keys.map(key => Cast(target[key], Doc) instanceof Doc && keyList.push(key));
-        if (LinkManager.Instance.getAllRelatedLinks(this.props.document).length > 0) keyList.push("links");
-        if (keyList.indexOf(this.fieldKey) !== -1) {
-            keyList.splice(keyList.indexOf(this.fieldKey), 1);
-        }
-        keyList.splice(0, 0, this.fieldKey);
-        return keyList.filter((item, index) => keyList.indexOf(item) >= index);
-    }
     /**
      * Renders the EditableView title element for placement into the tree.
      */
@@ -218,13 +200,9 @@ class TreeView extends React.Component<TreeViewProps> {
         let onItemDown = SetupDrag(reference, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId, true);
 
         let headerElements = (
-            <span className="collectionTreeView-keyHeader" key={this._chosenKey + "chosen"}
-                onPointerDown={action(() => {
-                    let ind = this.keyList.indexOf(this._chosenKey);
-                    ind = (ind + 1) % this.keyList.length;
-                    this.__chosenKey = this.keyList[ind];
-                })} >
-                {this._chosenKey}
+            <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView}
+                onPointerDown={action(() => this.props.document.treeViewExpandedView = this.treeViewExpandedView === "data" ? "fields" : this.treeViewExpandedView === "fields" && this.props.document.layout ? "layout" : "data")}>
+                {this.treeViewExpandedView}
             </span>);
         let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document[this.fieldKey], listSpec(Doc), []) : [];
         let openRight = dataDocs && dataDocs.indexOf(this.dataDoc) !== -1 ? (null) : (
@@ -249,7 +227,6 @@ class TreeView extends React.Component<TreeViewProps> {
 
     onWorkspaceContextMenu = (e: React.MouseEvent): void => {
         if (!e.isPropagationStopped()) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
-            ContextMenu.Instance.addItem({ description: (BoolCast(this.props.document.embed) ? "Collapse" : "Expand") + " inline", event: () => this.props.document.embed = !BoolCast(this.props.document.embed), icon: "expand" });
             if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) {
                 ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "inTab"), icon: "folder" });
                 ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "onRight"), icon: "caret-square-right" });
@@ -311,8 +288,8 @@ class TreeView extends React.Component<TreeViewProps> {
 
     renderLinks = () => {
         let ele: JSX.Element[] = [];
-        let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
-        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before);
+        let remDoc = (doc: Doc) => this.remove(doc, this.fieldKey);
+        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.props.document, this.fieldKey, doc, addBefore, before);
         let groups = LinkManager.Instance.getRelatedGroupedLinks(this.props.document);
         groups.forEach((groupLinkDocs, groupType) => {
             // let destLinks = groupLinkDocs.map(d => LinkManager.Instance.getOppositeAnchor(d, this.props.document));
@@ -358,20 +335,65 @@ class TreeView extends React.Component<TreeViewProps> {
 
     noOverlays = (doc: Doc) => ({ title: "", caption: "" });
 
+    expandedField = (doc?: Doc) => {
+        if (!doc) return <div />;
+        let realDoc = doc;
+
+        let ids: { [key: string]: string } = {};
+        Object.keys(doc).forEach(key => {
+            if (!(key in ids) && realDoc[key] !== ComputedField.undefined) {
+                ids[key] = key;
+            }
+        });
+
+        let rows: JSX.Element[] = [];
+        for (let key of Object.keys(ids).sort()) {
+            let contents = realDoc[key] ? realDoc[key] : undefined;
+            let contentElement: JSX.Element[] | JSX.Element = [];
+
+            if (contents instanceof Doc || Cast(contents, listSpec(Doc))) {
+                let docList = contents;
+                let remDoc = (doc: Doc) => this.remove(doc, key);
+                let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before);
+                contentElement = key === "links" ? this.renderLinks() :
+                    TreeView.GetChildElements(docList instanceof Doc ? [docList as Doc] : DocListCast(docList), this.props.treeViewId, realDoc, undefined, key, addDoc, remDoc, this.move,
+                        this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth);
+            } else {
+                contentElement = <EditableView
+                    key="editableView"
+                    contents={contents ? contents.toString() : "null"}
+                    height={13}
+                    fontSize={12}
+                    GetValue={() => Field.toKeyValueString(realDoc, key)}
+                    SetValue={(value: string) => KeyValueBox.SetField(realDoc, key, value)} />;
+            }
+            rows.push(<div style={{ display: "flex" }} key={key}>
+                <span style={{ fontWeight: "bold" }}>{key + ":"}</span>
+                &nbsp;
+                {contentElement}
+            </div>);
+        }
+        return rows;
+    }
+
     render() {
         let contentElement: (JSX.Element | null) = null;
-        let docList = Cast(this.dataDoc[this._chosenKey], listSpec(Doc));
-        let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
-        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this._chosenKey, doc, addBefore, before);
+        let docList = Cast(this.dataDoc[this.fieldKey], listSpec(Doc));
+        let remDoc = (doc: Doc) => this.remove(doc, this.fieldKey);
+        let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc, addBefore, before);
 
         if (!this._collapsed) {
-            if (!this.props.document.embed) {
-                let doc = Cast(this.props.document[this._chosenKey], Doc);
-                contentElement = <ul key={this._chosenKey + "more"}>
-                    {this._chosenKey === "links" ? this.renderLinks() :
-                        TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.resolvedDataDoc, this._chosenKey, addDoc, remDoc, this.move,
+            if (this.treeViewExpandedView === "data") {
+                let doc = Cast(this.props.document[this.fieldKey], Doc);
+                contentElement = <ul key={this.fieldKey + "more"}>
+                    {this.fieldKey === "links" ? this.renderLinks() :
+                        TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, this.props.document, this.resolvedDataDoc, this.fieldKey, addDoc, remDoc, this.move,
                             this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth)}
                 </ul >;
+            } else if (this.treeViewExpandedView === "fields") {
+                contentElement = <ul><div ref={this._dref} style={{ display: "inline-block" }} key={this.props.document[Id] + this.props.document.title}>
+                    {this.expandedField(this.dataDoc)}
+                </div></ul>;
             } else {
                 let layoutDoc = this.props.document;
                 contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id] + this.props.document.title}>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b39c77adb..b5e64ed19 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -300,7 +300,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             Doc.UseDetailLayout(fullScreenAlias);
             this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab");
             SelectionManager.DeselectAll();
-            this.props.Document.libraryBrush = undefined;
+            this.props.Document.libraryBrush = false;
         }
         else if (CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
             (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
@@ -612,7 +612,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; };
-    onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = undefined; };
+    onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; };
 
     isSelected = () => SelectionManager.IsSelected(this);
     @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); };
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 3d77696fe..14208ce17 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -175,7 +175,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
                 const url = Utils.prepend(files[0]);
                 // upload to server with known URL 
                 let audioDoc = Docs.Create.AudioDocument(url, { title: "audio test", x: NumCast(self.props.Document.x), y: NumCast(self.props.Document.y), width: 200, height: 32 });
-                audioDoc.embed = true;
+                audioDoc.treeViewExpandedView = "layout";
                 let audioAnnos = Cast(self.extensionDoc.audioAnnotations, listSpec(Doc));
                 if (audioAnnos === undefined) {
                     self.extensionDoc.audioAnnotations = new List([audioDoc]);
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index a995140e2..5c2ced2eb 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -205,13 +205,13 @@ export class SearchItem extends React.Component<SearchItemProps> {
 
                 let doc1 = Cast(this.props.doc.anchor1, Doc, null);
                 let doc2 = Cast(this.props.doc.anchor2, Doc, null);
-                doc1 && (doc1.libraryBrush = undefined);
-                doc2 && (doc2.libraryBrush = undefined);
+                doc1 && (doc1.libraryBrush = false);
+                doc2 && (doc2.libraryBrush = false);
             }
         } else {
             let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc);
             docViews.forEach(element => {
-                element.props.Document.libraryBrush = undefined;
+                element.props.Document.libraryBrush = false;
             });
         }
     }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 64b4acb7b..c37c0fd22 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -380,7 +380,7 @@ export namespace Doc {
         }
         if (expandedTemplateLayout === undefined) {
             setTimeout(() =>
-                dataDoc[expandedLayoutFieldKey] = Doc.MakeDelegate(templateLayoutDoc, undefined, templateLayoutDoc.title + ".layout"), 0);
+                dataDoc[expandedLayoutFieldKey] = Doc.MakeDelegate(templateLayoutDoc, undefined, "["+templateLayoutDoc.title + "]"), 0);
         }
         return templateLayoutDoc; // use the templateLayout when it's not a template or the expandedTemplate is pending.
     }
-- 
cgit v1.2.3-70-g09d2

