From 6c7dc0f939635982ae619eb5831ff45063d7021e Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Wed, 17 Jul 2019 14:08:24 -0400
Subject: can add columns and delete columns through column header

---
 .../views/collections/CollectionSchemaView.tsx     | 286 +++++++++++++--------
 1 file changed, 181 insertions(+), 105 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f72b1aa07..8ddf26be2 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -4,10 +4,10 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
-import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
+import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer } from "react-table";
 import "react-table/react-table.css";
 import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils";
-import { Doc, DocListCast, DocListCastAsync, Field } from "../../../new_fields/Doc";
+import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
@@ -31,12 +31,28 @@ 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 } from "./CollectionSchemaCells";
 
 
 library.add(faCog);
 library.add(faPlus);
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
 
+export enum ColumnType {
+    Any,
+    Number,
+    String,
+    Boolean,
+    Doc,
+    Checkbox
+}
+// this map should be used for keys that should have a const type of value
+const columnTypes: Map<string, ColumnType> = new Map([
+    ["x", ColumnType.Number], ["y", ColumnType.Number], ["width", ColumnType.Number], ["height", ColumnType.Number],
+    ["nativeWidth", ColumnType.Number], ["nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean],
+    ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number]
+]);
 
 @observer
 class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> {
@@ -66,21 +82,72 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable _keys: string[] = [];
     @observable _newKeyName: string = "";
     @observable previewScript: string = "";
+    @observable _headerIsEditing: boolean = false;
 
     @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(); }
     @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); }
+    set columns(columns: string[]) { this.props.Document.schemaColumns = new List<string>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns() {
-        return this.columns.map(col => {
-            const ref = React.createRef<HTMLParagraphElement>();
+        let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
+
+        let cols = this.columns.map(col => {
             return {
-                Header: <p ref={ref} onPointerDown={SetupDrag(ref, () => this.onHeaderDrag(col), undefined, "copy")}>{col}</p>,
+                Header: <CollectionSchemaHeader 
+                    keyValue={col}
+                    possibleKeys={possibleKeys}
+                    existingKeys={this.columns}
+                    keyType={this.getColumnType(col)}
+                    typeConst={false}
+                    onSelect={this.changeColumns}
+                    setIsEditing={this.setHeaderIsEditing}
+                    deleteColumn={this.deleteColumn}
+                    setColumnType={this.setColumnType}
+                />,
                 accessor: (doc: Doc) => doc ? doc[col] : 0,
-                id: col
+                id: col,
+                Cell: (rowProps: CellInfo) => {
+                    let row = rowProps.index;
+                    let column = this.columns.indexOf(rowProps.column.id!);
+                    // let isFocused = focusedRow === row && focusedCol === column;
+                    let isFocused = false;
+
+                    let props: CellProps = {
+                        row: row,
+                        col: column,
+                        rowProps: rowProps,
+                        isFocused: isFocused,
+                        changeFocusedCellByDirection: action(emptyFunction),//this.changeFocusedCellByDirection,
+                        changeFocusedCellByIndex: action(emptyFunction), //this.changeFocusedCellByIndex,
+                        CollectionView: this.props.CollectionView,
+                        ContainingCollection: this.props.ContainingCollectionView,
+                        Document: this.props.Document,
+                        fieldKey: this.props.fieldKey,
+                        renderDepth: this.props.renderDepth, addDocTab: this.props.addDocTab,
+                        moveDocument: this.props.moveDocument,
+                        setIsEditing: action(emptyFunction), //this.setCellIsEditing,
+                        isEditable: true //isEditable
+                    };
+                    return <CollectionSchemaCell {...props}/>
+                }
             };
+        }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult<Field>, id: string, Cell: (rowProps: CellInfo) => JSX.Element}[];
+
+        cols.push({
+            Header: <CollectionSchemaAddColumnHeader
+                possibleKeys={possibleKeys}
+                existingKeys={this.columns}
+                onSelect={this.changeColumns}
+                setIsEditing={this.setHeaderIsEditing}
+            />,
+            accessor: (doc: Doc) => 0,
+            id: "add",
+            Cell: (rowProps: CellInfo) => <></>,
         });
+
+        return cols;
     }
 
     onHeaderDrag = (columnName: string) => {
@@ -97,72 +164,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return this.props.Document;
     }
 
-    renderCell = (rowProps: CellInfo) => {
-        let props: FieldViewProps = {
-            Document: rowProps.original,
-            DataDoc: rowProps.original,
-            fieldKey: rowProps.column.id as string,
-            fieldExt: "",
-            ContainingCollectionView: this.props.CollectionView,
-            isSelected: returnFalse,
-            select: emptyFunction,
-            renderDepth: this.props.renderDepth + 1,
-            selectOnLoad: false,
-            ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
-            active: returnFalse,
-            whenActiveChanged: emptyFunction,
-            PanelHeight: returnZero,
-            PanelWidth: returnZero,
-            addDocTab: this.props.addDocTab,
-        };
-        let fieldContentView = <FieldView {...props} />;
-        let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = (e: React.PointerEvent) => {
-            (!this.props.CollectionView.props.isSelected() ? undefined :
-                SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
-        };
-        let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
-            const res = run({ this: doc });
-            if (!res.success) return false;
-            doc[props.fieldKey] = res.result;
-            return true;
-        };
-        return (
-            <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document[Id]} ref={reference}>
-                <EditableView
-                    display={"inline"}
-                    contents={fieldContentView}
-                    height={Number(MAX_ROW_HEIGHT)}
-                    GetValue={() => {
-                        let field = props.Document[props.fieldKey];
-                        if (Field.IsField(field)) {
-                            return Field.toScriptString(field);
-                        }
-                        return "";
-                    }}
-                    SetValue={(value: string) => {
-                        let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } });
-                        if (!script.compiled) {
-                            return false;
-                        }
-                        return applyToDoc(props.Document, script.run);
-                    }}
-                    OnFillDown={async (value: string) => {
-                        let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } });
-                        if (!script.compiled) {
-                            return;
-                        }
-                        const run = script.run;
-                        //TODO This should be able to be refactored to compile the script once
-                        const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-                        val && val.forEach(doc => applyToDoc(doc, run));
-                    }}>
-                </EditableView>
-            </div >
-        );
-    }
-
     private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
         const that = this;
         if (!rowInfo) {
@@ -189,6 +190,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         super.CreateDropTarget(ele);
     }
 
+    @action
+    setHeaderIsEditing = (isEditing: boolean) => {
+        this._headerIsEditing = isEditing;
+    }
+
     @action
     toggleKey = (key: string) => {
         let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
@@ -278,10 +284,60 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
 
     @action
-    newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        this._newKeyName = e.currentTarget.value;
+    deleteColumn = (key: string) => {
+        let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
+        if (list === undefined) {
+            this.props.Document.schemaColumns = list = new List<string>([]);
+        } else {
+            const index = list.indexOf(key);
+            if (index > -1) {
+                list.splice(index, 1);
+            }
+        }
+    }
+
+    @action
+    changeColumns = (oldKey: string, newKey: string, addNew: boolean) => {
+        let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
+        if (list === undefined) {
+            this.props.Document.schemaColumns = list = new List<string>([newKey]);
+        } else {
+            if (addNew) {
+                this.columns.push(newKey);
+            } else {
+                const index = list.indexOf(oldKey);
+                if (index > -1) {
+                    list[index] = newKey;
+                }
+            }
+        }
+    }
+
+    getColumnType = (key: string): ColumnType => {
+        if (columnTypes.get(key)) return columnTypes.get(key)!;
+        const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc));
+        if (!typesDoc) return ColumnType.Any;
+        return NumCast(typesDoc[key]);
+    }
+
+    setColumnType = (key: string, type: ColumnType): void => {
+        if (columnTypes.get(key)) return;
+        const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc));
+        if (!typesDoc) {
+            // let newTypesDoc = new Doc();
+            // newTypesDoc[key] = type;
+            // this.props.Document.schemaColumnTypes  = newTypesDoc;
+            return;
+        } else {
+            typesDoc[key] = type;
+        }
     }
 
+    // @action
+    // newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    //     this._newKeyName = e.currentTarget.value;
+    // }
+
     @computed
     get previewDocument(): Doc | undefined {
         const selected = this.childDocs.length > this._selectedIndex ? this.childDocs[this._selectedIndex] : undefined;
@@ -289,11 +345,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return pdc;
     }
 
-    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(
-        - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth)
+    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth);
 
 
-    get documentKeysCheckList() {
+    get documentKeys() {
         const docs = DocListCast(this.props.Document[this.props.fieldKey]);
         let keys: { [key: string]: boolean } = {};
         // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
@@ -305,39 +360,60 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false))));
 
         this.columns.forEach(key => keys[key] = true);
-        return Array.from(Object.keys(keys)).map(item =>
-            (<KeyToggle checked={keys[item]} key={item} keyName={item} toggle={this.toggleKey} />));
-    }
-
-    get tableOptionsPanel() {
-        return !this.props.active() ? (null) :
-            (<Flyout
-                anchorPoint={anchorPoints.RIGHT_TOP}
-                content={<div>
-                    <div id="schema-options-header"><h5><b>Options</b></h5></div>
-                    <div id="options-flyout-div">
-                        <h6 className="schema-options-subHeader">Preview Window</h6>
-                        <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />  Show Preview </div>
-                        <h6 className="schema-options-subHeader" >Displayed Columns</h6>
-                        <ul id="schema-col-checklist" >
-                            {this.documentKeysCheckList}
-                        </ul>
-                        <input value={this._newKeyName} onChange={this.newKeyChange} />
-                        <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
-                    </div>
-                </div>
-                }>
-                <button id="schemaOptionsMenuBtn" ><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
-            </Flyout>);
-    }
+        return Array.from(Object.keys(keys));
+    }
+
+    // get documentKeysCheckList() {
+    //     const docs = DocListCast(this.props.Document[this.props.fieldKey]);
+    //     let keys: { [key: string]: boolean } = {};
+    //     // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
+    //     //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
+    //     //  invalidated and re-rendered.   This workaround will inquire all of the document fields before the options button is clicked.
+    //     //  then by the time the options button is clicked, all of the fields should be in place.  If a new field is added while this menu
+    //     //  is displayed (unlikely) it won't show up until something else changes.
+    //     //TODO Types
+    //     untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false))));
+
+    //     this.columns.forEach(key => keys[key] = true);
+    //     return Array.from(Object.keys(keys)).map(item =>
+    //         (<KeyToggle checked={keys[item]} key={item} keyName={item} toggle={this.toggleKey} />));
+    // }
+
+    // get tableOptionsPanel() {
+    //     return !this.props.active() ? (null) :
+    //         (<Flyout
+    //             anchorPoint={anchorPoints.RIGHT_TOP}
+    //             content={<div>
+    //                 <div id="schema-options-header"><h5><b>Options</b></h5></div>
+    //                 <div id="options-flyout-div">
+    //                     <h6 className="schema-options-subHeader">Preview Window</h6>
+    //                     <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />  Show Preview </div>
+    //                     <h6 className="schema-options-subHeader" >Displayed Columns</h6>
+    //                     <ul id="schema-col-checklist" >
+    //                         {this.documentKeysCheckList}
+    //                     </ul>
+    //                     <input value={this._newKeyName} onChange={this.newKeyChange} />
+    //                     <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
+    //                 </div>
+    //             </div>
+    //             }>
+    //             <button id="schemaOptionsMenuBtn" ><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
+    //         </Flyout>);
+    // }
 
     @computed
     get reactTable() {
         let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
-        return <ReactTable style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} data={this.childDocs} page={0} pageSize={this.childDocs.length} showPagination={false}
+        return <ReactTable 
+            style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} 
+            data={this.childDocs} 
+            page={0} 
+            pageSize={this.childDocs.length} 
+            showPagination={false}
             columns={this.tableColumns}
-            column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
+            // column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
             getTrProps={this.getTrProps}
+            sortable={false}
         />;
     }
 
@@ -392,7 +468,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 {this.reactTable}
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
-                {this.tableOptionsPanel}
+                {/* {this.tableOptionsPanel} */}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 235bc1ea11df56e13d8a1103d4c029be42cf208d Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Wed, 17 Jul 2019 16:34:58 -0400
Subject: can change column type to any, string, number, bool, or checkbox

---
 .../views/collections/CollectionSchemaCells.tsx    | 276 +++------------------
 .../views/collections/CollectionSchemaHeaders.tsx  |   4 +
 .../views/collections/CollectionSchemaView.tsx     |  17 +-
 3 files changed, 45 insertions(+), 252 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index f15734df6..691c4f630 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -63,7 +63,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
     @action
     onKeyDown = (e: KeyboardEvent): void => {
         if (this.props.isFocused && this.props.isEditable) {
-            // console.log("schema cell", this.props.isEditable);
             document.removeEventListener("keydown", this.onKeyDown);
             this._isEditing = true;
             this.props.setIsEditing(true);
@@ -82,72 +81,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
     }
 
-    renderCell = (rowProps: CellInfo) => {
-        let props: FieldViewProps = {
-            Document: rowProps.original,
-            DataDoc: rowProps.original,
-            fieldKey: rowProps.column.id as string,
-            fieldExt: "",
-            ContainingCollectionView: this.props.CollectionView,
-            isSelected: returnFalse,
-            select: emptyFunction,
-            renderDepth: this.props.renderDepth + 1,
-            selectOnLoad: false,
-            ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
-            active: returnFalse,
-            whenActiveChanged: emptyFunction,
-            PanelHeight: returnZero,
-            PanelWidth: returnZero,
-            addDocTab: this.props.addDocTab,
-        };
-        let fieldContentView = <FieldView {...props} />;
-        let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = (e: React.PointerEvent) => {
-            (!this.props.CollectionView.props.isSelected() ? undefined :
-                SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
-        };
-        let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
-            const res = run({ this: doc });
-            if (!res.success) return false;
-            doc[props.fieldKey] = res.result;
-            return true;
-        };
-        return (
-            <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document[Id]} ref={reference}>
-                <EditableView
-                    display={"inline"}
-                    contents={fieldContentView}
-                    height={Number(MAX_ROW_HEIGHT)}
-                    GetValue={() => {
-                        let field = props.Document[props.fieldKey];
-                        if (Field.IsField(field)) {
-                            return Field.toScriptString(field);
-                        }
-                        return "";
-                    }}
-                    SetValue={(value: string) => {
-                        let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } });
-                        if (!script.compiled) {
-                            return false;
-                        }
-                        return applyToDoc(props.Document, script.run);
-                    }}
-                    OnFillDown={async (value: string) => {
-                        let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } });
-                        if (!script.compiled) {
-                            return;
-                        }
-                        const run = script.run;
-                        //TODO This should be able to be refactored to compile the script once
-                        const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-                        val && val.forEach(doc => applyToDoc(doc, run));
-                    }}>
-                </EditableView>
-            </div >
-        );
-    }
-
     renderCellWithType(type: string | undefined) {
         let props: FieldViewProps = {
             Document: this.props.rowProps.original,
@@ -167,7 +100,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             PanelWidth: returnZero,
             addDocTab: this.props.addDocTab,
         };
-        let fieldContentView: JSX.Element = <FieldView {...props} />;
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = (e: React.PointerEvent) => {
             // (!this.props.CollectionView.props.isSelected() ? undefined :
@@ -181,8 +113,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         };
 
         let field = props.Document[props.fieldKey];
-        let contents = type === undefined ? <FieldView {...props} /> : type === "number" ? NumCast(field) : type === "boolean" ? (BoolCast(field) ? "true" : "false") : "incorrect type";
-        // let contents = typeof field === "number" ? NumCast(field) : "incorrect type";
+        let contents: any = "incorrect type";
+        if (type === undefined) contents =  <FieldView {...props} />;
+        if (type === "number") contents = typeof field === "number" ? NumCast(field) : "--" + typeof field + "--";
+        if (type === "string") contents = typeof field === "string" ? (StrCast(field) === "" ? "--" : StrCast(field)) : "--" + typeof field + "--";
+        if (type === "boolean") contents = typeof field === "boolean" ? (BoolCast(field) ? "true" : "false") : "--" + typeof field + "--";
 
         return (
             <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
@@ -191,7 +126,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                         editing={this._isEditing}
                         // isEditingCallback={this.isEditingCallback}
                         display={"inline"}
-                        contents={fieldContentView}
+                        contents={contents}
                         height={Number(MAX_ROW_HEIGHT)}
                         GetValue={() => {
                             let field = props.Document[props.fieldKey];
@@ -224,7 +159,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
     }
 
     render() {
-        return this.renderCell(this.props.rowProps);
+        return this.renderCellWithType(undefined);
     }
 }
 
@@ -251,190 +186,37 @@ export class CollectionSchemaStringCell extends CollectionSchemaCell {
 
 @observer
 export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
+    @observable private _isChecked: boolean = typeof this.props.rowProps.original[this.props.rowProps.column.id as string] === "boolean" ? BoolCast(this.props.rowProps.original[this.props.rowProps.column.id as string]) : false;
+    private _doc: Doc = this.props.rowProps.original;
+
+    applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
+        const res = run({ this: doc });
+        if (!res.success) return false;
+        doc[this.props.rowProps.column.id as string] = res.result;
+        return true;
+    }
+
+    @action
+    toggleChecked = (e: React.ChangeEvent<HTMLInputElement>) => {
+        this._isChecked = e.target.checked;
+        let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } });
+            if (script.compiled) {
+                this.applyToDoc(this._doc, script.run);
+            }
+    }
+
     render() {
-        console.log("render checkbox cell");
-        let props: FieldViewProps = {
-            Document: this.props.rowProps.original,
-            DataDoc: this.props.rowProps.original,
-            fieldKey: this.props.rowProps.column.id as string,
-            fieldExt: "",
-            ContainingCollectionView: this.props.CollectionView,
-            isSelected: returnFalse,
-            select: emptyFunction,
-            renderDepth: this.props.renderDepth + 1,
-            selectOnLoad: false,
-            ScreenToLocalTransform: Transform.Identity,
-            focus: emptyFunction,
-            active: returnFalse,
-            whenActiveChanged: emptyFunction,
-            PanelHeight: returnZero,
-            PanelWidth: returnZero,
-            addDocTab: this.props.addDocTab,
-        };
-        let fieldContentView: JSX.Element = <FieldView {...props} />;
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = (e: React.PointerEvent) => {
             // (!this.props.CollectionView.props.isSelected() ? undefined :
             //     SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
         };
-        let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
-            const res = run({ this: doc });
-            if (!res.success) return false;
-            doc[props.fieldKey] = res.result;
-            return true;
-        };
-
-        let field = props.Document[props.fieldKey];
-        let contents = BoolCast(field);
-        console.log("contents", contents);
-        // let contents = typeof field === "number" ? NumCast(field) : "incorrect type";
-
-        let toggleChecked = (e: React.ChangeEvent<HTMLInputElement>) => {
-            console.log("toggle check", e.target.checked);
-            // this._isChecked = e.target.checked;
-
-            let document = this.props.rowProps.original;
-            let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } });
-            if (script.compiled) {
-                let applied = applyToDoc(document, script.run);
-                console.log("applied", applied);
-            }
-        };
-
         return (
             <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
-                <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document[Id]} ref={reference}>
-                    <input type="checkbox" onChange={toggleChecked} />
-                    {/* <EditableView
-                        editing={this._isEditing}
-                        isEditingCallback={this.isEditingCallback}
-                        display={"inline"}
-                        contents={fieldContentView}
-                        height={Number(MAX_ROW_HEIGHT)}
-                        GetValue={() => {
-                            let field = props.Document[props.fieldKey];
-                            if (Field.IsField(field)) {
-                                return Field.toScriptString(field);
-                            }
-                            return "";
-                        }
-                        }
-                        SetValue={(value: string) => {
-                            let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
-                            if (!script.compiled) {
-                                return false;
-                            }
-                            return applyToDoc(props.Document, script.run);
-                        }}
-                        OnFillDown={async (value: string) => {
-                            let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
-                            if (!script.compiled) {
-                                return;
-                            }
-                            const run = script.run;
-                            //TODO This should be able to be refactored to compile the script once
-                            const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-                            val && val.forEach(doc => applyToDoc(doc, run));
-                        }} /> */}
+                <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={this._doc[Id]} ref={reference}>
+                    <input type="checkbox" checked={this._isChecked} onChange={this.toggleChecked}/>
                 </div >
             </div>
         );
     }
-}
-
-        // @observer
-// export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
-//     // @observable private _isChecked: boolean = BoolCast(this.props.rowProps.original[this.props.fieldKey]);
-
-//     render() {
-//         console.log("checkbox rneder");
-
-//         let props: FieldViewProps = {
-//             Document: this.props.rowProps.original,
-//             DataDoc: this.props.rowProps.original,
-//             fieldKey: this.props.rowProps.column.id as string,
-//             fieldExt: "",
-//             ContainingCollectionView: this.props.CollectionView,
-//             isSelected: returnFalse,
-//             select: emptyFunction,
-//             renderDepth: this.props.renderDepth + 1,
-//             selectOnLoad: false,
-//             ScreenToLocalTransform: Transform.Identity,
-//             focus: emptyFunction,
-//             active: returnFalse,
-//             whenActiveChanged: emptyFunction,
-//             PanelHeight: returnZero,
-//             PanelWidth: returnZero,
-//             addDocTab: this.props.addDocTab,
-//         };
-//         let reference = React.createRef<HTMLDivElement>();
-//         let onItemDown = (e: React.PointerEvent) => {
-//             (!this.props.CollectionView.props.isSelected() ? undefined :
-//                 SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
-//         };
-
-//         let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
-//             const res = run({ this: doc });
-//             if (!res.success) return false;
-//             doc[this.props.fieldKey] = res.result;
-//             return true;
-//         };
-
-//         let toggleChecked = (e: React.ChangeEvent<HTMLInputElement>) => {
-//             console.log("toggle check", e.target.checked);
-//             // this._isChecked = e.target.checked;
-
-//             let document = this.props.rowProps.original;
-//             let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } });
-//             if (script.compiled) {
-//                 console.log("script compiled");
-//                 applyToDoc(document, script.run);
-//             }
-//         };
-
-
-//         let field = props.Document[props.fieldKey];
-//         // let contents = typeof field === "boolean" ? BoolCast(field) : "incorrect type";
-//         let checked = typeof field === "boolean" ? BoolCast(field) : false;
-
-//         return (
-//             <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
-//                 <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document[Id]} ref={reference}>
-//                     <input type="checkbox" checked={checked} onChange={toggleChecked} />
-
-//                     {/* <EditableView
-//                         editing={this._isEditing}
-//                         isEditingCallback={this.isEditingCallback}
-//                         display={"inline"}
-//                         contents={contents}
-//                         height={Number(MAX_ROW_HEIGHT)}
-//                         GetValue={() => {
-//                             let field = props.Document[props.fieldKey];
-//                             if (typeof field === "string") {
-//                                 return Field.toScriptString(field);
-//                             }
-//                             return "";
-//                         }
-//                         }
-//                         SetValue={(value: string) => {
-//                             let script = CompileScript(value, { requiredType: "boolean", addReturn: true, params: { this: Doc.name } });
-//                             if (!script.compiled) {
-//                                 return false;
-//                             }
-//                             return applyToDoc(props.Document, script.run);
-//                         }}
-//                         OnFillDown={async (value: string) => {
-//                             let script = CompileScript(value, { requiredType: "boolean", addReturn: true, params: { this: Doc.name } });
-//                             if (!script.compiled) {
-//                                 return;
-//                             }
-//                             const run = script.run;
-//                             //TODO This should be able to be refactored to compile the script once
-//                             const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-//                             val && val.forEach(doc => applyToDoc(doc, run));
-//                         }} /> */}
-//                 </div >
-//             </div>
-//         );
-//     }
-// }
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index a9d4a0170..3d45089a3 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -35,6 +35,7 @@ export class CollectionSchemaHeader extends React.Component<HeaderProps> {
                     possibleKeys={this.props.possibleKeys}
                     existingKeys={this.props.existingKeys}
                     keyType={this.props.keyType}
+                    typeConst={this.props.typeConst}
                     menuButtonContent={<div><FontAwesomeIcon icon={icon} size="sm" />{this.props.keyValue}</div>}
                     addNew={false}
                     onSelect={this.props.onSelect}
@@ -95,6 +96,7 @@ export interface ColumnMenuProps {
     possibleKeys: string[];
     existingKeys: string[];
     keyType: ColumnType;
+    typeConst: boolean;
     menuButtonContent: JSX.Element;
     addNew: boolean;
     onSelect: (oldKey: string, newKey: string, addnew: boolean) => void;
@@ -150,6 +152,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                             addNew={this.props.addNew}
                             onSelect={this.props.onSelect}
                         />
+                        {!this.props.typeConst ? 
                         <KeysDropdown
                             keyValue={keyTypeStr}
                             possibleKeys={colTypes}
@@ -158,6 +161,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                             addNew={false}
                             onSelect={this.setColumnType}
                         />
+                        : null}
                         <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button>
                     </div>
                 );
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 8ddf26be2..3572fac55 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -32,7 +32,7 @@ import { CollectionView } from "./CollectionView";
 import { undoBatch } from "../../util/UndoManager";
 import { timesSeries } from "async";
 import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders";
-import { CellProps, CollectionSchemaCell } from "./CollectionSchemaCells";
+import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell } from "./CollectionSchemaCells";
 
 
 library.add(faCog);
@@ -100,7 +100,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     possibleKeys={possibleKeys}
                     existingKeys={this.columns}
                     keyType={this.getColumnType(col)}
-                    typeConst={false}
+                    typeConst={columnTypes.get(col) !== undefined}
                     onSelect={this.changeColumns}
                     setIsEditing={this.setHeaderIsEditing}
                     deleteColumn={this.deleteColumn}
@@ -130,6 +130,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                         setIsEditing: action(emptyFunction), //this.setCellIsEditing,
                         isEditable: true //isEditable
                     };
+
+                    let colType = this.getColumnType(col);
+                    if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/>
+                    if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/>
+                    if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} />
+                    if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} />
                     return <CollectionSchemaCell {...props}/>
                 }
             };
@@ -324,9 +330,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         if (columnTypes.get(key)) return;
         const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc));
         if (!typesDoc) {
-            // let newTypesDoc = new Doc();
-            // newTypesDoc[key] = type;
-            // this.props.Document.schemaColumnTypes  = newTypesDoc;
+            let newTypesDoc = new Doc();
+            newTypesDoc[key] = type;
+            this.props.Document.schemaColumnTypes  = newTypesDoc;
+            console.log("no typesDoc");
             return;
         } else {
             typesDoc[key] = type;
-- 
cgit v1.2.3-70-g09d2


From 928f217b51acd105b5366b57fbb0c043740f97a6 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Wed, 17 Jul 2019 20:47:54 -0400
Subject: column menu styling

---
 .../views/collections/CollectionSchemaCells.tsx    |  46 ++-
 .../views/collections/CollectionSchemaHeaders.tsx  | 153 +++++---
 .../views/collections/CollectionSchemaView.scss    | 413 +++++++--------------
 .../views/collections/CollectionSchemaView.tsx     |  32 +-
 4 files changed, 272 insertions(+), 372 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 691c4f630..1bb661f88 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -81,6 +81,13 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
     }
 
+    applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
+        const res = run({ this: doc });
+        if (!res.success) return false;
+        doc[this.props.rowProps.column.id as string] = res.result;
+        return true;
+    }
+
     renderCellWithType(type: string | undefined) {
         let props: FieldViewProps = {
             Document: this.props.rowProps.original,
@@ -105,12 +112,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             // (!this.props.CollectionView.props.isSelected() ? undefined :
             //     SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
         };
-        let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
-            const res = run({ this: doc });
-            if (!res.success) return false;
-            doc[props.fieldKey] = res.result;
-            return true;
-        };
 
         let field = props.Document[props.fieldKey];
         let contents: any = "incorrect type";
@@ -141,7 +142,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                             if (!script.compiled) {
                                 return false;
                             }
-                            return applyToDoc(props.Document, script.run);
+                            return this.applyToDoc(props.Document, script.run);
                         }}
                         OnFillDown={async (value: string) => {
                             let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
@@ -151,7 +152,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                             const run = script.run;
                             //TODO This should be able to be refactored to compile the script once
                             const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-                            val && val.forEach(doc => applyToDoc(doc, run));
+                            val && val.forEach(doc => this.applyToDoc(doc, run));
                         }} />
                 </div >
             </div>
@@ -187,21 +188,13 @@ export class CollectionSchemaStringCell extends CollectionSchemaCell {
 @observer
 export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
     @observable private _isChecked: boolean = typeof this.props.rowProps.original[this.props.rowProps.column.id as string] === "boolean" ? BoolCast(this.props.rowProps.original[this.props.rowProps.column.id as string]) : false;
-    private _doc: Doc = this.props.rowProps.original;
-
-    applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
-        const res = run({ this: doc });
-        if (!res.success) return false;
-        doc[this.props.rowProps.column.id as string] = res.result;
-        return true;
-    }
 
     @action
     toggleChecked = (e: React.ChangeEvent<HTMLInputElement>) => {
         this._isChecked = e.target.checked;
         let script = CompileScript(e.target.checked.toString(), { requiredType: "boolean", addReturn: true, params: { this: Doc.name } });
             if (script.compiled) {
-                this.applyToDoc(this._doc, script.run);
+                this.applyToDoc(this._document, script.run);
             }
     }
 
@@ -213,10 +206,27 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
         };
         return (
             <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
-                <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={this._doc[Id]} ref={reference}>
+                <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={this._document[Id]} ref={reference}>
                     <input type="checkbox" checked={this._isChecked} onChange={this.toggleChecked}/>
                 </div >
             </div>
         );
     }
+}
+
+@observer
+export class CollectionSchemaDocCell extends CollectionSchemaCell {
+    render() {
+        let reference = React.createRef<HTMLDivElement>();
+        let onItemDown = (e: React.PointerEvent) => {
+            // (!this.props.CollectionView.props.isSelected() ? undefined :
+            //     SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
+        };
+        return (
+            <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+                <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={this._document[Id]} ref={reference}>
+                </div >
+            </div>
+        );
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 3d45089a3..d6ebaf8d8 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -2,14 +2,14 @@ import React = require("react");
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
 import "./CollectionSchemaView.scss";
-import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare } from '@fortawesome/free-solid-svg-icons';
+import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn } from '@fortawesome/free-solid-svg-icons';
 import { library, IconProp } from "@fortawesome/fontawesome-svg-core";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Flyout, anchorPoints } from "../DocumentDecorations";
 import { ColumnType } from "./CollectionSchemaView";
 import { emptyFunction } from "../../../Utils";
 
-library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare);
+library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn);
 
 export interface HeaderProps {
     keyValue: string;
@@ -26,7 +26,7 @@ export interface HeaderProps {
 export class CollectionSchemaHeader extends React.Component<HeaderProps> {
     render() {
         let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" :
-            this.props.keyType === ColumnType.Checkbox || this.props.keyType === ColumnType.Boolean ? "check-square" : "align-justify";
+            this.props.keyType === ColumnType.Checkbox ? "check-square" : this.props.keyType === ColumnType.Boolean ? "toggle-on" : "align-justify";
 
         return (
             <div className="collectionSchemaView-header" >
@@ -67,7 +67,7 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe
     // }
 
     render() {
-        let addButton = <button onClick={() => console.log("add clicked")}><FontAwesomeIcon icon="plus" size="sm" /></button>;
+        let addButton = <button><FontAwesomeIcon icon="plus" size="sm" /></button>;
         return (
             <div className="collectionSchemaView-header-addColumn" >
                 {/* {this._creatingColumn ? <></> : */}
@@ -76,6 +76,7 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe
                     possibleKeys={this.props.possibleKeys}
                     existingKeys={this.props.existingKeys}
                     keyType={ColumnType.Any}
+                    typeConst={true}
                     menuButtonContent={addButton}
                     addNew={true}
                     onSelect={this.props.onSelect}
@@ -120,68 +121,74 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         this.props.setColumnType(this.props.keyValue, type);
     }
 
-    renderContent = () => {
-        let keyTypeStr = ColumnType[this.props.keyType];
-        let colTypes = [];
-        for (let type in ColumnType) {
-            if (!(parseInt(type, 10) >= 0)) colTypes.push(type);
-        }
+    renderTypes = () => {
+        if (this.props.typeConst) return <></>;
+        return (
+            <div className="collectionSchema-headerMenu-group">
+                <label>Column type:</label>
+                <div className="columnMenu-types"> 
+                    <button title="Any" className={this.props.keyType === ColumnType.Any ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Any)}>
+                        <FontAwesomeIcon icon={"align-justify"} size="sm" />
+                        </button>
+                    <button title="Number" className={this.props.keyType === ColumnType.Number ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Number)}>
+                        <FontAwesomeIcon icon={"hashtag"} size="sm" />
+                        </button>
+                    <button title="String" className={this.props.keyType === ColumnType.String ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.String)}>
+                        <FontAwesomeIcon icon={"font"} size="sm" />
+                        </button>
+                    <button title="Boolean" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}>
+                        <FontAwesomeIcon icon={"toggle-on"} size="sm" />
+                        </button>
+                    <button title="Checkbox" className={this.props.keyType === ColumnType.Checkbox ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Checkbox)}>
+                        <FontAwesomeIcon icon={"check-square"} size="sm" />
+                        </button>
+                </div>
+            </div>
+        );
+    }
 
-        if (this._isOpen) {
-            if (this.props.onlyShowOptions) {
-                return (
-                    <div className="collectionSchema-header-menuOptions">
-                        <KeysDropdown
-                            keyValue={this.props.keyValue}
-                            possibleKeys={this.props.possibleKeys}
-                            existingKeys={this.props.existingKeys}
-                            canAddNew={true}
-                            addNew={this.props.addNew}
-                            onSelect={this.props.onSelect}
-                        />
-                    </div>
-                );
-            } else {
-                return (
-                    <div className="collectionSchema-header-menuOptions">
-                        <KeysDropdown
-                            keyValue={this.props.keyValue}
-                            possibleKeys={this.props.possibleKeys}
-                            existingKeys={this.props.existingKeys}
-                            canAddNew={true}
-                            addNew={this.props.addNew}
-                            onSelect={this.props.onSelect}
-                        />
-                        {!this.props.typeConst ? 
-                        <KeysDropdown
-                            keyValue={keyTypeStr}
-                            possibleKeys={colTypes}
-                            existingKeys={[]}
-                            canAddNew={false}
-                            addNew={false}
-                            onSelect={this.setColumnType}
-                        />
-                        : null}
+    renderContent = () => {
+        return (
+            <div className="collectionSchema-header-menuOptions">
+                <label>Key:</label>
+                <div className="collectionSchema-headerMenu-group">
+                    <KeysDropdown
+                        keyValue={this.props.keyValue}
+                        possibleKeys={this.props.possibleKeys}
+                        existingKeys={this.props.existingKeys}
+                        canAddNew={true}
+                        addNew={this.props.addNew}
+                        onSelect={this.props.onSelect}
+                    />
+                </div>
+                {this.props.onlyShowOptions ? <></> :
+                <>
+                    {this.renderTypes()}
+                    <div className="collectionSchema-headerMenu-group">
                         <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button>
                     </div>
-                );
-            }
-        }
+                </>
+                }
+            </div>
+        );
     }
 
     render() {
         return (
-            // <Flyout anchorPoint={anchorPoints.TOP} content={<div style={{ color: "black" }}>{this.renderContent()}</div>}>
-            //     <div onClick={() => { this.props.setIsEditing(true); console.log("clicked anchor"); }}>{this.props.menuButton}</div>
-            // </ Flyout >
             <div className="collectionSchema-header-menu">
-                <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div>
-                {this.renderContent()}
+                <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderContent()}>
+                    <div className="collectionSchema-header-toggler" onClick={() => { this.props.setIsEditing(true); }}>{this.props.menuButtonContent}</div>
+                </ Flyout >
             </div>
         );
     }
 }
 
+{/* // <div className="collectionSchema-header-menu">
+            //     <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div>
+            //     {this.renderContent()}
+            // </div> */}
+
 
 interface KeysDropdownProps {
     keyValue: string;
@@ -190,27 +197,56 @@ interface KeysDropdownProps {
     canAddNew: boolean;
     addNew: boolean;
     onSelect: (oldKey: string, newKey: string, addnew: boolean) => void;
-
 }
 @observer
 class KeysDropdown extends React.Component<KeysDropdownProps> {
     @observable private _key: string = this.props.keyValue;
     @observable private _searchTerm: string = "";
+    @observable private _isOpen: boolean = false;
+    @observable private _canClose: boolean = true;
 
     @action setSearchTerm = (value: string): void => { this._searchTerm = value; };
     @action setKey = (key: string): void => { this._key = key; };
+    @action setIsOpen = (isOpen: boolean): void => {this._isOpen = isOpen;};
 
     @action
     onSelect = (key: string): void => {
         this.props.onSelect(this._key, key, this.props.addNew);
         this.setKey(key);
+        this._isOpen = false;
     }
 
     onChange = (val: string): void => {
         this.setSearchTerm(val);
     }
 
+    @action
+    onFocus = (e: React.FocusEvent): void => {
+        this._isOpen = true;
+    }
+
+    @action
+    onBlur = (e: React.FocusEvent): void => {
+        // const that = this;
+        if (this._canClose) this._isOpen = false;
+        // setTimeout(function() { // TODO: this might be too hacky lol
+        //     that.setIsOpen(false);
+        // }, 100);
+    }
+
+    @action 
+    onPointerEnter = (e: React.PointerEvent): void => {
+        this._canClose = false;
+    }
+
+    @action
+    onPointerOut = (e: React.PointerEvent): void => {
+        this._canClose = true;
+    }
+
     renderOptions = (): JSX.Element[] | JSX.Element => {
+        if (!this._isOpen) return <></>;
+
         let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
         let exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 ||
             this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1;
@@ -222,7 +258,8 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
         // if search term does not already exist as a group type, give option to create new group type
         if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) {
             options.push(<div key={""} className="key-option"
-                onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}>Create "{this._searchTerm}" key</div>);
+                onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}>
+                    Create "{this._searchTerm}" key</div>);
         }
 
         return options;
@@ -231,9 +268,9 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
     render() {
         return (
             <div className="keys-dropdown">
-                <input type="text" value={this._searchTerm} placeholder="Search for or create a new key"
-                    onChange={e => this.onChange(e.target.value)} ></input>
-                <div className="keys-options-wrapper">
+                <input className="keys-search" type="text" value={this._searchTerm} placeholder="Search for or create a new key"
+                    onChange={e => this.onChange(e.target.value)} onFocus={this.onFocus} onBlur={this.onBlur}></input>
+                <div className="keys-options-wrapper" onPointerEnter={this.onPointerEnter} onPointerOut={this.onPointerOut}>
                     {this.renderOptions()}
                 </div>
             </div >
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 4ab38b9d9..4bc7a778c 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -1,7 +1,5 @@
 @import "../globalCssVariables";
 
-
-
 .collectionSchemaView-container {
     border-width: $COLLECTION_BORDER_WIDTH;
     border-color: $intermediate-color;
@@ -13,15 +11,6 @@
     height: 100%;
     overflow: hidden;
 
-    .collectionSchemaView-cellContents {
-        height: $MAX_ROW_HEIGHT;
-
-        img {
-            width: auto;
-            max-height: $MAX_ROW_HEIGHT;
-        }
-    }
-
     .collectionSchemaView-previewRegion {
         position: relative;
         background: $light-color;
@@ -47,16 +36,6 @@
         }
     }
 
-    .collectionSchemaView-previewHandle {
-        position: absolute;
-        height: 15px;
-        width: 15px;
-        z-index: 20;
-        right: 0;
-        top: 20px;
-        background: Black;
-    }
-
     .collectionSchemaView-dividerDragger {
         position: relative;
         background: black;
@@ -67,324 +46,198 @@
         right: 0;
         top: 0;
         background: $main-accent;
-    }
-
-    .collectionSchemaView-columnsHandle {
-        position: absolute;
-        height: 37px;
-        width: 20px;
-        z-index: 20;
-        left: 0;
-        bottom: 0;
-        background: $main-accent;
-    }
-
-    .collectionSchemaView-colDividerDragger {
-        position: relative;
-        box-sizing: border-box;
-        border-top: 1px solid $intermediate-color;
-        border-bottom: 1px solid $intermediate-color;
-        float: top;
-        width: 100%;
-    }
-
-    .collectionSchemaView-dividerDragger {
-        position: relative;
         box-sizing: border-box;
         border-left: 1px solid $intermediate-color;
         border-right: 1px solid $intermediate-color;
-        float: left;
-        height: 100%;
     }
+}
 
-    .collectionSchemaView-tableContainer {
-        position: relative;
-        float: left;
-        height: 100%;
-    }
+.ReactTable {
+    width: 100%;
+    height: 100%;
+    background: $light-color;
+    box-sizing: border-box;
+    border: none !important;
 
-    .ReactTable {
-        // position: absolute; // display: inline-block;
-        // overflow: auto;
-        width: 100%;
+    .rt-table {
+        overflow-y: auto;
+        overflow-x: auto;
         height: 100%;
-        background: $light-color;
-        box-sizing: border-box;
-        border: none !important;
-
-        .rt-table {
-            overflow-y: auto;
-            overflow-x: auto;
-            height: 100%;
-            display: -webkit-inline-box;
-            direction: ltr; // direction:rtl;
-            // display:block;
-        }
-
-        .rt-tbody {
-            //direction: ltr;
-            direction: rtl;
-        }
+        display: -webkit-inline-box;
+        direction: ltr; 
+    }
 
-        .rt-tr-group {
-            direction: ltr;
-            max-height: $MAX_ROW_HEIGHT;
+    .rt-thead {
+        &.-header {
+            background: $intermediate-color;
+            color: $light-color;
+            font-size: 12px;
+            height: 30px;
         }
 
-        .rt-td {
-            border-width: 1px;
-            border-right-color: $intermediate-color;
-
-            .imageBox-cont {
-                position: relative;
-                max-height: 100%;
-            }
-
-            .imageBox-cont img {
-                object-fit: contain;
-                max-width: 100%;
-                height: 100%;
-            }
+        .rt-resizable-header {
+            padding: 0;
+            height: 30px;
 
-            .videoBox-cont {
-                object-fit: contain;
-                width: auto;
-                height: 100%;
+            &:last-child {
+                overflow: visible;
             }
         }
-    }
 
-    .ReactTable .rt-thead.-header {
-        background: $intermediate-color;
-        color: $light-color;
-        // text-transform: uppercase;
-        letter-spacing: 2px;
-        font-size: 12px;
-        height: 30px;
-        padding-top: 4px;
+        .rt-resizable-header-content {
+            height: 100%;
+            overflow: visible;
+        }
     }
 
-    .ReactTable .rt-th,
-    .ReactTable .rt-td {
+    .rt-th {
         max-height: $MAX_ROW_HEIGHT;
         padding: 3px 7px;
         font-size: 13px;
         text-align: center;
     }
 
-    .ReactTable .rt-tbody .rt-tr-group:last-child {
-        border-bottom: $intermediate-color;
-        border-bottom-style: solid;
-        border-bottom-width: 1;
+    .rt-tbody {
+        direction: rtl;
     }
 
-    .documentView-node-topmost {
-        text-align: left;
-        transform-origin: center top;
-        display: inline-block;
-    }
+    .rt-tr-group {
+        direction: ltr;
+        max-height: $MAX_ROW_HEIGHT;
 
-    .documentView-node:first-child {
-        background: $light-color;
+        &:last-child {
+            border-bottom: $intermediate-color;
+            border-bottom-style: solid;
+            border-bottom-width: 1;
+        }
     }
 
-    .ReactTable .rt-thead .rt-resizable-header:last-child {
-        overflow: visible;
-    }
-}
+    .rt-td {
+        border-width: 1px;
+        border-right-color: $intermediate-color;
+        max-height: $MAX_ROW_HEIGHT;
+        padding: 3px 7px;
+        font-size: 13px;
+        text-align: center;
 
-.collectionSchema-header-menuOptions {
-    position: absolute;
-    top: $MAX_ROW_HEIGHT;
-    left: 0;
-    z-index: 9999;
-    background-color: $light-color-secondary;
-    color: black;
-    border: 1px solid $main-accent;
-    width: 250px;
-    padding: 10px;
+        .imageBox-cont {
+            position: relative;
+            max-height: 100%;
+        }
 
-    input {
-        color: black;
-        width: 100%;
+        .imageBox-cont img {
+            object-fit: contain;
+            max-width: 100%;
+            height: 100%;
+        }
+
+        .videoBox-cont {
+            object-fit: contain;
+            width: auto;
+            height: 100%;
+        }
     }
 }
 
-//options menu styling
-#schemaOptionsMenuBtn {
-    position: absolute;
-    height: 20px;
-    width: 20px;
-    border-radius: 50%;
-    z-index: 21;
-    right: 4px;
-    top: 4px;
-    pointer-events: auto;
-    background-color: black;
+.documentView-node-topmost {
+    text-align: left;
+    transform-origin: center top;
     display: inline-block;
-    padding: 0px;
-    font-size: 100%;
-}
-
-ul {
-    list-style-type: disc;
 }
 
-#schema-options-header {
-    text-align: center;
-    padding: 0px;
-    margin: 0px;
+.documentView-node:first-child {
+    background: $light-color;
 }
 
-.schema-options-subHeader {
-    color: $intermediate-color;
-    margin-bottom: 5px;
-}
+.collectionSchemaView-header {
+    height: 100%;
 
-#schemaOptionsMenuBtn:hover {
-    transform: scale(1.15);
-}
+    .collectionSchema-header-menu {
+        height: 100%;
 
-#preview-schema-checkbox-div {
-    margin-left: 20px;
-    font-size: 12px;
-}
+        .collectionSchema-header-toggler {
+            width: 100%;
+            height: 100%;
+            padding: 4px;
 
-#options-flyout-div {
-    text-align: left;
-    padding: 0px;
-    z-index: 100;
-    font-family: $sans-serif;
-    padding-left: 5px;
+            svg {
+                margin-right: 4px;
+            }
+        }
+    }
 }
 
-#schema-col-checklist {
-    overflow: scroll;
+.collectionSchema-header-menuOptions {
+    // position: absolute;
+    // top: 30px;
+    // left: 50%;
+    // transform: translateX(-50%);
+    // z-index: 9999;
+    // background-color: $light-color-secondary;
+    color: black;
+    // border: 1px solid $main-accent;
+    width: 175px;
+    // padding: 10px;
     text-align: left;
-    //background-color: $light-color-secondary;
-    line-height: 25px;
-    max-height: 175px;
-    font-family: $sans-serif;
-    font-size: 12px;
-}
-
 
-.Resizer {
-    box-sizing: border-box;
-    background: #000;
-    opacity: 0.5;
-    z-index: 1;
-    background-clip: padding-box;
-
-    &.horizontal {
-        height: 11px;
-        margin: -5px 0;
-        border-top: 5px solid rgba(255, 255, 255, 0);
-        border-bottom: 5px solid rgba(255, 255, 255, 0);
-        cursor: row-resize;
-        width: 100%;
-
-        &:hover {
-            border-top: 5px solid rgba(0, 0, 0, 0.5);
-            border-bottom: 5px solid rgba(0, 0, 0, 0.5);
-        }
+    .collectionSchema-headerMenu-group {
+        margin-bottom: 10px;
     }
 
-    &.vertical {
-        width: 11px;
-        margin: 0 -5px;
-        border-left: 5px solid rgba(255, 255, 255, 0);
-        border-right: 5px solid rgba(255, 255, 255, 0);
-        cursor: col-resize;
-
-        &:hover {
-            border-left: 5px solid rgba(0, 0, 0, 0.5);
-            border-right: 5px solid rgba(0, 0, 0, 0.5);
-        }
+    label {
+        color: $main-accent;
+        font-weight: normal;
     }
 
-    &:hover {
-        -webkit-transition: all 2s ease;
-        transition: all 2s ease;
+    input {
+        color: black;
+        width: 100%;
     }
-}
 
-.vertical {
-    section {
-        width: 100vh;
-        height: 100vh;
-        display: -webkit-box;
-        display: -webkit-flex;
-        display: -ms-flexbox;
-        display: flex;
-        -webkit-box-orient: vertical;
-        -webkit-box-direction: normal;
-        -webkit-flex-direction: column;
-        -ms-flex-direction: column;
-        flex-direction: column;
-    }
+    .keys-dropdown {
+        position: relative;
+        max-width: 175px;
 
-    header {
-        padding: 1rem;
-        background: #eee;
-    }
+        // .keys-search {
 
-    footer {
-        padding: 1rem;
-        background: #eee;
-    }
-}
+        // }
 
-.horizontal {
-    section {
-        width: 100vh;
-        height: 100vh;
-        display: flex;
-        flex-direction: column;
+        .keys-options-wrapper {
+            width: 100%;
+            max-height: 150px;
+            overflow-y: scroll;
+            position: absolute;
+            top: 20px;
+
+            .key-option {
+                background-color: $light-color;
+                border: 1px solid $light-color-secondary;
+                padding: 2px 3px;
+                
+                &:not(:last-child) {
+                    border-top: 0;
+                }
+
+                &:hover {
+                    background-color: $light-color-secondary;
+                }
+            }
+        }
     }
 
-    header {
-        padding: 1rem;
-        background: #eee;
-    }
+    .columnMenu-types {
+        display: flex;
+        justify-content: space-between;
 
-    footer {
-        padding: 1rem;
-        background: #eee;
+        button {
+            border-radius: 20px;
+        }
     }
 }
 
-.parent {
-    width: 100%;
-    height: 100%;
-    -webkit-box-flex: 1;
-    -webkit-flex: 1;
-    -ms-flex: 1;
-    flex: 1;
-    display: -webkit-box;
-    display: -webkit-flex;
-    display: -ms-flexbox;
-    display: flex;
-    -webkit-box-orient: vertical;
-    -webkit-box-direction: normal;
-    -webkit-flex-direction: column;
-    -ms-flex-direction: column;
-    flex-direction: column;
-}
-
-.header {
-    background: #aaa;
-    height: 3rem;
-    line-height: 3rem;
-}
-
-.wrapper {
-    background: #ffa;
-    margin: 5rem;
-    -webkit-box-flex: 1;
-    -webkit-flex: 1;
-    -ms-flex: 1;
-    flex: 1;
+#preview-schema-checkbox-div {
+    margin-left: 20px;
+    font-size: 12px;
 }
 
 .-even {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 3572fac55..3ef58bcaf 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -44,7 +44,7 @@ export enum ColumnType {
     Number,
     String,
     Boolean,
-    Doc,
+    // Doc,
     Checkbox
 }
 // this map should be used for keys that should have a const type of value
@@ -54,21 +54,21 @@ const columnTypes: Map<string, ColumnType> = new Map([
     ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number]
 ]);
 
-@observer
-class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> {
-    constructor(props: any) {
-        super(props);
-    }
-
-    render() {
-        return (
-            <div key={this.props.keyName}>
-                <input type="checkbox" checked={this.props.checked} onChange={() => this.props.toggle(this.props.keyName)} />
-                {this.props.keyName}
-            </div>
-        );
-    }
-}
+// @observer
+// class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> {
+//     constructor(props: any) {
+//         super(props);
+//     }
+
+//     render() {
+//         return (
+//             <div key={this.props.keyName}>
+//                 <input type="checkbox" checked={this.props.checked} onChange={() => this.props.toggle(this.props.keyName)} />
+//                 {this.props.keyName}
+//             </div>
+//         );
+//     }
+// }
 
 @observer
 export class CollectionSchemaView extends CollectionSubView(doc => doc) {
-- 
cgit v1.2.3-70-g09d2


From 28420a749a0e06ee105a2d8f1cc3c273469b83d7 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Thu, 18 Jul 2019 17:55:19 -0400
Subject: shema rows can be moved by dragging

---
 .../views/collections/CollectionSchemaCells.tsx    |  12 +-
 .../views/collections/CollectionSchemaHeaders.tsx  |   3 +
 .../CollectionSchemaMovableTableHOC.tsx            | 261 +++++++++++++++++++++
 .../views/collections/CollectionSchemaView.scss    |  82 +++++--
 .../views/collections/CollectionSchemaView.tsx     | 183 +++++++++++----
 5 files changed, 476 insertions(+), 65 deletions(-)
 create mode 100644 src/client/views/collections/CollectionSchemaMovableTableHOC.tsx

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 1bb661f88..51e9016b7 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -109,8 +109,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         };
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = (e: React.PointerEvent) => {
-            // (!this.props.CollectionView.props.isSelected() ? undefined :
-            //     SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
+            (!this.props.CollectionView.props.isSelected() ? undefined :
+                SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
         };
 
         let field = props.Document[props.fieldKey];
@@ -201,8 +201,8 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
     render() {
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = (e: React.PointerEvent) => {
-            // (!this.props.CollectionView.props.isSelected() ? undefined :
-            //     SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
+            (!this.props.CollectionView.props.isSelected() ? undefined :
+                SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
         };
         return (
             <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
@@ -219,8 +219,8 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell {
     render() {
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = (e: React.PointerEvent) => {
-            // (!this.props.CollectionView.props.isSelected() ? undefined :
-            //     SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
+            (!this.props.CollectionView.props.isSelected() ? undefined :
+                SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
         };
         return (
             <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index d6ebaf8d8..c81cf1aef 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -177,7 +177,10 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         return (
             <div className="collectionSchema-header-menu">
                 <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderContent()}>
+                {/* <div onClick={this.toggleIsOpen}> */}
                     <div className="collectionSchema-header-toggler" onClick={() => { this.props.setIsEditing(true); }}>{this.props.menuButtonContent}</div>
+                    {/* {this._isOpen ? this.renderContent() : <></>} */}
+                {/* </div> */}
                 </ Flyout >
             </div>
         );
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
new file mode 100644
index 000000000..44a134d31
--- /dev/null
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -0,0 +1,261 @@
+import React = require("react");
+import { TableProps, ReactTableDefaults, Column, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table";
+import { ComponentType, ComponentClass } from 'react';
+import { action } from "mobx";
+import "./CollectionSchemaView.scss";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faBars } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Transform } from "../../util/Transform";
+import { Doc } from "../../../new_fields/Doc";
+import { DragManager, SetupDrag } from "../../util/DragManager";
+import { SelectionManager } from "../../util/SelectionManager";
+import { Cast, FieldValue } from "../../../new_fields/Types";
+
+library.add(faBars);
+
+// export interface MovableSchemaProps {
+//     ScreenToLocalTransform: () => Transform;
+//     addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
+//     moveDoc: DragManager.MoveFunction;
+//     columnsValues: string[];
+//     columnsList: Column<any>[];
+//     setColumnsOrder: (columns: string[]) => void;
+//     numImmovableColumns?: number;
+// }
+
+// export default function CollectionSchemaMovableHOC<Props extends Partial<TableProps>>(WrappedComponent: ComponentType<Props>): ComponentClass<Props & MovableSchemaProps> {
+//     return class CollectionSchemaMovableSchemaHOC extends React.Component<Props & MovableSchemaProps> {
+//         constructor(props: any) {
+//             super(props);
+//         }
+
+//         reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) {
+//             let columns = [...columnsValues];
+//             let oldIndex = columns.indexOf(toMove);
+//             let relIndex = columns.indexOf(relativeTo);
+//             let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
+
+//             if (oldIndex === newIndex) return;
+
+//             columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
+//             setColumnsOrder(columns);
+//         }
+
+//         createColumns(columnsValues: string[], columnsList: Column<any>[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column<any>[] {
+//             let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length;
+//             return columnsList.map((col, index) => {
+//                 if (index >= immovableIndex) {
+//                     return col;
+//                 } else {
+//                     return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) });
+//                 }
+//             });
+//         }
+
+//         render() {
+//             console.log("THIS IS THE RIGHT HOC");
+//             const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props;
+//             return (
+//                 <WrappedComponent {...props as Props} ></WrappedComponent>
+//             );
+//         }
+
+//     };
+// }
+// //TrComponent={MovableRow(ScreenToLocalTransform, addDoc, moveDoc)}
+// //columns={this.createColumns(columnsValues, columnsList, setColumnsOrder, ScreenToLocalTransform)}
+
+// export  function MovableSchemaHOC<Props extends Partial<TableProps>>(WrappedComponent: ComponentType<Props>): ComponentClass<Props & MovableSchemaProps> {
+//     return class MovableSchemaHOC extends React.Component<Props & MovableSchemaProps> {
+//         constructor(props: any) {
+//             super(props);
+//         }
+
+//         createColumns(columnsValues: string[], columnsList: Column<any>[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column<any>[] {
+//             let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length;
+//             return columnsList.map((col, index) => {
+//                 if (index >= immovableIndex) {
+//                     return col;
+//                 } else {
+//                     return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) });
+//                 }
+//             });
+//         }
+
+//         reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) {
+//             let columns = [...columnsValues];
+//             let oldIndex = columns.indexOf(toMove);
+//             let relIndex = columns.indexOf(relativeTo);
+//             let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
+
+//             if (oldIndex === newIndex) return;
+
+//             columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
+//             setColumnsOrder(columns);
+//         }
+
+//         render() {
+//             const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props;
+//             return (
+//                 <WrappedComponent {...props as Props} columns={this.createColumns(columnsValues, columnsList, setColumnsOrder, ScreenToLocalTransform)} TrComponent={MovableRow(ScreenToLocalTransform, addDoc, moveDoc)} ></WrappedComponent>
+//             );
+//         }
+//     };
+// }
+
+
+
+
+export interface MovableColumnProps {
+    columnRenderer: TableCellRenderer;
+    columnValue: string;
+    allColumns: string[];
+    reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void;
+    ScreenToLocalTransform: () => Transform;
+}
+export class MovableColumn extends React.Component<MovableColumnProps> {
+    // private _ref: React.RefObject<HTMLDivElement> = React.createRef();
+
+    onDragStart = (e: React.DragEvent<HTMLDivElement>, ref: React.RefObject<HTMLDivElement>): void => {
+        console.log("drag start");
+        e.dataTransfer.setData("column", this.props.columnValue);
+    }
+
+    onDragOver = (e: React.DragEvent<HTMLDivElement>,ref: React.RefObject<HTMLDivElement>): void => {
+        console.log("drag over");
+        let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+        let rect = ref.current!.getBoundingClientRect();
+        let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top);
+        let before = x[0] < bounds[0];
+
+        ref.current!.className = "collectionSchema-column-header";
+        if (before) ref.current!.className += " col-before";
+        if (!before) ref.current!.className += " col-after";
+        // e.stopPropagation();
+    }
+
+    onDragLeave = (e: React.DragEvent<HTMLDivElement>, ref: React.RefObject<HTMLDivElement>): void => {
+        console.log("drag leave");
+        ref.current!.className = "collectionSchema-column-header";
+        e.stopPropagation();
+    }
+
+    onDrop = (e: React.DragEvent<HTMLDivElement>,ref: React.RefObject<HTMLDivElement>): void => {
+        console.log("on drop");
+        // TODO: get column being dropped and before/after
+        let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+        let rect = ref.current!.getBoundingClientRect();
+        let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top);
+        let before = x[0] < bounds[0];
+
+        this.props.reorderColumns(e.dataTransfer.getData("column"), this.props.columnValue, before, this.props.allColumns);
+        ref.current!.className = "collectionSchema-column-header";
+    }
+
+    render() {
+        let ref: React.RefObject<HTMLDivElement> =  React.createRef();
+        return (
+             <div className="collectionSchema-column-header" ref={ref} draggable={true} 
+             onPointerDown={() => console.log("pointer down")} onPointerEnter={() => console.log("pointer enter")} onPointerOut={() => console.log("pointer exit")}
+                 onDragStart={e => this.onDragStart(e, ref)} onDragOver={e => this.onDragOver(e, ref)} onDragLeave={e => this.onDragLeave(e, ref)} onDrop={e => this.onDrop(e, ref)}>
+                 {this.props.columnRenderer}
+            </div>
+        );
+    }
+}
+
+// export function MovableColumn(columnRenderer: TableCellRenderer, columnValue: string, allColumns: string[],
+//     reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void,
+//     ScreenToLocalTransform: () => Transform) {
+//     return ;
+// }
+
+export function MovableRow(ScreenToLocalTransform: () => Transform, addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean, moveDoc: DragManager.MoveFunction) {
+    return class MovableRow extends React.Component {
+        private _header?: React.RefObject<HTMLDivElement> = React.createRef();
+        private _treedropDisposer?: DragManager.DragDropDisposer;
+
+        onPointerEnter = (e: React.PointerEvent): void => {
+            if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
+                this._header!.current!.className = "collectionSchema-row-wrapper";
+                document.addEventListener("pointermove", this.onDragMove, true);
+            }
+        }
+        onPointerLeave = (e: React.PointerEvent): void => {
+            this._header!.current!.className = "collectionSchema-row-wrapper";
+            document.removeEventListener("pointermove", this.onDragMove, true);
+        }
+        onDragMove = (e: PointerEvent): void => {
+            let x = ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+            let rect = this._header!.current!.getBoundingClientRect();
+            let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+            let before = x[1] < bounds[1];
+            this._header!.current!.className = "collectionSchema-row-wrapper";
+            if (before) this._header!.current!.className += " row-above";
+            if (!before) this._header!.current!.className += " row-below";
+            e.stopPropagation();
+        }
+
+        createTreeDropTarget = (ele: HTMLDivElement) => {
+            this._treedropDisposer && this._treedropDisposer();
+            if (ele) {
+                this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } });
+            }
+        }
+
+        treeDrop = (e: Event, de: DragManager.DropEvent) => {
+            const { children = null, rowInfo } = this.props;
+            if (!rowInfo) return false;
+
+            const { original } = rowInfo;
+            const rowDoc = FieldValue(Cast(original, Doc));
+            if (!rowDoc) return false;
+
+            let x = ScreenToLocalTransform().transformPoint(de.x, de.y);
+            let rect = this._header!.current!.getBoundingClientRect();
+            let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+            let before = x[1] < bounds[1];
+            if (de.data instanceof DragManager.DocumentDragData) {
+                e.stopPropagation();
+                if (de.data.draggedDocuments[0] === rowDoc) return true;
+                let addDocument = (doc: Doc) => addDoc(doc, rowDoc, before);
+                let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
+                return (de.data.dropAction || de.data.userDropAction) ?
+                    de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before) || added, false)
+                    : (de.data.moveDocument) ?
+                        movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false)
+                        : de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before), false);
+            }
+            return false;
+        }
+
+        render() {
+            const { children = null, rowInfo } = this.props;
+            if (!rowInfo) {
+                console.log("no rowinfo");
+                return <ReactTableDefaults.TrComponent>{children}</ReactTableDefaults.TrComponent>;
+            }
+
+            const { original } = rowInfo;
+            const doc = FieldValue(Cast(original, Doc));
+            if (!doc) return <></>;
+
+            let reference = React.createRef<HTMLDivElement>();
+            let onItemDown = SetupDrag(reference, () => doc, moveDoc);
+
+            return (
+                <div className="collectionSchema-row" ref={this.createTreeDropTarget}>
+                    <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+                        <div className="row-dragger" ref={reference} onPointerDown={onItemDown}>
+                            <ReactTableDefaults.TrComponent>
+                                {children}
+                            </ReactTableDefaults.TrComponent>
+                        </div>
+                    </div>
+                </div>
+            );
+        }
+    };
+}
+
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 4bc7a778c..fce1c8833 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -105,6 +105,14 @@
         direction: ltr;
         max-height: $MAX_ROW_HEIGHT;
 
+        &:nth-child(even) {
+            background-color: $light-color;
+        }
+    
+        &:nth-child(odd) {
+            background-color: $light-color-secondary;
+        }
+
         &:last-child {
             border-bottom: $intermediate-color;
             border-bottom-style: solid;
@@ -112,6 +120,10 @@
         }
     }
 
+    .rt-tr {
+        width: 100%;
+    }
+
     .rt-td {
         border-width: 1px;
         border-right-color: $intermediate-color;
@@ -149,6 +161,18 @@
     background: $light-color;
 }
 
+.collectionSchema-column-header {
+    height: 100%;
+    background-color: green;
+
+    &.col-before {
+        border-left: 2px solid red;
+    }
+    &.col-after {
+        border-right: 2px solid red;
+    }
+}  
+
 .collectionSchemaView-header {
     height: 100%;
 
@@ -168,16 +192,8 @@
 }
 
 .collectionSchema-header-menuOptions {
-    // position: absolute;
-    // top: 30px;
-    // left: 50%;
-    // transform: translateX(-50%);
-    // z-index: 9999;
-    // background-color: $light-color-secondary;
     color: black;
-    // border: 1px solid $main-accent;
     width: 175px;
-    // padding: 10px;
     text-align: left;
 
     .collectionSchema-headerMenu-group {
@@ -235,15 +251,51 @@
     }
 }
 
-#preview-schema-checkbox-div {
-    margin-left: 20px;
-    font-size: 12px;
+.collectionSchema-row {
+    height: $MAX_ROW_HEIGHT;
+    // display: flex;
+
+    .row-dragger {
+        height: $MAX_ROW_HEIGHT;
+    }
+
+    .collectionSchema-row-wrapper {
+        max-height: $MAX_ROW_HEIGHT;
+        // width: 100%;
+        // border: 1px solid lightgray;
+
+        &.row-above {
+            border-top: 1px solid red;
+        }
+        &.row-below {
+            border-bottom: 1px solid red;
+        }
+        &.row-inside {
+            border: 1px solid red;
+        }
+    }
 }
 
-.-even {
-    background: $light-color !important;
+
+.collectionSchemaView-cellWrapper {
+    // height: $MAX_ROW_HEIGHT;
+    // background-color: red;
+    height: 100%;
+    padding: 4px;
+
+    &.focused {
+        // background-color: yellowgreen;
+        border: 2px solid yellowgreen;
+
+        input {
+            outline: 0;
+            border: none;
+            background-color: yellow;
+        }
+    }
 }
 
-.-odd {
-    background: $light-color-secondary !important;
+#preview-schema-checkbox-div {
+    margin-left: 20px;
+    font-size: 12px;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 3ef58bcaf..4746e637b 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -4,7 +4,7 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 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 } from "react-table";
+import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column } from "react-table";
 import "react-table/react-table.css";
 import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils";
 import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc";
@@ -33,12 +33,14 @@ import { undoBatch } from "../../util/UndoManager";
 import { timesSeries } from "async";
 import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders";
 import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell } from "./CollectionSchemaCells";
-
+import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC";
 
 library.add(faCog);
 library.add(faPlus);
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
 
+// const MovableTable = CollectionSchemaMovableSchemaHOC(ReactTable);
+
 export enum ColumnType {
     Any,
     Number,
@@ -54,22 +56,6 @@ const columnTypes: Map<string, ColumnType> = new Map([
     ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number]
 ]);
 
-// @observer
-// class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> {
-//     constructor(props: any) {
-//         super(props);
-//     }
-
-//     render() {
-//         return (
-//             <div key={this.props.keyName}>
-//                 <input type="checkbox" checked={this.props.checked} onChange={() => this.props.toggle(this.props.keyName)} />
-//                 {this.props.keyName}
-//             </div>
-//         );
-//     }
-// }
-
 @observer
 export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     private _mainCont?: HTMLDivElement;
@@ -83,6 +69,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable _newKeyName: string = "";
     @observable previewScript: string = "";
     @observable _headerIsEditing: boolean = false;
+    @observable _cellIsEditing: boolean = false;
+    @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0};
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
@@ -90,10 +78,25 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); }
     set columns(columns: string[]) { this.props.Document.schemaColumns = new List<string>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
-    @computed get tableColumns() {
+    @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
 
         let cols = this.columns.map(col => {
+            let focusedRow = this._focusedCell.row;
+            let focusedCol = this._focusedCell.col;
+            let isEditable = !this._headerIsEditing;
+            let header = <CollectionSchemaHeader 
+                keyValue={col}
+                possibleKeys={possibleKeys}
+                existingKeys={this.columns}
+                keyType={this.getColumnType(col)}
+                typeConst={columnTypes.get(col) !== undefined}
+                onSelect={this.changeColumns}
+                setIsEditing={this.setHeaderIsEditing}
+                deleteColumn={this.deleteColumn}
+                setColumnType={this.setColumnType}
+            />;
+
             return {
                 Header: <CollectionSchemaHeader 
                     keyValue={col}
@@ -106,37 +109,37 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     deleteColumn={this.deleteColumn}
                     setColumnType={this.setColumnType}
                 />,
+                // Header: <MovableColumn columnRenderer={header} columnValue={col} allColumns={this.columns} reorderColumns={this.reorderColumns} ScreenToLocalTransform={this.props.ScreenToLocalTransform} />,
                 accessor: (doc: Doc) => doc ? doc[col] : 0,
                 id: col,
                 Cell: (rowProps: CellInfo) => {
                     let row = rowProps.index;
                     let column = this.columns.indexOf(rowProps.column.id!);
-                    // let isFocused = focusedRow === row && focusedCol === column;
-                    let isFocused = false;
+                    let isFocused = focusedRow === row && focusedCol === column;
 
                     let props: CellProps = {
                         row: row,
                         col: column,
                         rowProps: rowProps,
                         isFocused: isFocused,
-                        changeFocusedCellByDirection: action(emptyFunction),//this.changeFocusedCellByDirection,
-                        changeFocusedCellByIndex: action(emptyFunction), //this.changeFocusedCellByIndex,
+                        changeFocusedCellByDirection: this.changeFocusedCellByDirection,
+                        changeFocusedCellByIndex: this.changeFocusedCellByIndex,
                         CollectionView: this.props.CollectionView,
                         ContainingCollection: this.props.ContainingCollectionView,
                         Document: this.props.Document,
                         fieldKey: this.props.fieldKey,
                         renderDepth: this.props.renderDepth, addDocTab: this.props.addDocTab,
                         moveDocument: this.props.moveDocument,
-                        setIsEditing: action(emptyFunction), //this.setCellIsEditing,
-                        isEditable: true //isEditable
+                        setIsEditing: this.setCellIsEditing,
+                        isEditable: isEditable
                     };
 
                     let colType = this.getColumnType(col);
-                    if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/>
-                    if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/>
-                    if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} />
-                    if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} />
-                    return <CollectionSchemaCell {...props}/>
+                    if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/>;
+                    if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/>;
+                    if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} />;
+                    if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} />;
+                    return <CollectionSchemaCell {...props}/>;
                 }
             };
         }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult<Field>, id: string, Cell: (rowProps: CellInfo) => JSX.Element}[];
@@ -156,6 +159,19 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return cols;
     }
 
+    reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) {
+        let columns = [...columnsValues];
+        let oldIndex = columns.indexOf(toMove);
+        let relIndex = columns.indexOf(relativeTo);
+        let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
+
+        if (oldIndex === newIndex) return;
+
+        columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
+        this.columns = columns;
+    }
+
+
     onHeaderDrag = (columnName: string) => {
         let schemaDoc = Cast(this.props.Document.schemaDoc, Doc);
         if (schemaDoc instanceof Doc) {
@@ -170,12 +186,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return this.props.Document;
     }
 
+    componentDidMount() {
+        document.addEventListener("keydown", this.onKeyDown);
+    }
+
+    componentWillUnmount() {
+        document.removeEventListener("keydown", this.onKeyDown);
+    }
+
     private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
         const that = this;
         if (!rowInfo) {
             return {};
         }
         return {
+            rowInfo, 
             onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
                 that.props.select(e.ctrlKey);
                 that._selectedIndex = rowInfo.index;
@@ -195,27 +220,63 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this._mainCont = ele;
         super.CreateDropTarget(ele);
     }
+    @action
+    changeFocusedCellByDirection = (direction: string): void => {
+        switch (direction) {
+            case "tab":
+                if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) {
+                    this._focusedCell = { row: 0, col: 0 };
+                } else if (this._focusedCell.col + 1 === this.columns.length) {
+                    this._focusedCell = { row: this._focusedCell.row + 1, col: 0 };
+                } else {
+                    this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 };
+                }
+                break;
+            case "right":
+                this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 === this.columns.length ? this._focusedCell.col : this._focusedCell.col + 1 };
+                break;
+            case "left":
+                this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col === 0 ? this._focusedCell.col : this._focusedCell.col - 1 };
+                break;
+            case "up":
+                this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col };
+                break;
+            case "down":
+                this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
+                break;
+        }
+    }
 
     @action
-    setHeaderIsEditing = (isEditing: boolean) => {
-        this._headerIsEditing = isEditing;
+    changeFocusedCellByIndex = (row: number, col: number): void => {
+        this._focusedCell = { row: row, col: col };
     }
 
     @action
-    toggleKey = (key: string) => {
-        let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
-        if (list === undefined) {
-            this.props.Document.schemaColumns = list = new List<string>([key]);
-        } else {
-            const index = list.indexOf(key);
-            if (index === -1) {
-                list.push(key);
-            } else {
-                list.splice(index, 1);
-            }
-        }
+    setCellIsEditing = (isEditing: boolean): void => {
+        this._cellIsEditing = isEditing;
     }
 
+    @action
+    setHeaderIsEditing = (isEditing: boolean): void => {
+        this._headerIsEditing = isEditing;
+    }
+
+    // @action
+    // toggleKey = (key: string) => {
+    //     let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
+    //     if (list === undefined) {
+    //         this.props.Document.schemaColumns = list = new List<string>([key]);
+    //     } else {
+    //         const index = list.indexOf(key);
+    //         if (index === -1) {
+    //             list.push(key);
+    //         } else {
+    //             list.splice(index, 1);
+    //         }
+    //     }
+    // }
+
     //toggles preview side-panel of schema
     @action
     toggleExpander = () => {
@@ -262,6 +323,13 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         }
     }
 
+    onKeyDown = (e: KeyboardEvent): void => {
+        if (!this._cellIsEditing && !this._headerIsEditing) {
+            let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
+            this.changeFocusedCellByDirection(direction);
+        }
+    }
+
     @action
     makeDB = async () => {
         let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
@@ -410,7 +478,31 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @computed
     get reactTable() {
+        let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
+        let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
         let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
+
+        // return <MovableTable
+        //     style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
+        //     data={this.childDocs}
+        //     page={0}
+        //     pageSize={this.childDocs.length}
+        //     showPagination={false}
+        //     columns={this.tableColumns}
+        //     sortable={false}
+        //     getTrProps={this.getTrProps}
+
+        //     ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+        //     addDoc={addDoc}
+        //     moveDoc={moveDoc}
+        //     columnsValues={this.columns}
+        //     columnsList={this.tableColumns}
+        //     setColumnsOrder={(columns: string[]) => this.columns = columns}
+        //     numImmovableColumns={1}
+        // />;
+
+
+        // // let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         return <ReactTable 
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} 
             data={this.childDocs} 
@@ -421,6 +513,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             // column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
             getTrProps={this.getTrProps}
             sortable={false}
+
+            TrComponent={MovableRow(this.props.ScreenToLocalTransform, addDoc, moveDoc)}
         />;
     }
 
@@ -472,6 +566,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
+                    <div draggable={true} style={{backgroundColor: "green"}}>TESTER</div>
                 {this.reactTable}
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
-- 
cgit v1.2.3-70-g09d2


From 8a1be635352177ba05845851289d1a67b4060708 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Thu, 18 Jul 2019 19:24:58 -0400
Subject: schema cols can be moved by dragging

---
 src/client/util/DragManager.ts                     |  13 +
 .../CollectionSchemaMovableTableHOC.tsx            | 346 +++++++++------------
 .../views/collections/CollectionSchemaView.scss    |  15 +-
 .../views/collections/CollectionSchemaView.tsx     |  63 +---
 4 files changed, 175 insertions(+), 262 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 323908302..f9f6b05c0 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -288,6 +288,15 @@ export namespace DragManager {
         [id: string]: any;
     }
 
+    // for column dragging in schema view
+    export class ColumnDragData {
+        constructor(colKey: string) {
+            this.colKey = colKey;
+        }
+        colKey: string;
+        [id: string]: any;
+    }
+
     export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, downX: number, downY: number, options?: DragOptions) {
         StartDrag([ele], dragData, downX, downY, options);
     }
@@ -296,6 +305,10 @@ export namespace DragManager {
         StartDrag([ele], dragData, downX, downY, options);
     }
 
+    export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?:DragOptions) {
+        StartDrag([ele], dragData, downX, downY, options);
+    }
+
     export let AbortDrag: () => void = emptyFunction;
 
     function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) {
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 44a134d31..3a61881a7 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -1,111 +1,12 @@
 import React = require("react");
-import { TableProps, ReactTableDefaults, Column, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table";
-import { ComponentType, ComponentClass } from 'react';
-import { action } from "mobx";
+import { ReactTableDefaults, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table";
 import "./CollectionSchemaView.scss";
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faBars } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Transform } from "../../util/Transform";
 import { Doc } from "../../../new_fields/Doc";
 import { DragManager, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Cast, FieldValue } from "../../../new_fields/Types";
 
-library.add(faBars);
-
-// export interface MovableSchemaProps {
-//     ScreenToLocalTransform: () => Transform;
-//     addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
-//     moveDoc: DragManager.MoveFunction;
-//     columnsValues: string[];
-//     columnsList: Column<any>[];
-//     setColumnsOrder: (columns: string[]) => void;
-//     numImmovableColumns?: number;
-// }
-
-// export default function CollectionSchemaMovableHOC<Props extends Partial<TableProps>>(WrappedComponent: ComponentType<Props>): ComponentClass<Props & MovableSchemaProps> {
-//     return class CollectionSchemaMovableSchemaHOC extends React.Component<Props & MovableSchemaProps> {
-//         constructor(props: any) {
-//             super(props);
-//         }
-
-//         reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) {
-//             let columns = [...columnsValues];
-//             let oldIndex = columns.indexOf(toMove);
-//             let relIndex = columns.indexOf(relativeTo);
-//             let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
-
-//             if (oldIndex === newIndex) return;
-
-//             columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
-//             setColumnsOrder(columns);
-//         }
-
-//         createColumns(columnsValues: string[], columnsList: Column<any>[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column<any>[] {
-//             let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length;
-//             return columnsList.map((col, index) => {
-//                 if (index >= immovableIndex) {
-//                     return col;
-//                 } else {
-//                     return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) });
-//                 }
-//             });
-//         }
-
-//         render() {
-//             console.log("THIS IS THE RIGHT HOC");
-//             const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props;
-//             return (
-//                 <WrappedComponent {...props as Props} ></WrappedComponent>
-//             );
-//         }
-
-//     };
-// }
-// //TrComponent={MovableRow(ScreenToLocalTransform, addDoc, moveDoc)}
-// //columns={this.createColumns(columnsValues, columnsList, setColumnsOrder, ScreenToLocalTransform)}
-
-// export  function MovableSchemaHOC<Props extends Partial<TableProps>>(WrappedComponent: ComponentType<Props>): ComponentClass<Props & MovableSchemaProps> {
-//     return class MovableSchemaHOC extends React.Component<Props & MovableSchemaProps> {
-//         constructor(props: any) {
-//             super(props);
-//         }
-
-//         createColumns(columnsValues: string[], columnsList: Column<any>[], setColumnsOrder: (columnsValues: string[]) => void, ScreenToLocalTransform: () => Transform): Column<any>[] {
-//             let immovableIndex = this.props.numImmovableColumns ? columnsList.length - this.props.numImmovableColumns! : columnsList.length;
-//             return columnsList.map((col, index) => {
-//                 if (index >= immovableIndex) {
-//                     return col;
-//                 } else {
-//                     return ({ ...col, Header: MovableColumn(col.Header, columnsValues[index], columnsValues, setColumnsOrder, this.reorderColumns, ScreenToLocalTransform) });
-//                 }
-//             });
-//         }
-
-//         reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[], setColumnsOrder: (columns: string[]) => void) {
-//             let columns = [...columnsValues];
-//             let oldIndex = columns.indexOf(toMove);
-//             let relIndex = columns.indexOf(relativeTo);
-//             let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
-
-//             if (oldIndex === newIndex) return;
-
-//             columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
-//             setColumnsOrder(columns);
-//         }
-
-//         render() {
-//             const { ScreenToLocalTransform, addDoc, moveDoc, columnsValues, columnsList, setColumnsOrder, getTrProps, ...props } = this.props;
-//             return (
-//                 <WrappedComponent {...props as Props} columns={this.createColumns(columnsValues, columnsList, setColumnsOrder, ScreenToLocalTransform)} TrComponent={MovableRow(ScreenToLocalTransform, addDoc, moveDoc)} ></WrappedComponent>
-//             );
-//         }
-//     };
-// }
-
-
-
 
 export interface MovableColumnProps {
     columnRenderer: TableCellRenderer;
@@ -115,147 +16,178 @@ export interface MovableColumnProps {
     ScreenToLocalTransform: () => Transform;
 }
 export class MovableColumn extends React.Component<MovableColumnProps> {
-    // private _ref: React.RefObject<HTMLDivElement> = React.createRef();
+    private _header?: React.RefObject<HTMLDivElement> = React.createRef();
+    private _colDropDisposer?: DragManager.DragDropDisposer;
 
-    onDragStart = (e: React.DragEvent<HTMLDivElement>, ref: React.RefObject<HTMLDivElement>): void => {
-        console.log("drag start");
-        e.dataTransfer.setData("column", this.props.columnValue);
+    onPointerEnter = (e: React.PointerEvent): void => {
+        if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
+            this._header!.current!.className = "collectionSchema-col-wrapper";
+            document.addEventListener("pointermove", this.onDragMove, true);
+        }
     }
-
-    onDragOver = (e: React.DragEvent<HTMLDivElement>,ref: React.RefObject<HTMLDivElement>): void => {
-        console.log("drag over");
+    onPointerLeave = (e: React.PointerEvent): void => {
+        this._header!.current!.className = "collectionSchema-col-wrapper";
+        document.removeEventListener("pointermove", this.onDragMove, true);
+    }
+    onDragMove = (e: PointerEvent): void => {
         let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
-        let rect = ref.current!.getBoundingClientRect();
+        let rect = this._header!.current!.getBoundingClientRect();
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top);
         let before = x[0] < bounds[0];
-
-        ref.current!.className = "collectionSchema-column-header";
-        if (before) ref.current!.className += " col-before";
-        if (!before) ref.current!.className += " col-after";
-        // e.stopPropagation();
+        this._header!.current!.className = "collectionSchema-col-wrapper";
+        if (before) this._header!.current!.className += " col-before";
+        if (!before) this._header!.current!.className += " col-after";
+        e.stopPropagation();
     }
 
-    onDragLeave = (e: React.DragEvent<HTMLDivElement>, ref: React.RefObject<HTMLDivElement>): void => {
-        console.log("drag leave");
-        ref.current!.className = "collectionSchema-column-header";
-        e.stopPropagation();
+    createColDropTarget = (ele: HTMLDivElement) => {
+        this._colDropDisposer && this._colDropDisposer();
+        if (ele) {
+            this._colDropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.colDrop.bind(this) } });
+        }
     }
 
-    onDrop = (e: React.DragEvent<HTMLDivElement>,ref: React.RefObject<HTMLDivElement>): void => {
-        console.log("on drop");
-        // TODO: get column being dropped and before/after
-        let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
-        let rect = ref.current!.getBoundingClientRect();
+    colDrop = (e: Event, de: DragManager.DropEvent) => {
+        document.removeEventListener("pointermove", this.onDragMove, true);
+        let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
+        let rect = this._header!.current!.getBoundingClientRect();
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + ((rect.right - rect.left) / 2), rect.top);
         let before = x[0] < bounds[0];
+        if (de.data instanceof DragManager.ColumnDragData) {
+            this.props.reorderColumns(de.data.colKey, this.props.columnValue, before, this.props.allColumns);
+            return true;
+        }
+        return false;
+    }
 
-        this.props.reorderColumns(e.dataTransfer.getData("column"), this.props.columnValue, before, this.props.allColumns);
-        ref.current!.className = "collectionSchema-column-header";
+    setupDrag (ref: React.RefObject<HTMLElement>) {
+        let onRowMove = (e: PointerEvent) => {
+            e.stopPropagation();
+            e.preventDefault();
+
+            document.removeEventListener("pointermove", onRowMove);
+            document.removeEventListener('pointerup', onRowUp);
+            let dragData = new DragManager.ColumnDragData(this.props.columnValue);
+            DragManager.StartColumnDrag(ref.current!, dragData, e.x, e.y);
+        };
+        let onRowUp = (): void => {
+            document.removeEventListener("pointermove", onRowMove);
+            document.removeEventListener('pointerup', onRowUp);
+        };
+        let onItemDown = (e: React.PointerEvent) => {
+            if (e.button === 0) {
+                e.stopPropagation();
+                document.addEventListener("pointermove", onRowMove);
+                document.addEventListener("pointerup", onRowUp);
+            }
+        };
+        return onItemDown;
     }
 
+
     render() {
-        let ref: React.RefObject<HTMLDivElement> =  React.createRef();
+        let reference = React.createRef<HTMLDivElement>();
+        let onItemDown = this.setupDrag(reference);
+
         return (
-             <div className="collectionSchema-column-header" ref={ref} draggable={true} 
-             onPointerDown={() => console.log("pointer down")} onPointerEnter={() => console.log("pointer enter")} onPointerOut={() => console.log("pointer exit")}
-                 onDragStart={e => this.onDragStart(e, ref)} onDragOver={e => this.onDragOver(e, ref)} onDragLeave={e => this.onDragLeave(e, ref)} onDrop={e => this.onDrop(e, ref)}>
-                 {this.props.columnRenderer}
+            <div className="collectionSchema-col" ref={this.createColDropTarget}>
+                <div className="collectionSchema-col-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+                    <div className="col-dragger" ref={reference} onPointerDown={onItemDown}>
+                        {this.props.columnRenderer}
+                    </div>
+                </div>
             </div>
         );
     }
 }
 
-// export function MovableColumn(columnRenderer: TableCellRenderer, columnValue: string, allColumns: string[],
-//     reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void,
-//     ScreenToLocalTransform: () => Transform) {
-//     return ;
-// }
+export interface MovableRowProps {
+    ScreenToLocalTransform: () => Transform;
+    addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
+    moveDoc: DragManager.MoveFunction;
+}
 
-export function MovableRow(ScreenToLocalTransform: () => Transform, addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean, moveDoc: DragManager.MoveFunction) {
-    return class MovableRow extends React.Component {
-        private _header?: React.RefObject<HTMLDivElement> = React.createRef();
-        private _treedropDisposer?: DragManager.DragDropDisposer;
+export class MovableRow extends React.Component<MovableRowProps> {
+    private _header?: React.RefObject<HTMLDivElement> = React.createRef();
+    private _rowDropDisposer?: DragManager.DragDropDisposer;
 
-        onPointerEnter = (e: React.PointerEvent): void => {
-            if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
-                this._header!.current!.className = "collectionSchema-row-wrapper";
-                document.addEventListener("pointermove", this.onDragMove, true);
-            }
-        }
-        onPointerLeave = (e: React.PointerEvent): void => {
-            this._header!.current!.className = "collectionSchema-row-wrapper";
-            document.removeEventListener("pointermove", this.onDragMove, true);
-        }
-        onDragMove = (e: PointerEvent): void => {
-            let x = ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
-            let rect = this._header!.current!.getBoundingClientRect();
-            let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
-            let before = x[1] < bounds[1];
+    onPointerEnter = (e: React.PointerEvent): void => {
+        if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
             this._header!.current!.className = "collectionSchema-row-wrapper";
-            if (before) this._header!.current!.className += " row-above";
-            if (!before) this._header!.current!.className += " row-below";
-            e.stopPropagation();
+            document.addEventListener("pointermove", this.onDragMove, true);
         }
+    }
+    onPointerLeave = (e: React.PointerEvent): void => {
+        this._header!.current!.className = "collectionSchema-row-wrapper";
+        document.removeEventListener("pointermove", this.onDragMove, true);
+    }
+    onDragMove = (e: PointerEvent): void => {
+        let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+        let rect = this._header!.current!.getBoundingClientRect();
+        let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+        let before = x[1] < bounds[1];
+        this._header!.current!.className = "collectionSchema-row-wrapper";
+        if (before) this._header!.current!.className += " row-above";
+        if (!before) this._header!.current!.className += " row-below";
+        e.stopPropagation();
+    }
 
-        createTreeDropTarget = (ele: HTMLDivElement) => {
-            this._treedropDisposer && this._treedropDisposer();
-            if (ele) {
-                this._treedropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.treeDrop.bind(this) } });
-            }
+    createRowDropTarget = (ele: HTMLDivElement) => {
+        this._rowDropDisposer && this._rowDropDisposer();
+        if (ele) {
+            this._rowDropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.rowDrop.bind(this) } });
         }
+    }
 
-        treeDrop = (e: Event, de: DragManager.DropEvent) => {
-            const { children = null, rowInfo } = this.props;
-            if (!rowInfo) return false;
+    rowDrop = (e: Event, de: DragManager.DropEvent) => {
+        const { children = null, rowInfo } = this.props;
+        if (!rowInfo) return false;
 
-            const { original } = rowInfo;
-            const rowDoc = FieldValue(Cast(original, Doc));
-            if (!rowDoc) return false;
+        const { original } = rowInfo;
+        const rowDoc = FieldValue(Cast(original, Doc));
+        if (!rowDoc) return false;
 
-            let x = ScreenToLocalTransform().transformPoint(de.x, de.y);
-            let rect = this._header!.current!.getBoundingClientRect();
-            let bounds = ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
-            let before = x[1] < bounds[1];
-            if (de.data instanceof DragManager.DocumentDragData) {
-                e.stopPropagation();
-                if (de.data.draggedDocuments[0] === rowDoc) return true;
-                let addDocument = (doc: Doc) => addDoc(doc, rowDoc, before);
-                let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
-                return (de.data.dropAction || de.data.userDropAction) ?
-                    de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before) || added, false)
-                    : (de.data.moveDocument) ?
-                        movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false)
-                        : de.data.droppedDocuments.reduce((added: boolean, d) => addDoc(d, rowDoc, before), false);
-            }
-            return false;
+        let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
+        let rect = this._header!.current!.getBoundingClientRect();
+        let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+        let before = x[1] < bounds[1];
+        if (de.data instanceof DragManager.DocumentDragData) {
+            e.stopPropagation();
+            if (de.data.draggedDocuments[0] === rowDoc) return true;
+            let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before);
+            let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
+            return (de.data.dropAction || de.data.userDropAction) ?
+                de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
+                : (de.data.moveDocument) ?
+                    movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false)
+                    : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false);
         }
+        return false;
+    }
 
-        render() {
-            const { children = null, rowInfo } = this.props;
-            if (!rowInfo) {
-                console.log("no rowinfo");
-                return <ReactTableDefaults.TrComponent>{children}</ReactTableDefaults.TrComponent>;
-            }
+    render() {
+        const { children = null, rowInfo } = this.props;
+        if (!rowInfo) {
+            return <ReactTableDefaults.TrComponent>{children}</ReactTableDefaults.TrComponent>;
+        }
 
-            const { original } = rowInfo;
-            const doc = FieldValue(Cast(original, Doc));
-            if (!doc) return <></>;
+        const { original } = rowInfo;
+        const doc = FieldValue(Cast(original, Doc));
+        if (!doc) return <></>;
 
-            let reference = React.createRef<HTMLDivElement>();
-            let onItemDown = SetupDrag(reference, () => doc, moveDoc);
+        let reference = React.createRef<HTMLDivElement>();
+        let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc);
 
-            return (
-                <div className="collectionSchema-row" ref={this.createTreeDropTarget}>
-                    <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
-                        <div className="row-dragger" ref={reference} onPointerDown={onItemDown}>
-                            <ReactTableDefaults.TrComponent>
-                                {children}
-                            </ReactTableDefaults.TrComponent>
-                        </div>
+        return (
+            <div className="collectionSchema-row" ref={this.createRowDropTarget}>
+                <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+                    <div className="row-dragger" ref={reference} onPointerDown={onItemDown}>
+                        <ReactTableDefaults.TrComponent>
+                            {children}
+                        </ReactTableDefaults.TrComponent>
                     </div>
                 </div>
-            );
-        }
-    };
-}
-
+            </div>
+        );
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index fce1c8833..15dec4e44 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -161,18 +161,21 @@
     background: $light-color;
 }
 
-.collectionSchema-column-header {
+.collectionSchema-col{
     height: 100%;
     background-color: green;
 
-    &.col-before {
-        border-left: 2px solid red;
-    }
-    &.col-after {
-        border-right: 2px solid red;
+    .collectionSchema-col-wrapper {
+        &.col-before {
+            border-left: 2px solid red;
+        }
+        &.col-after {
+            border-right: 2px solid red;
+        }
     }
 }  
 
+
 .collectionSchemaView-header {
     height: 100%;
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4746e637b..b9b299e13 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -62,7 +62,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     private _startPreviewWidth = 0;
     private DIVIDER_WIDTH = 4;
 
-    @observable _columns: Array<string> = ["title", "data", "author"];
+    // @observable _columns: Array<string> = ["title", "data", "author"];
     @observable _selectedIndex = 0;
     @observable _columnsPercentage = 0;
     @observable _keys: string[] = [];
@@ -76,7 +76,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @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(); }
     @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); }
-    set columns(columns: string[]) { this.props.Document.schemaColumns = new List<string>(columns); }
+    set columns(columns: string[]) {this.props.Document.schemaColumns = new List<string>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
@@ -98,18 +98,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             />;
 
             return {
-                Header: <CollectionSchemaHeader 
-                    keyValue={col}
-                    possibleKeys={possibleKeys}
-                    existingKeys={this.columns}
-                    keyType={this.getColumnType(col)}
-                    typeConst={columnTypes.get(col) !== undefined}
-                    onSelect={this.changeColumns}
-                    setIsEditing={this.setHeaderIsEditing}
-                    deleteColumn={this.deleteColumn}
-                    setColumnType={this.setColumnType}
-                />,
-                // Header: <MovableColumn columnRenderer={header} columnValue={col} allColumns={this.columns} reorderColumns={this.reorderColumns} ScreenToLocalTransform={this.props.ScreenToLocalTransform} />,
+                Header: <MovableColumn columnRenderer={header} columnValue={col} allColumns={this.columns} reorderColumns={this.reorderColumns} ScreenToLocalTransform={this.props.ScreenToLocalTransform} />,
                 accessor: (doc: Doc) => doc ? doc[col] : 0,
                 id: col,
                 Cell: (rowProps: CellInfo) => {
@@ -159,7 +148,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return cols;
     }
 
-    reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) {
+    @action
+    setColumns = (columns: string[]) => {
+        this.columns = columns;
+    }
+
+    reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => {
         let columns = [...columnsValues];
         let oldIndex = columns.indexOf(toMove);
         let relIndex = columns.indexOf(relativeTo);
@@ -168,7 +162,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         if (oldIndex === newIndex) return;
 
         columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
-        this.columns = columns;
+        this.setColumns(columns);
     }
 
 
@@ -200,6 +194,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             return {};
         }
         return {
+            ScreenToLocalTransform: this.props.ScreenToLocalTransform,
+            addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before),
+            moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc),
             rowInfo, 
             onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
                 that.props.select(e.ctrlKey);
@@ -209,10 +206,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     handleOriginal();
                 }
             }),
-            style: {
-                background: rowInfo.index === this._selectedIndex ? "lightGray" : "white",
-                //color: rowInfo.index === this._selectedIndex ? "white" : "black"
-            }
         };
     }
 
@@ -401,7 +394,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             let newTypesDoc = new Doc();
             newTypesDoc[key] = type;
             this.props.Document.schemaColumnTypes  = newTypesDoc;
-            console.log("no typesDoc");
             return;
         } else {
             typesDoc[key] = type;
@@ -478,31 +470,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @computed
     get reactTable() {
-        let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
-        let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc);
         let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
-
-        // return <MovableTable
-        //     style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
-        //     data={this.childDocs}
-        //     page={0}
-        //     pageSize={this.childDocs.length}
-        //     showPagination={false}
-        //     columns={this.tableColumns}
-        //     sortable={false}
-        //     getTrProps={this.getTrProps}
-
-        //     ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-        //     addDoc={addDoc}
-        //     moveDoc={moveDoc}
-        //     columnsValues={this.columns}
-        //     columnsList={this.tableColumns}
-        //     setColumnsOrder={(columns: string[]) => this.columns = columns}
-        //     numImmovableColumns={1}
-        // />;
-
-
-        // // let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         return <ReactTable 
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} 
             data={this.childDocs} 
@@ -510,11 +478,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             pageSize={this.childDocs.length} 
             showPagination={false}
             columns={this.tableColumns}
-            // column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
             getTrProps={this.getTrProps}
             sortable={false}
-
-            TrComponent={MovableRow(this.props.ScreenToLocalTransform, addDoc, moveDoc)}
+            TrComponent={MovableRow}
         />;
     }
 
@@ -566,7 +532,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
-                    <div draggable={true} style={{backgroundColor: "green"}}>TESTER</div>
                 {this.reactTable}
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
-- 
cgit v1.2.3-70-g09d2


From ae51e87874a714fdb46d4093fee513787b413ed8 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Fri, 19 Jul 2019 13:11:10 -0400
Subject: can sort columns by asc, desc

---
 src/client/views/EditableView.tsx                  |  12 +-
 .../views/collections/CollectionSchemaCells.tsx    |   2 +-
 .../views/collections/CollectionSchemaHeaders.tsx  |  90 ++++++---
 .../views/collections/CollectionSchemaView.scss    |   1 -
 .../views/collections/CollectionSchemaView.tsx     | 204 ++++++++-------------
 5 files changed, 159 insertions(+), 150 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 989fb1be9..42faedf9d 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -31,6 +31,7 @@ export interface EditableProps {
     oneLine?: boolean;
     editing?: boolean;
     onClick?: (e: React.MouseEvent) => boolean;
+    isEditingCallback?:  (isEditing: boolean) => void;
 }
 
 /**
@@ -47,6 +48,11 @@ export class EditableView extends React.Component<EditableProps> {
         this._editing = this.props.editing ? true : false;
     }
 
+    @action
+    componentWillReceiveProps(nextProps: EditableProps) {
+        this._editing = nextProps.editing ? true : false;
+    }
+
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
         if (e.key === "Tab") {
@@ -55,13 +61,16 @@ export class EditableView extends React.Component<EditableProps> {
             if (!e.ctrlKey) {
                 if (this.props.SetValue(e.currentTarget.value, e.shiftKey)) {
                     this._editing = false;
+                    this.props.isEditingCallback && this.props.isEditingCallback(false);
                 }
             } else if (this.props.OnFillDown) {
                 this.props.OnFillDown(e.currentTarget.value);
                 this._editing = false;
+                this.props.isEditingCallback && this.props.isEditingCallback(false);
             }
         } else if (e.key === "Escape") {
             this._editing = false;
+            this.props.isEditingCallback && this.props.isEditingCallback(false);
         }
     }
 
@@ -69,6 +78,7 @@ export class EditableView extends React.Component<EditableProps> {
     onClick = (e: React.MouseEvent) => {
         if (!this.props.onClick || !this.props.onClick(e)) {
             this._editing = true;
+            this.props.isEditingCallback && this.props.isEditingCallback(true);
         }
         e.stopPropagation();
     }
@@ -85,7 +95,7 @@ export class EditableView extends React.Component<EditableProps> {
     render() {
         if (this._editing) {
             return <input className="editableView-input" defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus
-                onBlur={action(() => this._editing = false)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
+                onBlur={action(() => {this._editing = false; this.props.isEditingCallback && this.props.isEditingCallback(false);})} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
                 style={{ display: this.props.display, fontSize: this.props.fontSize }} />;
         } else {
             return (
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 51e9016b7..5b40032eb 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -125,7 +125,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                 <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document[Id]} ref={reference}>
                     <EditableView
                         editing={this._isEditing}
-                        // isEditingCallback={this.isEditingCallback}
+                        isEditingCallback={this.isEditingCallback}
                         display={"inline"}
                         contents={contents}
                         height={Number(MAX_ROW_HEIGHT)}
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index c81cf1aef..6002d64ce 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -21,6 +21,8 @@ export interface HeaderProps {
     setIsEditing: (isEditing: boolean) => void;
     deleteColumn: (column: string) => void;
     setColumnType: (key: string, type: ColumnType) => void;
+    setColumnSort: (key: string, desc: boolean) => void;
+    removeColumnSort: (key: string) => void;
 }
 
 export class CollectionSchemaHeader extends React.Component<HeaderProps> {
@@ -43,6 +45,8 @@ export class CollectionSchemaHeader extends React.Component<HeaderProps> {
                     deleteColumn={this.props.deleteColumn}
                     onlyShowOptions={false}
                     setColumnType={this.props.setColumnType}
+                    setColumnSort={this.props.setColumnSort}
+                    removeColumnSort={this.props.removeColumnSort}
                 />
             </div>
         );
@@ -59,18 +63,10 @@ export interface AddColumnHeaderProps {
 
 @observer
 export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHeaderProps> {
-    // @observable private _creatingColumn: boolean = false;
-
-    // @action
-    // onClick = (e: React.MouseEvent): void => {
-    //     this._creatingColumn = true;
-    // }
-
     render() {
         let addButton = <button><FontAwesomeIcon icon="plus" size="sm" /></button>;
         return (
             <div className="collectionSchemaView-header-addColumn" >
-                {/* {this._creatingColumn ? <></> : */}
                 <CollectionSchemaColumnMenu
                     keyValue=""
                     possibleKeys={this.props.possibleKeys}
@@ -84,6 +80,8 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe
                     deleteColumn={action(emptyFunction)}
                     onlyShowOptions={true}
                     setColumnType={action(emptyFunction)}
+                    setColumnSort={action(emptyFunction)}
+                    removeColumnSort={action(emptyFunction)}
                 />
             </div>
         );
@@ -105,12 +103,38 @@ export interface ColumnMenuProps {
     deleteColumn: (column: string) => void;
     onlyShowOptions: boolean;
     setColumnType: (key: string, type: ColumnType) => void;
+    setColumnSort: (key: string, desc: boolean) => void;
+    removeColumnSort: (key: string) => void;
 }
 @observer
 export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> {
     @observable private _isOpen: boolean = false;
+    // @observable private _node : HTMLDivElement | null = null;
+    @observable private _node = React.createRef<HTMLDivElement>();
 
-    @action toggleIsOpen = (): void => {
+    componentDidMount() {
+        document.addEventListener("pointerdown", this.onPointerDown);
+        console.log("did mount", this._node);
+    }
+
+    componentWillUnmount() {
+        document.removeEventListener("pointerdown", this.onPointerDown);
+    }
+
+    onPointerDown (e: PointerEvent) {
+        console.log("pointer down", this._node);
+        if (this._node ) {
+            // && this._node.contains(e.target as Node)
+            console.log("CLICKED INSNIDE");
+        } else {
+            console.log("CLICKED OUTSIDE");
+            // console.log(this._node);
+            // console.log(e.target as Node);
+        }
+    }
+
+    @action 
+    toggleIsOpen = (): void => {
         this._isOpen = !this._isOpen;
         this.props.setIsEditing(this._isOpen);
     }
@@ -121,6 +145,14 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         this.props.setColumnType(this.props.keyValue, type);
     }
 
+    // @action
+    // setNode = (node: HTMLDivElement): void => {
+    //     if (node) {
+    //         this._node = node;
+    //         console.log("set node to ", this._node);
+    //     }
+    // }
+
     renderTypes = () => {
         if (this.props.typeConst) return <></>;
         return (
@@ -147,6 +179,19 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         );
     }
 
+    renderSorting = () => {
+        return (
+            <div className="collectionSchema-headerMenu-group">
+                <label>Sort by:</label>
+                <div className="columnMenu-sort">
+                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.keyValue, false)}>Sort ascending</div>
+                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.keyValue, true)}>Sort descending</div>
+                    <div className="columnMenu-option" onClick={() => this.props.removeColumnSort(this.props.keyValue)}>Clear sorting</div>
+                </div>
+            </div>
+        );
+    }
+
     renderContent = () => {
         return (
             <div className="collectionSchema-header-menuOptions">
@@ -159,11 +204,13 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                         canAddNew={true}
                         addNew={this.props.addNew}
                         onSelect={this.props.onSelect}
+                        setIsEditing={this.props.setIsEditing}
                     />
                 </div>
                 {this.props.onlyShowOptions ? <></> :
                 <>
                     {this.renderTypes()}
+                    {this.renderSorting()}
                     <div className="collectionSchema-headerMenu-group">
                         <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button>
                     </div>
@@ -174,24 +221,17 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
     }
 
     render() {
+        console.log("render", this._node);
         return (
-            <div className="collectionSchema-header-menu">
+            <div className="collectionSchema-header-menu" ref={this._node}>
                 <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderContent()}>
-                {/* <div onClick={this.toggleIsOpen}> */}
-                    <div className="collectionSchema-header-toggler" onClick={() => { this.props.setIsEditing(true); }}>{this.props.menuButtonContent}</div>
-                    {/* {this._isOpen ? this.renderContent() : <></>} */}
-                {/* </div> */}
+                    <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div>
                 </ Flyout >
             </div>
         );
     }
 }
 
-{/* // <div className="collectionSchema-header-menu">
-            //     <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div>
-            //     {this.renderContent()}
-            // </div> */}
-
 
 interface KeysDropdownProps {
     keyValue: string;
@@ -200,6 +240,7 @@ interface KeysDropdownProps {
     canAddNew: boolean;
     addNew: boolean;
     onSelect: (oldKey: string, newKey: string, addnew: boolean) => void;
+    setIsEditing: (isEditing: boolean) => void;
 }
 @observer
 class KeysDropdown extends React.Component<KeysDropdownProps> {
@@ -217,6 +258,7 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
         this.props.onSelect(this._key, key, this.props.addNew);
         this.setKey(key);
         this._isOpen = false;
+        this.props.setIsEditing(false);
     }
 
     onChange = (val: string): void => {
@@ -226,15 +268,15 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
     @action
     onFocus = (e: React.FocusEvent): void => {
         this._isOpen = true;
+        this.props.setIsEditing(true);
     }
 
     @action
     onBlur = (e: React.FocusEvent): void => {
-        // const that = this;
-        if (this._canClose) this._isOpen = false;
-        // setTimeout(function() { // TODO: this might be too hacky lol
-        //     that.setIsOpen(false);
-        // }, 100);
+        if (this._canClose) {
+            this._isOpen = false;
+            this.props.setIsEditing(false);
+        }
     }
 
     @action 
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 15dec4e44..4ae9628a9 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -163,7 +163,6 @@
 
 .collectionSchema-col{
     height: 100%;
-    background-color: green;
 
     .collectionSchema-col-wrapper {
         &.col-before {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index b9b299e13..10b1e895d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -39,8 +39,6 @@ library.add(faCog);
 library.add(faPlus);
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
 
-// const MovableTable = CollectionSchemaMovableSchemaHOC(ReactTable);
-
 export enum ColumnType {
     Any,
     Number,
@@ -62,7 +60,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     private _startPreviewWidth = 0;
     private DIVIDER_WIDTH = 4;
 
-    // @observable _columns: Array<string> = ["title", "data", "author"];
     @observable _selectedIndex = 0;
     @observable _columnsPercentage = 0;
     @observable _keys: string[] = [];
@@ -71,6 +68,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable _headerIsEditing: boolean = false;
     @observable _cellIsEditing: boolean = false;
     @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0};
+    @observable _sortedColumns: Map<string, {id: string, desc: boolean}> = new Map();
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
@@ -80,7 +78,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
-
         let cols = this.columns.map(col => {
             let focusedRow = this._focusedCell.row;
             let focusedCol = this._focusedCell.col;
@@ -95,6 +92,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 setIsEditing={this.setHeaderIsEditing}
                 deleteColumn={this.deleteColumn}
                 setColumnType={this.setColumnType}
+                setColumnSort={this.setColumnSort}
+                removeColumnSort={this.removeColumnSort}
             />;
 
             return {
@@ -148,37 +147,19 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return cols;
     }
 
-    @action
-    setColumns = (columns: string[]) => {
-        this.columns = columns;
-    }
-
-    reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => {
-        let columns = [...columnsValues];
-        let oldIndex = columns.indexOf(toMove);
-        let relIndex = columns.indexOf(relativeTo);
-        let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
-
-        if (oldIndex === newIndex) return;
-
-        columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
-        this.setColumns(columns);
-    }
-
-
-    onHeaderDrag = (columnName: string) => {
-        let schemaDoc = Cast(this.props.Document.schemaDoc, Doc);
-        if (schemaDoc instanceof Doc) {
-            let columnDocs = DocListCast(schemaDoc.data);
-            if (columnDocs) {
-                let ddoc = columnDocs.find(doc => doc.title === columnName);
-                if (ddoc) {
-                    return ddoc;
-                }
-            }
-        }
-        return this.props.Document;
-    }
+    // onHeaderDrag = (columnName: string) => {
+    //     let schemaDoc = Cast(this.props.Document.schemaDoc, Doc);
+    //     if (schemaDoc instanceof Doc) {
+    //         let columnDocs = DocListCast(schemaDoc.data);
+    //         if (columnDocs) {
+    //             let ddoc = columnDocs.find(doc => doc.title === columnName);
+    //             if (ddoc) {
+    //                 return ddoc;
+    //             }
+    //         }
+    //     }
+    //     return this.props.Document;
+    // }
 
     componentDidMount() {
         document.addEventListener("keydown", this.onKeyDown);
@@ -213,37 +194,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this._mainCont = ele;
         super.CreateDropTarget(ele);
     }
-    @action
-    changeFocusedCellByDirection = (direction: string): void => {
-        switch (direction) {
-            case "tab":
-                if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) {
-                    this._focusedCell = { row: 0, col: 0 };
-                } else if (this._focusedCell.col + 1 === this.columns.length) {
-                    this._focusedCell = { row: this._focusedCell.row + 1, col: 0 };
-                } else {
-                    this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 };
-                }
-                break;
-            case "right":
-                this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 === this.columns.length ? this._focusedCell.col : this._focusedCell.col + 1 };
-                break;
-            case "left":
-                this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col === 0 ? this._focusedCell.col : this._focusedCell.col - 1 };
-                break;
-            case "up":
-                this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col };
-                break;
-            case "down":
-                this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
-                break;
-        }
-    }
-
-    @action
-    changeFocusedCellByIndex = (row: number, col: number): void => {
-        this._focusedCell = { row: row, col: col };
-    }
 
     @action
     setCellIsEditing = (isEditing: boolean): void => {
@@ -255,21 +205,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this._headerIsEditing = isEditing;
     }
 
-    // @action
-    // toggleKey = (key: string) => {
-    //     let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
-    //     if (list === undefined) {
-    //         this.props.Document.schemaColumns = list = new List<string>([key]);
-    //     } else {
-    //         const index = list.indexOf(key);
-    //         if (index === -1) {
-    //             list.push(key);
-    //         } else {
-    //             list.splice(index, 1);
-    //         }
-    //     }
-    // }
-
     //toggles preview side-panel of schema
     @action
     toggleExpander = () => {
@@ -323,6 +258,38 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         }
     }
 
+    @action
+    changeFocusedCellByDirection = (direction: string): void => {
+        switch (direction) {
+            case "tab":
+                if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) {
+                    this._focusedCell = { row: 0, col: 0 };
+                } else if (this._focusedCell.col + 1 === this.columns.length) {
+                    this._focusedCell = { row: this._focusedCell.row + 1, col: 0 };
+                } else {
+                    this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 };
+                }
+                break;
+            case "right":
+                this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 === this.columns.length ? this._focusedCell.col : this._focusedCell.col + 1 };
+                break;
+            case "left":
+                this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col === 0 ? this._focusedCell.col : this._focusedCell.col - 1 };
+                break;
+            case "up":
+                this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col };
+                break;
+            case "down":
+                this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
+                break;
+        }
+    }
+
+    @action
+    changeFocusedCellByIndex = (row: number, col: number): void => {
+        this._focusedCell = { row: row, col: col };
+    }
+
     @action
     makeDB = async () => {
         let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
@@ -400,10 +367,32 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         }
     }
 
-    // @action
-    // newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    //     this._newKeyName = e.currentTarget.value;
-    // }
+    @action
+    setColumns = (columns: string[]) => {
+        this.columns = columns;
+    }
+
+    reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => {
+        let columns = [...columnsValues];
+        let oldIndex = columns.indexOf(toMove);
+        let relIndex = columns.indexOf(relativeTo);
+        let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
+
+        if (oldIndex === newIndex) return;
+
+        columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
+        this.setColumns(columns);
+    }
+
+    @action
+    setColumnSort = (column: string, descending: boolean) => {
+        this._sortedColumns.set(column, {id: column, desc: descending});
+    }
+
+    @action
+    removeColumnSort = (column: string) => {
+        this._sortedColumns.delete(column);
+    } 
 
     @computed
     get previewDocument(): Doc | undefined {
@@ -430,44 +419,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return Array.from(Object.keys(keys));
     }
 
-    // get documentKeysCheckList() {
-    //     const docs = DocListCast(this.props.Document[this.props.fieldKey]);
-    //     let keys: { [key: string]: boolean } = {};
-    //     // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
-    //     //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
-    //     //  invalidated and re-rendered.   This workaround will inquire all of the document fields before the options button is clicked.
-    //     //  then by the time the options button is clicked, all of the fields should be in place.  If a new field is added while this menu
-    //     //  is displayed (unlikely) it won't show up until something else changes.
-    //     //TODO Types
-    //     untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false))));
-
-    //     this.columns.forEach(key => keys[key] = true);
-    //     return Array.from(Object.keys(keys)).map(item =>
-    //         (<KeyToggle checked={keys[item]} key={item} keyName={item} toggle={this.toggleKey} />));
-    // }
-
-    // get tableOptionsPanel() {
-    //     return !this.props.active() ? (null) :
-    //         (<Flyout
-    //             anchorPoint={anchorPoints.RIGHT_TOP}
-    //             content={<div>
-    //                 <div id="schema-options-header"><h5><b>Options</b></h5></div>
-    //                 <div id="options-flyout-div">
-    //                     <h6 className="schema-options-subHeader">Preview Window</h6>
-    //                     <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />  Show Preview </div>
-    //                     <h6 className="schema-options-subHeader" >Displayed Columns</h6>
-    //                     <ul id="schema-col-checklist" >
-    //                         {this.documentKeysCheckList}
-    //                     </ul>
-    //                     <input value={this._newKeyName} onChange={this.newKeyChange} />
-    //                     <button onClick={this.addColumn}><FontAwesomeIcon style={{ color: "white" }} icon="plus" size="lg" /></button>
-    //                 </div>
-    //             </div>
-    //             }>
-    //             <button id="schemaOptionsMenuBtn" ><FontAwesomeIcon style={{ color: "white" }} icon="cog" size="sm" /></button>
-    //         </Flyout>);
-    // }
-
     @computed
     get reactTable() {
         let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
@@ -481,6 +432,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             getTrProps={this.getTrProps}
             sortable={false}
             TrComponent={MovableRow}
+            sorted={Array.from(this._sortedColumns.values())}
         />;
     }
 
@@ -614,7 +566,13 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
         }
         return undefined;
     }
+
+    
     render() {
+
+            //                     <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />  Show Preview </div>
+
+
         let input = this.props.previewScript === undefined ? (null) :
             <div ref={this.createTarget}><input className="collectionSchemaView-input" value={this.props.previewScript} onChange={this.onPreviewScriptChange}
                 style={{ left: `calc(50% - ${Math.min(75, (this.props.Document ? this.PanelWidth() / 2 : 75))}px)` }} /></div>;
-- 
cgit v1.2.3-70-g09d2


From 17f53f604e0087615c2baff6cffa344771301b5e Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Fri, 19 Jul 2019 13:49:37 -0400
Subject: fixed nto being able to edit when column menu flyout is closed bug

---
 .../views/collections/CollectionSchemaHeaders.tsx  | 39 +++++++++++-----------
 .../views/collections/CollectionSchemaView.tsx     | 16 ++++++---
 2 files changed, 31 insertions(+), 24 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 6002d64ce..316b3f0ff 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -8,6 +8,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Flyout, anchorPoints } from "../DocumentDecorations";
 import { ColumnType } from "./CollectionSchemaView";
 import { emptyFunction } from "../../../Utils";
+import { contains } from "typescript-collections/dist/lib/arrays";
 
 library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn);
 
@@ -109,27 +110,25 @@ export interface ColumnMenuProps {
 @observer
 export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> {
     @observable private _isOpen: boolean = false;
-    // @observable private _node : HTMLDivElement | null = null;
-    @observable private _node = React.createRef<HTMLDivElement>();
+    @observable private _node : HTMLDivElement | null = null;
+    // @observable private _node = React.createRef<HTMLDivElement>();
+    @observable private _test = "test";
 
     componentDidMount() {
-        document.addEventListener("pointerdown", this.onPointerDown);
+        document.addEventListener("pointerdown", this.detectClick);
         console.log("did mount", this._node);
     }
 
     componentWillUnmount() {
-        document.removeEventListener("pointerdown", this.onPointerDown);
+        document.removeEventListener("pointerdown", this.detectClick);
     }
 
-    onPointerDown (e: PointerEvent) {
-        console.log("pointer down", this._node);
-        if (this._node ) {
-            // && this._node.contains(e.target as Node)
-            console.log("CLICKED INSNIDE");
+    detectClick = (e: PointerEvent): void => {
+        console.log("click", this);
+        if (this._node && this._node.contains(e.target as Node)) {
         } else {
-            console.log("CLICKED OUTSIDE");
-            // console.log(this._node);
-            // console.log(e.target as Node);
+            this._isOpen = false;
+            this.props.setIsEditing(false);
         }
     }
 
@@ -145,13 +144,13 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         this.props.setColumnType(this.props.keyValue, type);
     }
 
-    // @action
-    // setNode = (node: HTMLDivElement): void => {
-    //     if (node) {
-    //         this._node = node;
-    //         console.log("set node to ", this._node);
-    //     }
-    // }
+    @action
+    setNode = (node: HTMLDivElement): void => {
+        if (node) {
+            this._node = node;
+            console.log("set node to ", this._node);
+        }
+    }
 
     renderTypes = () => {
         if (this.props.typeConst) return <></>;
@@ -223,7 +222,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
     render() {
         console.log("render", this._node);
         return (
-            <div className="collectionSchema-header-menu" ref={this._node}>
+            <div className="collectionSchema-header-menu" ref={this.setNode}>
                 <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderContent()}>
                     <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div>
                 </ Flyout >
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 10b1e895d..ffc9d7d09 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -480,10 +480,20 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this.previewScript = script;
     }
 
+    @computed
+    get schemaToolbar() {
+        return (
+            <div className="collectionSchemaView-toolbar">
+                <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />Show Preview</div>
+            </div>
+        );
+    }
+
     render() {
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
+                {this.schemaToolbar}
                 {this.reactTable}
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
@@ -492,6 +502,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         );
     }
 }
+
+
 interface CollectionSchemaPreviewProps {
     Document?: Doc;
     DataDocument?: Doc;
@@ -569,10 +581,6 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
 
     
     render() {
-
-            //                     <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />  Show Preview </div>
-
-
         let input = this.props.previewScript === undefined ? (null) :
             <div ref={this.createTarget}><input className="collectionSchemaView-input" value={this.props.previewScript} onChange={this.onPreviewScriptChange}
                 style={{ left: `calc(50% - ${Math.min(75, (this.props.Document ? this.PanelWidth() / 2 : 75))}px)` }} /></div>;
-- 
cgit v1.2.3-70-g09d2


From e1b11d49cc73ae9cfe85c5225537d681bbc976cc Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Fri, 19 Jul 2019 16:10:16 -0400
Subject: changed add col button to immediately add new column

---
 .../views/collections/CollectionSchemaCells.tsx    |  4 +-
 .../views/collections/CollectionSchemaHeaders.tsx  | 62 +++++++++++-----------
 .../views/collections/CollectionSchemaView.scss    |  4 ++
 .../views/collections/CollectionSchemaView.tsx     | 40 ++++++++++----
 4 files changed, 67 insertions(+), 43 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 5b40032eb..0307bb83e 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -31,7 +31,7 @@ export interface CellProps {
     renderDepth: number;
     addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
     moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
-    isFocused: boolean;
+    isFocused: boolean; 
     changeFocusedCellByDirection: (direction: string) => void;
     changeFocusedCellByIndex: (row: number, col: number) => void;
     setIsEditing: (isEditing: boolean) => void;
@@ -229,4 +229,4 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell {
             </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 316b3f0ff..5f8037fbf 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -29,7 +29,7 @@ export interface HeaderProps {
 export class CollectionSchemaHeader extends React.Component<HeaderProps> {
     render() {
         let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" :
-            this.props.keyType === ColumnType.Checkbox ? "check-square" : this.props.keyType === ColumnType.Boolean ? "toggle-on" : "align-justify";
+            this.props.keyType === ColumnType.Boolean ? "check-square" : "align-justify";
 
         return (
             <div className="collectionSchemaView-header" >
@@ -56,10 +56,11 @@ export class CollectionSchemaHeader extends React.Component<HeaderProps> {
 
 
 export interface AddColumnHeaderProps {
-    possibleKeys: string[];
-    existingKeys: string[];
-    onSelect: (oldKey: string, newKey: string, addnew: boolean) => void;
-    setIsEditing: (isEditing: boolean) => void;
+    // possibleKeys: string[];
+    // existingKeys: string[];
+    // onSelect: (oldKey: string, newKey: string, addnew: boolean) => void;
+    // setIsEditing: (isEditing: boolean) => void;
+    createColumn: () => void;
 }
 
 @observer
@@ -67,24 +68,26 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe
     render() {
         let addButton = <button><FontAwesomeIcon icon="plus" size="sm" /></button>;
         return (
-            <div className="collectionSchemaView-header-addColumn" >
-                <CollectionSchemaColumnMenu
-                    keyValue=""
-                    possibleKeys={this.props.possibleKeys}
-                    existingKeys={this.props.existingKeys}
-                    keyType={ColumnType.Any}
-                    typeConst={true}
-                    menuButtonContent={addButton}
-                    addNew={true}
-                    onSelect={this.props.onSelect}
-                    setIsEditing={this.props.setIsEditing}
-                    deleteColumn={action(emptyFunction)}
-                    onlyShowOptions={true}
-                    setColumnType={action(emptyFunction)}
-                    setColumnSort={action(emptyFunction)}
-                    removeColumnSort={action(emptyFunction)}
-                />
-            </div>
+            <button onClick={() => this.props.createColumn()}><FontAwesomeIcon icon="plus" size="sm" /></button>
+            // <div className="collectionSchemaView-header-addColumn" >
+            //     <CollectionSchemaColumnMenu
+            //         keyValue=""
+            //         possibleKeys={this.props.possibleKeys}
+            //         existingKeys={this.props.existingKeys}
+            //         keyType={ColumnType.Any}
+            //         typeConst={true}
+            //         menuButtonContent={addButton}
+            //         addNew={true}
+            //         onSelect={this.props.onSelect}
+            //         setIsEditing={this.props.setIsEditing}
+            //         deleteColumn={action(emptyFunction)}
+            //         onlyShowOptions={true}
+            //         setColumnType={action(emptyFunction)}
+            //         setColumnSort={action(emptyFunction)}
+            //         removeColumnSort={action(emptyFunction)}
+            //         anchorPoint={anchorPoints.TOP_RIGHT}
+            //     />
+            // </div>
         );
     }
 }
@@ -106,6 +109,7 @@ export interface ColumnMenuProps {
     setColumnType: (key: string, type: ColumnType) => void;
     setColumnSort: (key: string, desc: boolean) => void;
     removeColumnSort: (key: string) => void;
+    anchorPoint?: any;
 }
 @observer
 export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> {
@@ -116,7 +120,6 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
 
     componentDidMount() {
         document.addEventListener("pointerdown", this.detectClick);
-        console.log("did mount", this._node);
     }
 
     componentWillUnmount() {
@@ -124,7 +127,6 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
     }
 
     detectClick = (e: PointerEvent): void => {
-        console.log("click", this);
         if (this._node && this._node.contains(e.target as Node)) {
         } else {
             this._isOpen = false;
@@ -148,7 +150,6 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
     setNode = (node: HTMLDivElement): void => {
         if (node) {
             this._node = node;
-            console.log("set node to ", this._node);
         }
     }
 
@@ -167,10 +168,10 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                     <button title="String" className={this.props.keyType === ColumnType.String ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.String)}>
                         <FontAwesomeIcon icon={"font"} size="sm" />
                         </button>
-                    <button title="Boolean" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}>
+                    {/* <button title="Boolean" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}>
                         <FontAwesomeIcon icon={"toggle-on"} size="sm" />
-                        </button>
-                    <button title="Checkbox" className={this.props.keyType === ColumnType.Checkbox ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Checkbox)}>
+                        </button> */}
+                    <button title="Checkbox" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}>
                         <FontAwesomeIcon icon={"check-square"} size="sm" />
                         </button>
                 </div>
@@ -220,10 +221,9 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
     }
 
     render() {
-        console.log("render", this._node);
         return (
             <div className="collectionSchema-header-menu" ref={this.setNode}>
-                <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderContent()}>
+                <Flyout anchorPoint={this.props.anchorPoint ? this.props.anchorPoint : anchorPoints.TOP_CENTER} content={this.renderContent()}>
                     <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div>
                 </ Flyout >
             </div>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 4ae9628a9..47947829e 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -95,6 +95,10 @@
         padding: 3px 7px;
         font-size: 13px;
         text-align: center;
+        
+        &:last-child {
+            overflow: visible;
+        }
     }
 
     .rt-tbody {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ffc9d7d09..02c1ec082 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -32,7 +32,7 @@ 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 } from "./CollectionSchemaCells";
+import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell } from "./CollectionSchemaCells";
 import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC";
 
 library.add(faCog);
@@ -44,8 +44,8 @@ export enum ColumnType {
     Number,
     String,
     Boolean,
-    // Doc,
-    Checkbox
+    Doc,
+    // Checkbox
 }
 // this map should be used for keys that should have a const type of value
 const columnTypes: Map<string, ColumnType> = new Map([
@@ -125,23 +125,28 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     let colType = this.getColumnType(col);
                     if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/>;
                     if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/>;
-                    if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} />;
-                    if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} />;
+                    // if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} />;
+                    // if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} />;
+                    if (colType === ColumnType.Boolean) return <CollectionSchemaCheckboxCell {...props} />;
+                    if (colType === ColumnType.Doc) return <CollectionSchemaDocCell {...props} />;
                     return <CollectionSchemaCell {...props}/>;
                 }
             };
-        }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult<Field>, id: string, Cell: (rowProps: CellInfo) => JSX.Element}[];
+        }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult<Field>, id: string, Cell: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean}[];
 
         cols.push({
             Header: <CollectionSchemaAddColumnHeader
-                possibleKeys={possibleKeys}
-                existingKeys={this.columns}
-                onSelect={this.changeColumns}
-                setIsEditing={this.setHeaderIsEditing}
+                createColumn={this.createColumn}
+                // possibleKeys={possibleKeys}
+                // existingKeys={this.columns}
+                // onSelect={this.changeColumns}
+                // setIsEditing={this.setHeaderIsEditing}
             />,
             accessor: (doc: Doc) => 0,
             id: "add",
             Cell: (rowProps: CellInfo) => <></>,
+            width: 45,
+            resizable: false
         });
 
         return cols;
@@ -311,6 +316,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         }
     }
 
+    @action
+    createColumn = () => {  
+        let index = 0;
+        let found = this.columns.findIndex(col => col.toUpperCase() === "New field".toUpperCase()) > -1;
+        if (!found) {
+            this.columns.push("New field");
+            return;
+        }
+        while (found) {
+            index ++;
+            found = this.columns.findIndex(col => col.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
+        }
+        this.columns.push("New field (" + index + ")");
+    }
+
     @action
     addColumn = () => {
         this.columns.push(this._newKeyName);
-- 
cgit v1.2.3-70-g09d2


From fa37c6f8e9947b7f536d7ff7372c9f1025a3926d Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Fri, 19 Jul 2019 17:02:17 -0400
Subject: merge

---
 .../views/collections/CollectionSchemaCells.tsx    |  2 +-
 .../views/collections/CollectionSchemaView.scss    |  1 +
 .../views/collections/CollectionSchemaView.tsx     | 22 ++++++++++++++++++++--
 3 files changed, 22 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 31a9baa11..7c82ed720 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -42,7 +42,7 @@ export interface CellProps {
 export class CollectionSchemaCell extends React.Component<CellProps> {
     @observable protected _isEditing: boolean = false;
     protected _focusRef = React.createRef<HTMLDivElement>();
-    protected _document = this.props.rowProps.original;
+    protected _document: Doc = this.props.rowProps.original;
 
     componentDidMount() {
         if (this._focusRef.current) {
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 045994751..2134362ce 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -108,6 +108,7 @@
     .rt-tr-group {
         direction: ltr;
         max-height: $MAX_ROW_HEIGHT;
+        // for sub comp
 
         &:nth-child(even) {
             background-color: $light-color;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 02c1ec082..7c7309a4a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -4,7 +4,7 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
 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 } from "react-table";
+import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column, RowInfo } from "react-table";
 import "react-table/react-table.css";
 import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils";
 import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc";
@@ -132,7 +132,20 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     return <CollectionSchemaCell {...props}/>;
                 }
             };
-        }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult<Field>, id: string, Cell: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean}[];
+        }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult<Field>, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null}[];
+
+        cols.push({
+            expander: true,
+            Header: "",
+            width: 45,
+            Expander: (rowInfo) => {
+                if (rowInfo.original.type === "collection") {
+                    return <div>+</div>;
+                } else {
+                    return null;
+                }
+            }
+        });
 
         cols.push({
             Header: <CollectionSchemaAddColumnHeader
@@ -149,6 +162,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             resizable: false
         });
 
+        // SubComponent={row => row.original.type === "collection" && <div>SUB</div>}
+
         return cols;
     }
 
@@ -453,7 +468,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             sortable={false}
             TrComponent={MovableRow}
             sorted={Array.from(this._sortedColumns.values())}
+            SubComponent={row => row.original.type === "collection" && <div>this is the sub component</div>}
         />;
+
+
     }
 
     @computed
-- 
cgit v1.2.3-70-g09d2


From e81cf9407966612e25b944addbc8d2a08300d0bb Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Mon, 22 Jul 2019 11:38:55 -0400
Subject: editing + nav on schema only occur when that schemaview is selected

---
 .../views/collections/CollectionSchemaCells.tsx    |  3 +
 .../views/collections/CollectionSchemaHeaders.tsx  |  8 ++-
 .../views/collections/CollectionSchemaView.scss    | 10 ++-
 .../views/collections/CollectionSchemaView.tsx     | 80 ++++++++++++++--------
 4 files changed, 67 insertions(+), 34 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 91bd0453e..55185e30e 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -51,6 +51,9 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         if (this._focusRef.current) {
             if (this.props.isFocused) {
                 this._focusRef.current.className += " focused";
+                if (!this.props.isEditable) {
+                    this._focusRef.current.className += " inactive";
+                }
             } else {
                 this._focusRef.current.className = "collectionSchemaView-cellWrapper";
             }
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index df078eca5..3a57cd306 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -9,8 +9,9 @@ import { Flyout, anchorPoints } from "../DocumentDecorations";
 import { ColumnType } from "./CollectionSchemaView";
 import { emptyFunction } from "../../../Utils";
 import { contains } from "typescript-collections/dist/lib/arrays";
+import { faFile } from "@fortawesome/free-regular-svg-icons";
 
-library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn);
+library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile);
 
 export interface HeaderProps {
     keyValue: string;
@@ -29,7 +30,7 @@ export interface HeaderProps {
 export class CollectionSchemaHeader extends React.Component<HeaderProps> {
     render() {
         let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" :
-            this.props.keyType === ColumnType.Boolean ? "check-square" : "align-justify";
+            this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType ===  ColumnType.Doc ? "file" : "align-justify";
 
         return (
             <div className="collectionSchemaView-header" >
@@ -145,6 +146,9 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                     <button title="Checkbox" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}>
                         <FontAwesomeIcon icon={"check-square"} size="sm" />
                         </button>
+                    <button title="Document" className={this.props.keyType === ColumnType.Doc ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Doc)}>
+                        <FontAwesomeIcon icon={"file"} size="sm" />
+                    </button>
                 </div>
             </div>
         );
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 2134362ce..e511bc1bd 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -8,8 +8,9 @@
     box-sizing: border-box;
     position: absolute;
     width: 100%;
-    height: 100%;
-    overflow: hidden;
+    height: calc(100% - 25px);
+    // overflow: hidden;
+    overflow-x: scroll;
 
     .collectionSchemaView-previewRegion {
         position: relative;
@@ -304,6 +305,11 @@
             border: none;
             background-color: yellow;
         }
+
+        &.inactive {
+            // border: 2px solid rgba(255, 255, 0, 0.4);
+            border: none;
+        }
     }
 }
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7c7309a4a..ea09926d4 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -34,6 +34,7 @@ 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";
 
 library.add(faCog);
 library.add(faPlus);
@@ -60,7 +61,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     private _startPreviewWidth = 0;
     private DIVIDER_WIDTH = 4;
 
-    @observable _selectedIndex = 0;
+    // @observable _selectedIndex = 0;
     @observable _columnsPercentage = 0;
     @observable _keys: string[] = [];
     @observable _newKeyName: string = "";
@@ -69,6 +70,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable _cellIsEditing: boolean = false;
     @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0};
     @observable _sortedColumns: Map<string, {id: string, desc: boolean}> = new Map();
+    @observable private _node : HTMLDivElement | null = null;
+    // @observable _schemaIsFocused: boolean = 
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
@@ -81,7 +84,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         let cols = this.columns.map(col => {
             let focusedRow = this._focusedCell.row;
             let focusedCol = this._focusedCell.col;
-            let isEditable = !this._headerIsEditing;
+            let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false;
+            let isEditable = !this._headerIsEditing && (isSelected);// || BoolCast(this.props.Document.libraryBrush));
+            console.log(BoolCast(this.props.Document.libraryBrush), isSelected);
+
             let header = <CollectionSchemaHeader 
                 keyValue={col}
                 possibleKeys={possibleKeys}
@@ -130,22 +136,23 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     if (colType === ColumnType.Boolean) return <CollectionSchemaCheckboxCell {...props} />;
                     if (colType === ColumnType.Doc) return <CollectionSchemaDocCell {...props} />;
                     return <CollectionSchemaCell {...props}/>;
-                }
+                },
+                minWidth: 200,
             };
-        }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult<Field>, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null}[];
-
-        cols.push({
-            expander: true,
-            Header: "",
-            width: 45,
-            Expander: (rowInfo) => {
-                if (rowInfo.original.type === "collection") {
-                    return <div>+</div>;
-                } else {
-                    return null;
-                }
-            }
-        });
+        }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult<Field>, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[];
+
+        // cols.push({
+        //     expander: true,
+        //     Header: "",
+        //     width: 45,
+        //     Expander: (rowInfo) => {
+        //         if (rowInfo.original.type === "collection") {
+        //             return <div>+</div>;
+        //         } else {
+        //             return null;
+        //         }
+        //     }
+        // });
 
         cols.push({
             Header: <CollectionSchemaAddColumnHeader
@@ -178,7 +185,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     //             }
     //         }
     //     }
-    //     return this.props.Document;
+    //     return this.props.Document;  
     // }
 
     componentDidMount() {
@@ -199,14 +206,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before),
             moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc),
             rowInfo, 
-            onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
-                that.props.select(e.ctrlKey);
-                that._selectedIndex = rowInfo.index;
-
-                if (handleOriginal) {
-                    handleOriginal();
-                }
-            }),
+            // onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
+            //     that.props.select(e.ctrlKey);
+            //     that._selectedIndex = rowInfo.index;
+
+            //     if (handleOriginal) {
+            //         handleOriginal();
+            //     }
+            // }),
         };
     }
 
@@ -215,6 +222,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         super.CreateDropTarget(ele);
     }
 
+    // detectClick = (e: PointerEvent): void => {
+    //     if (this._node && this._node.contains(e.target as Node)) {
+    //     } else {
+    //         this._isOpen = false;
+    //         this.props.setIsEditing(false);
+    //     }
+    // }
+
     @action
     setCellIsEditing = (isEditing: boolean): void => {
         this._cellIsEditing = isEditing;
@@ -272,7 +287,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
 
     onKeyDown = (e: KeyboardEvent): void => {
-        if (!this._cellIsEditing && !this._headerIsEditing) {
+        let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false;
+        if (!this._cellIsEditing && !this._headerIsEditing && isSelected) {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
         }
@@ -431,7 +447,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @computed
     get previewDocument(): Doc | undefined {
-        const selected = this.childDocs.length > this._selectedIndex ? this.childDocs[this._selectedIndex] : undefined;
+        let selectedIndex = this._focusedCell.row;
+        console.log("preview", selectedIndex);
+        const selected = this.childDocs.length > selectedIndex ? this.childDocs[selectedIndex] : undefined;
         let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
         return pdc;
     }
@@ -468,7 +486,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             sortable={false}
             TrComponent={MovableRow}
             sorted={Array.from(this._sortedColumns.values())}
-            SubComponent={row => row.original.type === "collection" && <div>this is the sub component</div>}
+            // SubComponent={row => row.original.type === "collection" && <div>this is the sub component</div>}
         />;
 
 
@@ -529,14 +547,16 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     render() {
         return (
+            <>
+            {this.schemaToolbar}
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
-                {this.schemaToolbar}
                 {this.reactTable}
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
                 {/* {this.tableOptionsPanel} */}
             </div>
+            </>
         );
     }
 }
-- 
cgit v1.2.3-70-g09d2


From 8515b6957f075f8ae7e88243ab5a4c7cb8fff3b6 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Mon, 22 Jul 2019 14:49:57 -0400
Subject: removed fixed row height

---
 .../views/collections/CollectionSchemaCells.tsx    | 103 +++++++++++----------
 .../CollectionSchemaMovableTableHOC.tsx            |   5 +-
 .../views/collections/CollectionSchemaView.scss    |  67 +++++++++-----
 .../views/collections/CollectionSchemaView.tsx     |  45 +++++----
 4 files changed, 126 insertions(+), 94 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 55185e30e..2dd3eeff4 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -20,6 +20,7 @@ import { CollectionView } from "./CollectionView";
 import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_fields/Types";
 import { Docs } from "../../documents/Documents";
 import { DocumentContentsView } from "../nodes/DocumentContentsView";
+import { SelectionManager } from "../../util/SelectionManager";
 
 
 export interface CellProps {
@@ -118,6 +119,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
     }
 
     renderCellWithType(type: string | undefined) {
+        let dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+
         let props: FieldViewProps = {
             Document: this.props.rowProps.original,
             DataDoc: this.props.rowProps.original,
@@ -136,10 +139,19 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             PanelWidth: returnZero,
             addDocTab: this.props.addDocTab,
         };
+
         let onItemDown = (e: React.PointerEvent) => {
             SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
                 this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
         };
+        let onPointerEnter = (e: React.PointerEvent): void => {
+            if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) {
+                dragRef!.current!.className = "doc-drag-over";
+            }
+        };
+        let onPointerLeave = (e: React.PointerEvent): void => {
+            dragRef!.current!.className = "";
+        };
 
         let field = props.Document[props.fieldKey];
         let contents: any = "incorrect type";
@@ -153,40 +165,42 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         }
 
         return (
-            <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
-                <div className="collectionSchemaView-cellContents" ref={this.dropRef} onPointerDown={onItemDown} key={props.Document[Id]}>
-                    <EditableView
-                        editing={this._isEditing}
-                        isEditingCallback={this.isEditingCallback}
-                        display={"inline"}
-                        contents={contents}
-                        height={Number(MAX_ROW_HEIGHT)}
-                        GetValue={() => {
-                            let field = props.Document[props.fieldKey];
-                            if (Field.IsField(field)) {
-                                return Field.toScriptString(field);
+            <div className="" ref={dragRef} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
+                <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+                    <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef: null} onPointerDown={onItemDown} key={props.Document[Id]}>
+                        <EditableView
+                            editing={this._isEditing}
+                            isEditingCallback={this.isEditingCallback}
+                            display={"inline"}
+                            contents={contents}
+                            height={Number(MAX_ROW_HEIGHT)}
+                            GetValue={() => {
+                                let field = props.Document[props.fieldKey];
+                                if (Field.IsField(field)) {
+                                    return Field.toScriptString(field);
+                                }
+                                return "";
                             }
-                            return "";
-                        }
-                        }
-                        SetValue={(value: string) => {
-                            let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
-                            if (!script.compiled) {
-                                return false;
                             }
-                            return this.applyToDoc(props.Document, script.run);
-                        }}
-                        OnFillDown={async (value: string) => {
-                            let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
-                            if (!script.compiled) {
-                                return;
-                            }
-                            const run = script.run;
-                            //TODO This should be able to be refactored to compile the script once
-                            const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-                            val && val.forEach(doc => this.applyToDoc(doc, run));
-                        }} />
-                </div >
+                            SetValue={(value: string) => {
+                                let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
+                                if (!script.compiled) {
+                                    return false;
+                                }
+                                return this.applyToDoc(props.Document, script.run);
+                            }}
+                            OnFillDown={async (value: string) => {
+                                let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
+                                if (!script.compiled) {
+                                    return;
+                                }
+                                const run = script.run;
+                                //TODO This should be able to be refactored to compile the script once
+                                const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
+                                val && val.forEach(doc => this.applyToDoc(doc, run));
+                            }} />
+                    </div >
+                </div>
             </div>
         );
     }
@@ -217,6 +231,13 @@ export class CollectionSchemaStringCell extends CollectionSchemaCell {
     }
 }
 
+@observer
+export class CollectionSchemaDocCell extends CollectionSchemaCell {
+    render() {
+        return this.renderCellWithType("document");
+    }
+}
+
 @observer
 export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
     @observable private _isChecked: boolean = typeof this.props.rowProps.original[this.props.rowProps.column.id as string] === "boolean" ? BoolCast(this.props.rowProps.original[this.props.rowProps.column.id as string]) : false;
@@ -245,21 +266,3 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
         );
     }
 }
-
-@observer
-export class CollectionSchemaDocCell extends CollectionSchemaCell {
-    render() {
-        return this.renderCellWithType("document");
-        // let reference = React.createRef<HTMLDivElement>();
-        // let onItemDown = (e: React.PointerEvent) => {
-        //     // (!this.props.CollectionView.props.isSelected() ? undefined :
-        //     //     SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
-        // };
-        // return (
-        //     <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
-        //         <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={this._document[Id]} ref={reference}>
-        //         </div >
-        //     </div>
-        // );
-    }
-}
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 3a61881a7..8ed71d70f 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -105,6 +105,7 @@ export interface MovableRowProps {
     ScreenToLocalTransform: () => Transform;
     addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
     moveDoc: DragManager.MoveFunction;
+    rowFocused: boolean;
 }
 
 export class MovableRow extends React.Component<MovableRowProps> {
@@ -178,8 +179,10 @@ export class MovableRow extends React.Component<MovableRowProps> {
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc);
 
+        console.log("row focused", this.props.rowFocused);
+
         return (
-            <div className="collectionSchema-row" ref={this.createRowDropTarget}>
+            <div className={this.props.rowFocused ? "collectionSchema-row row-focused" : "collectionSchema-row"} ref={this.createRowDropTarget}>
                 <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
                     <div className="row-dragger" ref={reference} onPointerDown={onItemDown}>
                         <ReactTableDefaults.TrComponent>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index e511bc1bd..ef93e381b 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -11,6 +11,7 @@
     height: calc(100% - 25px);
     // overflow: hidden;
     overflow-x: scroll;
+    border: none;
 
     .collectionSchemaView-previewRegion {
         position: relative;
@@ -70,10 +71,11 @@
 
     .rt-thead {
         &.-header {
-            background: $intermediate-color;
-            color: $light-color;
+            // background: $intermediate-color;
+            // color: $light-color;
             font-size: 12px;
             height: 30px;
+            border: 1px solid $intermediate-color;
         }
 
         .rt-resizable-header {
@@ -89,11 +91,14 @@
             height: 100%;
             overflow: visible;
         }
+
+        .rt-th {
+            padding: 0;
+        }
     }
 
     .rt-th {
-        max-height: $MAX_ROW_HEIGHT;
-        padding: 3px 7px;
+        // max-height: $MAX_ROW_HEIGHT;
         font-size: 13px;
         text-align: center;
         
@@ -108,16 +113,17 @@
 
     .rt-tr-group {
         direction: ltr;
-        max-height: $MAX_ROW_HEIGHT;
+        flex: 0 1 auto;
+        // max-height: $MAX_ROW_HEIGHT;
         // for sub comp
 
-        &:nth-child(even) {
-            background-color: $light-color;
-        }
+        // &:nth-child(even) {
+        //     background-color: $light-color;
+        // }
     
-        &:nth-child(odd) {
-            background-color: $light-color-secondary;
-        }
+        // &:nth-child(odd) {
+        //     background-color: $light-color-secondary;
+        // }
 
         &:last-child {
             border-bottom: $intermediate-color;
@@ -128,13 +134,13 @@
 
     .rt-tr {
         width: 100%;
-        height: $MAX_ROW_HEIGHT;
+        // height: $MAX_ROW_HEIGHT;
     }
 
     .rt-td {
         border-width: 1px;
         border-right-color: $intermediate-color;
-        max-height: $MAX_ROW_HEIGHT;
+        // max-height: $MAX_ROW_HEIGHT;
         padding: 0;
         font-size: 13px;
         text-align: center;
@@ -184,6 +190,7 @@
 
 .collectionSchemaView-header {
     height: 100%;
+    color: $intermediate-color;
 
     .collectionSchema-header-menu {
         height: 100%;
@@ -223,10 +230,6 @@
         position: relative;
         max-width: 175px;
 
-        // .keys-search {
-
-        // }
-
         .keys-options-wrapper {
             width: 100%;
             max-height: 150px;
@@ -261,17 +264,18 @@
 }
 
 .collectionSchema-row {
-    height: $MAX_ROW_HEIGHT;
-    // display: flex;
+    // height: $MAX_ROW_HEIGHT;
+
+    &.row-focused {
+        background-color: $light-color-secondary;
+    }
 
     .row-dragger {
-        height: $MAX_ROW_HEIGHT;
+        // height: $MAX_ROW_HEIGHT;
     }
 
     .collectionSchema-row-wrapper {
-        max-height: $MAX_ROW_HEIGHT;
-        // width: 100%;
-        // border: 1px solid lightgray;
+        // max-height: $MAX_ROW_HEIGHT;
 
         &.row-above {
             border-top: 1px solid red;
@@ -287,8 +291,6 @@
 
 
 .collectionSchemaView-cellWrapper {
-    // height: $MAX_ROW_HEIGHT;
-    // background-color: red;
     height: 100%;
     padding: 4px;
 
@@ -311,6 +313,21 @@
             border: none;
         }
     }
+
+    p {
+        width: 100%;
+        height: 100%;
+        word-wrap: break-word;
+    }
+}
+
+.doc-drag-over {
+    background-color: red;
+}
+
+.collectionSchemaView-toolbar {
+    display: flex;
+    justify-content: flex-end;
 }
 
 #preview-schema-checkbox-div {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ea09926d4..a1251b028 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -81,6 +81,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
+        let columns: Column<Doc>[] = [
+            {
+            expander: true,
+            Header: "",
+            width: 45,
+            Expander: (rowInfo) => {
+                if (rowInfo.original.type === "collection") {
+                    return <div>+</div>;
+                } else {
+                    return null;
+                }
+            }
+        }
+        ];
+        
         let cols = this.columns.map(col => {
             let focusedRow = this._focusedCell.row;
             let focusedCol = this._focusedCell.col;
@@ -139,22 +154,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 },
                 minWidth: 200,
             };
-        }) as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult<Field>, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[];
-
-        // cols.push({
-        //     expander: true,
-        //     Header: "",
-        //     width: 45,
-        //     Expander: (rowInfo) => {
-        //         if (rowInfo.original.type === "collection") {
-        //             return <div>+</div>;
-        //         } else {
-        //             return null;
-        //         }
-        //     }
-        // });
-
-        cols.push({
+        });// as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult<Field>, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[];
+        columns.push(...cols);
+
+        columns.push({
             Header: <CollectionSchemaAddColumnHeader
                 createColumn={this.createColumn}
                 // possibleKeys={possibleKeys}
@@ -171,7 +174,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
         // SubComponent={row => row.original.type === "collection" && <div>SUB</div>}
 
-        return cols;
+        return columns;
     }
 
     // onHeaderDrag = (columnName: string) => {
@@ -201,11 +204,17 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         if (!rowInfo) {
             return {};
         }
+        let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false;
         return {
             ScreenToLocalTransform: this.props.ScreenToLocalTransform,
             addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before),
             moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc),
             rowInfo, 
+            rowFocused: !this._headerIsEditing && isSelected && rowInfo.index === this._focusedCell.row,
+            // style: {
+            //     background: rowInfo.index === this._focusedCell.row ? "lightGray" : "white",
+            //     //color: rowInfo.index === this._selectedIndex ? "white" : "black"
+            // }
             // onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
             //     that.props.select(e.ctrlKey);
             //     that._selectedIndex = rowInfo.index;
@@ -486,7 +495,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             sortable={false}
             TrComponent={MovableRow}
             sorted={Array.from(this._sortedColumns.values())}
-            // SubComponent={row => row.original.type === "collection" && <div>this is the sub component</div>}
+            SubComponent={row => row.original.type === "collection" && <div>this is the sub component</div>}
         />;
 
 
-- 
cgit v1.2.3-70-g09d2


From d3edc59402efb5d8ada602305a95a7a3a7f0ba95 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Mon, 22 Jul 2019 17:08:46 -0400
Subject: can have expanded collection in schema

---
 .../CollectionSchemaMovableTableHOC.tsx            |  2 -
 .../views/collections/CollectionSchemaView.scss    |  9 ++-
 .../views/collections/CollectionSchemaView.tsx     | 93 ++++++++++------------
 3 files changed, 51 insertions(+), 53 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 8ed71d70f..db60e657a 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -179,8 +179,6 @@ export class MovableRow extends React.Component<MovableRowProps> {
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc);
 
-        console.log("row focused", this.props.rowFocused);
-
         return (
             <div className={this.props.rowFocused ? "collectionSchema-row row-focused" : "collectionSchema-row"} ref={this.createRowDropTarget}>
                 <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index ef93e381b..4b20e8241 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -6,9 +6,9 @@
     border-style: solid;
     border-radius: $border-radius;
     box-sizing: border-box;
-    position: absolute;
+    // position: absolute;
     width: 100%;
-    height: calc(100% - 25px);
+    // height: calc(100% - 25px);
     // overflow: hidden;
     overflow-x: scroll;
     border: none;
@@ -333,4 +333,9 @@
 #preview-schema-checkbox-div {
     margin-left: 20px;
     font-size: 12px;
+}
+
+.sub {
+    padding: 20px;
+    background-color: red;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a1251b028..25e90a25e 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -61,7 +61,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     private _startPreviewWidth = 0;
     private DIVIDER_WIDTH = 4;
 
-    // @observable _selectedIndex = 0;
     @observable _columnsPercentage = 0;
     @observable _keys: string[] = [];
     @observable _newKeyName: string = "";
@@ -70,8 +69,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable _cellIsEditing: boolean = false;
     @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0};
     @observable _sortedColumns: Map<string, {id: string, desc: boolean}> = new Map();
+    @observable _openCollections: Array<Doc> = [];
     @observable private _node : HTMLDivElement | null = null;
-    // @observable _schemaIsFocused: boolean = 
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
@@ -81,27 +80,30 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
-        let columns: Column<Doc>[] = [
-            {
-            expander: true,
-            Header: "",
-            width: 45,
-            Expander: (rowInfo) => {
-                if (rowInfo.original.type === "collection") {
-                    return <div>+</div>;
-                } else {
-                    return null;
+        let columns: Column<Doc>[] = [];
+
+        if (this.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) {
+            columns.push(
+                {
+                    expander: true,
+                    Header: "",
+                    width: 45,
+                    Expander: (rowInfo) => {
+                        if (rowInfo.original.type === "collection") {
+                            if (rowInfo.isExpanded) return <div onClick={() => this.onCloseCollection(rowInfo.original)}>-</div>;
+                            if (!rowInfo.isExpanded) return <div onClick={() => this.onExpandCollection(rowInfo.original)}>+</div>;
+                        } else {
+                            return null;
+                        }
+                    }
                 }
-            }
+            );
         }
-        ];
         
         let cols = this.columns.map(col => {
             let focusedRow = this._focusedCell.row;
             let focusedCol = this._focusedCell.col;
-            let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false;
-            let isEditable = !this._headerIsEditing && (isSelected);// || BoolCast(this.props.Document.libraryBrush));
-            console.log(BoolCast(this.props.Document.libraryBrush), isSelected);
+            let isEditable = !this._headerIsEditing && this.props.isSelected();// || BoolCast(this.props.Document.libraryBrush));
 
             let header = <CollectionSchemaHeader 
                 keyValue={col}
@@ -146,34 +148,23 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     let colType = this.getColumnType(col);
                     if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/>;
                     if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/>;
-                    // if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} />;
-                    // if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} />;
                     if (colType === ColumnType.Boolean) return <CollectionSchemaCheckboxCell {...props} />;
                     if (colType === ColumnType.Doc) return <CollectionSchemaDocCell {...props} />;
                     return <CollectionSchemaCell {...props}/>;
                 },
                 minWidth: 200,
             };
-        });// as {Header?: TableCellRenderer, accessor?: (doc: Doc) => FieldResult<Field>, id?: string, Cell?: (rowProps: CellInfo) => JSX.Element, width?: number, resizable?: boolean, expander?: boolean, Expander?: (rowInfo: RowInfo) => JSX.Element | null, minWidth?: number}[];
+        });
         columns.push(...cols);
 
         columns.push({
-            Header: <CollectionSchemaAddColumnHeader
-                createColumn={this.createColumn}
-                // possibleKeys={possibleKeys}
-                // existingKeys={this.columns}
-                // onSelect={this.changeColumns}
-                // setIsEditing={this.setHeaderIsEditing}
-            />,
+            Header: <CollectionSchemaAddColumnHeader createColumn={this.createColumn} />,
             accessor: (doc: Doc) => 0,
             id: "add",
             Cell: (rowProps: CellInfo) => <></>,
             width: 45,
             resizable: false
         });
-
-        // SubComponent={row => row.original.type === "collection" && <div>SUB</div>}
-
         return columns;
     }
 
@@ -204,25 +195,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         if (!rowInfo) {
             return {};
         }
-        let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false;
         return {
             ScreenToLocalTransform: this.props.ScreenToLocalTransform,
             addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before),
             moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc),
             rowInfo, 
-            rowFocused: !this._headerIsEditing && isSelected && rowInfo.index === this._focusedCell.row,
-            // style: {
-            //     background: rowInfo.index === this._focusedCell.row ? "lightGray" : "white",
-            //     //color: rowInfo.index === this._selectedIndex ? "white" : "black"
-            // }
-            // onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
-            //     that.props.select(e.ctrlKey);
-            //     that._selectedIndex = rowInfo.index;
-
-            //     if (handleOriginal) {
-            //         handleOriginal();
-            //     }
-            // }),
+            rowFocused: !this._headerIsEditing && this.props.isSelected() && rowInfo.index === this._focusedCell.row,
         };
     }
 
@@ -239,6 +217,17 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     //     }
     // }
 
+    @action
+    onExpandCollection = (collection: Doc): void => {
+        this._openCollections.push(collection);
+    }
+
+    @action
+    onCloseCollection = (collection: Doc): void => {
+        let index = this._openCollections.findIndex(col => col === collection);
+        if (index > -1) this._openCollections.splice(index, 1);
+    }
+
     @action
     setCellIsEditing = (isEditing: boolean): void => {
         this._cellIsEditing = isEditing;
@@ -296,8 +285,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
 
     onKeyDown = (e: KeyboardEvent): void => {
-        let isSelected = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document === this.props.Document : false;
-        if (!this._cellIsEditing && !this._headerIsEditing && isSelected) {
+        if (!this._cellIsEditing && !this._headerIsEditing && this.props.isSelected()) {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
         }
@@ -457,7 +445,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed
     get previewDocument(): Doc | undefined {
         let selectedIndex = this._focusedCell.row;
-        console.log("preview", selectedIndex);
         const selected = this.childDocs.length > selectedIndex ? this.childDocs[selectedIndex] : undefined;
         let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
         return pdc;
@@ -484,6 +471,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed
     get reactTable() {
         let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
+        let hasCollectionChild = this.childDocs.reduce((found, doc) => found || doc.type === "collection", false);
+        let expandedRowsList = this._openCollections.map(col => this.childDocs.findIndex(doc => doc === col).toString());
+        let expanded = {};
+        expandedRowsList.forEach(row => expanded[row] = true);
+
         return <ReactTable 
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} 
             data={this.childDocs} 
@@ -494,8 +486,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             getTrProps={this.getTrProps}
             sortable={false}
             TrComponent={MovableRow}
-            sorted={Array.from(this._sortedColumns.values())}
-            SubComponent={row => row.original.type === "collection" && <div>this is the sub component</div>}
+            sorted={Array.from(this._sortedColumns.values())}    
+            expanded={expanded}       
+            SubComponent={hasCollectionChild ? row => row.original.type === "collection" && 
+            <div className="sub"><CollectionSchemaView {...this.props} Document={row.original} /></div> : undefined}
+            
         />;
 
 
-- 
cgit v1.2.3-70-g09d2


From e62b7a0c5c5eec2ef1431b2e2a876e2f3753ebc0 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Tue, 23 Jul 2019 15:14:35 -0400
Subject: key navigation of cells fixed when nested collections are expanded in
 schema

---
 .../views/collections/CollectionSchemaCells.tsx    |   1 -
 .../views/collections/CollectionSchemaView.tsx     | 413 +++++++++++++--------
 2 files changed, 257 insertions(+), 157 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 2dd3eeff4..abb2203a0 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -35,7 +35,6 @@ export interface CellProps {
     addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
     moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
     isFocused: boolean; 
-    changeFocusedCellByDirection: (direction: string) => void;
     changeFocusedCellByIndex: (row: number, col: number) => void;
     setIsEditing: (isEditing: boolean) => void;
     isEditable: boolean;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 25e90a25e..5546feb95 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -7,12 +7,12 @@ import { observer } from "mobx-react";
 import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column, RowInfo } from "react-table";
 import "react-table/react-table.css";
 import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils";
-import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc";
+import { Doc, DocListCast, DocListCastAsync, Field, FieldResult, Opt } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
 import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
-import { Docs } from "../../documents/Documents";
+import { Docs, DocumentOptions } from "../../documents/Documents";
 import { Gateway } from "../../northstar/manager/Gateway";
 import { SetupDrag, DragManager } from "../../util/DragManager";
 import { CompileScript } from "../../util/Scripting";
@@ -35,6 +35,7 @@ import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./Colle
 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";
 
 library.add(faCog);
 library.add(faPlus);
@@ -61,10 +62,202 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     private _startPreviewWidth = 0;
     private DIVIDER_WIDTH = 4;
 
-    @observable _columnsPercentage = 0;
-    @observable _keys: string[] = [];
-    @observable _newKeyName: string = "";
     @observable previewScript: string = "";
+    @observable previewDoc: Doc | undefined = this.childDocs.length ? this.childDocs[0] : undefined;
+    @observable private _node : HTMLDivElement | null = null;
+    @observable private _focusedTable: Doc = this.props.Document;
+
+    @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(); }
+    @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
+
+    private createTarget = (ele: HTMLDivElement) => {
+        this._mainCont = ele;
+        super.CreateDropTarget(ele);
+    }
+
+    // detectClick = (e: PointerEvent): void => {
+    //     if (this._node && this._node.contains(e.target as Node)) {
+    //     } else {
+    //         this._isOpen = false;
+    //         this.props.setIsEditing(false);
+    //     }
+    // }
+
+    isFocused = (doc: Doc): boolean => {
+        if (!this.props.isSelected()) return false;
+        return doc === this._focusedTable;
+    }
+
+    @action
+    setFocused = (doc: Doc): void => {
+        this._focusedTable = doc;
+    }
+
+
+    //toggles preview side-panel of schema
+    @action
+    toggleExpander = () => {
+        this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0;
+    }
+
+    onDividerDown = (e: React.PointerEvent) => {
+        this._startPreviewWidth = this.previewWidth();
+        e.stopPropagation();
+        e.preventDefault();
+        document.addEventListener("pointermove", this.onDividerMove);
+        document.addEventListener('pointerup', this.onDividerUp);
+    }
+    @action
+    onDividerMove = (e: PointerEvent): void => {
+        let nativeWidth = this._mainCont!.getBoundingClientRect();
+        this.props.Document.schemaPreviewWidth = Math.min(nativeWidth.right - nativeWidth.left - 40,
+            this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]);
+    }
+    @action
+    onDividerUp = (e: PointerEvent): void => {
+        document.removeEventListener("pointermove", this.onDividerMove);
+        document.removeEventListener('pointerup', this.onDividerUp);
+        if (this._startPreviewWidth === this.previewWidth()) {
+            this.toggleExpander();
+        }
+    }
+
+    onPointerDown = (e: React.PointerEvent): void => {
+        if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
+            if (this.props.isSelected()) e.stopPropagation();
+        }
+    }
+
+    onWheel = (e: React.WheelEvent): void => {
+        if (this.props.active()) {
+            e.stopPropagation();
+        }
+    }
+
+    @computed
+    get previewDocument(): Doc | undefined {
+        let selected = this.previewDoc;
+        let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
+        return pdc;
+    }
+
+    getPreviewTransform = (): Transform => {
+        return this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth);
+    }
+
+    @computed
+    get dividerDragger() {
+        return this.previewWidth() === 0 ? (null) :
+            <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
+    }
+
+    @computed
+    get previewPanel() {
+        let layoutDoc = this.previewDocument ? Doc.expandTemplateLayout(this.previewDocument, this.props.DataDoc) : undefined;
+        return <div ref={this.createTarget}>
+            <CollectionSchemaPreview
+                Document={layoutDoc}
+                DataDocument={this.previewDocument !== this.props.DataDoc ? this.props.DataDoc : undefined}
+                childDocs={this.childDocs}
+                renderDepth={this.props.renderDepth}
+                width={this.previewWidth}
+                height={this.previewHeight}
+                getTransform={this.getPreviewTransform}
+                CollectionView={this.props.CollectionView}
+                moveDocument={this.props.moveDocument}
+                addDocument={this.props.addDocument}
+                removeDocument={this.props.removeDocument}
+                active={this.props.active}
+                whenActiveChanged={this.props.whenActiveChanged}
+                addDocTab={this.props.addDocTab}
+                setPreviewScript={this.setPreviewScript}
+                previewScript={this.previewScript}
+            />
+        </div>;
+    }
+    @action
+    setPreviewScript = (script: string) => {
+        this.previewScript = script;
+    }
+
+    @computed
+    get schemaTable() {
+        return (
+            <SchemaTable 
+                Document={this.props.Document} // child doc
+                PanelHeight={this.props.PanelHeight}
+                PanelWidth={this.props.PanelWidth}
+                childDocs={this.childDocs}
+                CollectionView={this.props.CollectionView}
+                ContainingCollectionView={this.props.ContainingCollectionView}
+                fieldKey={this.props.fieldKey} // might just be this.
+                renderDepth={this.props.renderDepth}
+                moveDocument={this.props.moveDocument}
+                ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                active={this.props.active}
+                onDrop={this.onDrop}
+                addDocTab={this.props.addDocTab}
+                isSelected={this.props.isSelected}
+                isFocused={this.isFocused}
+                setFocused={this.setFocused}
+            />
+        );
+    }
+
+    @computed
+    get schemaToolbar() {
+        return (
+            <div className="collectionSchemaView-toolbar">
+                <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />Show Preview</div>
+            </div>
+        );
+    }
+
+    render() {
+
+        // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
+        // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
+        return (
+            <>
+                {this.schemaToolbar}
+                <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
+                    onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
+                    {this.schemaTable}
+                    {this.dividerDragger}
+                    {!this.previewWidth() ? (null) : this.previewPanel}
+                </div>
+            </>
+        );
+    }
+}
+
+export interface SchemaTableProps {
+    Document: Doc; // child doc
+    PanelHeight: () => number;
+    PanelWidth: () => number;
+    childDocs: Doc[];
+    CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
+    ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
+    fieldKey: string;
+    renderDepth: number;
+    moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
+    ScreenToLocalTransform: () => Transform;
+    // CreateDropTarget: (ele: HTMLDivElement)=> void; // super createdriotarget
+    active: () => boolean;
+    onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined)=> void;
+    addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+    isSelected: () => boolean;
+    isFocused: (document: Doc) => boolean;
+    setFocused: (document: Doc) => void;
+}
+
+@observer
+export class SchemaTable extends React.Component<SchemaTableProps> {
+    // private _mainCont?: HTMLDivElement;
+    private DIVIDER_WIDTH = 4;
+
     @observable _headerIsEditing: boolean = false;
     @observable _cellIsEditing: boolean = false;
     @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0};
@@ -81,8 +274,12 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
         let columns: Column<Doc>[] = [];
+        let tableIsFocused = this.props.isFocused(this.props.Document);
+        let focusedRow = this._focusedCell.row;
+        let focusedCol = this._focusedCell.col;
+        let isEditable = !this._headerIsEditing;// && this.props.isSelected();
 
-        if (this.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) {
+        if (this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) {
             columns.push(
                 {
                     expander: true,
@@ -101,9 +298,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         }
         
         let cols = this.columns.map(col => {
-            let focusedRow = this._focusedCell.row;
-            let focusedCol = this._focusedCell.col;
-            let isEditable = !this._headerIsEditing && this.props.isSelected();// || BoolCast(this.props.Document.libraryBrush));
 
             let header = <CollectionSchemaHeader 
                 keyValue={col}
@@ -126,20 +320,20 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 Cell: (rowProps: CellInfo) => {
                     let row = rowProps.index;
                     let column = this.columns.indexOf(rowProps.column.id!);
-                    let isFocused = focusedRow === row && focusedCol === column;
+                    let isFocused = focusedRow === row && focusedCol === column && tableIsFocused;
 
                     let props: CellProps = {
                         row: row,
                         col: column,
                         rowProps: rowProps,
                         isFocused: isFocused,
-                        changeFocusedCellByDirection: this.changeFocusedCellByDirection,
                         changeFocusedCellByIndex: this.changeFocusedCellByIndex,
                         CollectionView: this.props.CollectionView,
                         ContainingCollection: this.props.ContainingCollectionView,
                         Document: this.props.Document,
                         fieldKey: this.props.fieldKey,
-                        renderDepth: this.props.renderDepth, addDocTab: this.props.addDocTab,
+                        renderDepth: this.props.renderDepth, 
+                        addDocTab: this.props.addDocTab,
                         moveDocument: this.props.moveDocument,
                         setIsEditing: this.setCellIsEditing,
                         isEditable: isEditable
@@ -200,14 +394,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before),
             moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc),
             rowInfo, 
-            rowFocused: !this._headerIsEditing && this.props.isSelected() && rowInfo.index === this._focusedCell.row,
+            rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document)
         };
     }
 
-    private createTarget = (ele: HTMLDivElement) => {
-        this._mainCont = ele;
-        super.CreateDropTarget(ele);
-    }
+    // private createTarget = (ele: HTMLDivElement) => {
+    //     this._mainCont = ele;
+    //     this.props.CreateDropTarget(ele);
+    // }
 
     // detectClick = (e: PointerEvent): void => {
     //     if (this._node && this._node.contains(e.target as Node)) {
@@ -238,35 +432,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this._headerIsEditing = isEditing;
     }
 
-    //toggles preview side-panel of schema
-    @action
-    toggleExpander = () => {
-        this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0;
-    }
-
-    onDividerDown = (e: React.PointerEvent) => {
-        this._startPreviewWidth = this.previewWidth();
-        e.stopPropagation();
-        e.preventDefault();
-        document.addEventListener("pointermove", this.onDividerMove);
-        document.addEventListener('pointerup', this.onDividerUp);
-    }
-    @action
-    onDividerMove = (e: PointerEvent): void => {
-        let nativeWidth = this._mainCont!.getBoundingClientRect();
-        this.props.Document.schemaPreviewWidth = Math.min(nativeWidth.right - nativeWidth.left - 40,
-            this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]);
-    }
-    @action
-    onDividerUp = (e: PointerEvent): void => {
-        document.removeEventListener("pointermove", this.onDividerMove);
-        document.removeEventListener('pointerup', this.onDividerUp);
-        if (this._startPreviewWidth === this.previewWidth()) {
-            this.toggleExpander();
-        }
-    }
-
     onPointerDown = (e: React.PointerEvent): void => {
+        // console.log("pointer down", StrCast(this.props.Document.title));
+        this.props.setFocused(this.props.Document);
         if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
             if (this.props.isSelected()) e.stopPropagation();
         }
@@ -278,14 +446,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         }
     }
 
-    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 });
-        }
-    }
-
     onKeyDown = (e: KeyboardEvent): void => {
-        if (!this._cellIsEditing && !this._headerIsEditing && this.props.isSelected()) {
+        if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected()) {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
         }
@@ -295,7 +457,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     changeFocusedCellByDirection = (direction: string): void => {
         switch (direction) {
             case "tab":
-                if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) {
+                if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.props.childDocs.length) {
                     this._focusedCell = { row: 0, col: 0 };
                 } else if (this._focusedCell.col + 1 === this.columns.length) {
                     this._focusedCell = { row: this._focusedCell.row + 1, col: 0 };
@@ -313,7 +475,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col };
                 break;
             case "down":
-                this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
+                this._focusedCell = { row: this._focusedCell.row + 1 === this.props.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
                 break;
         }
     }
@@ -321,27 +483,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @action
     changeFocusedCellByIndex = (row: number, col: number): void => {
         this._focusedCell = { row: row, col: col };
-    }
-
-    @action
-    makeDB = async () => {
-        let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
-        csv = csv.substr(0, csv.length - 1) + "\n";
-        let self = this;
-        DocListCast(this.props.Document.data).map(doc => {
-            csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "0") + ",", "");
-            csv = csv.substr(0, csv.length - 1) + "\n";
-        });
-        csv.substring(0, csv.length - 1);
-        let dbName = StrCast(this.props.Document.title);
-        let res = await Gateway.Instance.PostSchema(csv, dbName);
-        if (self.props.CollectionView.props.addDocument) {
-            let schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document });
-            if (schemaDoc) {
-                //self.props.CollectionView.props.addDocument(schemaDoc, false);
-                self.props.Document.schemaDoc = schemaDoc;
-            }
-        }
+        this.props.setFocused(this.props.Document);
+        // console.log("changed cell by index", StrCast(this.props.Document.title));
     }
 
     @action
@@ -359,12 +502,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this.columns.push("New field (" + index + ")");
     }
 
-    @action
-    addColumn = () => {
-        this.columns.push(this._newKeyName);
-        this._newKeyName = "";
-    }
-
     @action
     deleteColumn = (key: string) => {
         let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
@@ -442,17 +579,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this._sortedColumns.delete(column);
     } 
 
-    @computed
-    get previewDocument(): Doc | undefined {
-        let selectedIndex = this._focusedCell.row;
-        const selected = this.childDocs.length > selectedIndex ? this.childDocs[selectedIndex] : undefined;
-        let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
-        return pdc;
-    }
-
-    getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth);
-
-
     get documentKeys() {
         const docs = DocListCast(this.props.Document[this.props.fieldKey]);
         let keys: { [key: string]: boolean } = {};
@@ -471,16 +597,16 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed
     get reactTable() {
         let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
-        let hasCollectionChild = this.childDocs.reduce((found, doc) => found || doc.type === "collection", false);
-        let expandedRowsList = this._openCollections.map(col => this.childDocs.findIndex(doc => doc === col).toString());
+        let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false);
+        let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc === col).toString());
         let expanded = {};
         expandedRowsList.forEach(row => expanded[row] = true);
 
         return <ReactTable 
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} 
-            data={this.childDocs} 
+            data={this.props.childDocs} 
             page={0} 
-            pageSize={this.childDocs.length} 
+            pageSize={this.props.childDocs.length} 
             showPagination={false}
             columns={this.tableColumns}
             getTrProps={this.getTrProps}
@@ -488,79 +614,54 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             TrComponent={MovableRow}
             sorted={Array.from(this._sortedColumns.values())}    
             expanded={expanded}       
-            SubComponent={hasCollectionChild ? row => row.original.type === "collection" && 
-            <div className="sub"><CollectionSchemaView {...this.props} Document={row.original} /></div> : undefined}
+            SubComponent={hasCollectionChild ? 
+                row => {
+                    if (row.original.type === "collection") { 
+                        let childDocs = DocListCast(row.original[this.props.fieldKey]);
+                        return <div className="sub"><SchemaTable {...this.props} Document={row.original} childDocs={childDocs}/></div>;
+                    }
+                }
+             : undefined}
             
         />;
-
-
     }
 
-    @computed
-    get dividerDragger() {
-        return this.previewWidth() === 0 ? (null) :
-            <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
+    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 });
+        }
     }
 
-
-    @computed
-    get previewPanel() {
-        // let layoutDoc = this.previewDocument;
-        // let resolvedDataDoc = (layoutDoc !== this.props.DataDoc) ? this.props.DataDoc : undefined;
-        // if (layoutDoc && !(Cast(layoutDoc.layout, Doc) instanceof Doc) &&
-        //     resolvedDataDoc && resolvedDataDoc !== layoutDoc) {
-        //     // ... so change the layout to be an expanded view of the template layout.  This allows the view override the template's properties and be referenceable as its own document.
-        //     layoutDoc = Doc.expandTemplateLayout(layoutDoc, resolvedDataDoc);
-        // }
-
-        let layoutDoc = this.previewDocument ? Doc.expandTemplateLayout(this.previewDocument, this.props.DataDoc) : undefined;
-        return <div ref={this.createTarget}>
-            <CollectionSchemaPreview
-                Document={layoutDoc}
-                DataDocument={this.previewDocument !== this.props.DataDoc ? this.props.DataDoc : undefined}
-                childDocs={this.childDocs}
-                renderDepth={this.props.renderDepth}
-                width={this.previewWidth}
-                height={this.previewHeight}
-                getTransform={this.getPreviewTransform}
-                CollectionView={this.props.CollectionView}
-                moveDocument={this.props.moveDocument}
-                addDocument={this.props.addDocument}
-                removeDocument={this.props.removeDocument}
-                active={this.props.active}
-                whenActiveChanged={this.props.whenActiveChanged}
-                addDocTab={this.props.addDocTab}
-                setPreviewScript={this.setPreviewScript}
-                previewScript={this.previewScript}
-            />
-        </div>;
-    }
     @action
-    setPreviewScript = (script: string) => {
-        this.previewScript = script;
-    }
-
-    @computed
-    get schemaToolbar() {
-        return (
-            <div className="collectionSchemaView-toolbar">
-                <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />Show Preview</div>
-            </div>
-        );
+    makeDB = async () => {
+        let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
+        csv = csv.substr(0, csv.length - 1) + "\n";
+        let self = this;
+        DocListCast(this.props.Document.data).map(doc => {
+            csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "0") + ",", "");
+            csv = csv.substr(0, csv.length - 1) + "\n";
+        });
+        csv.substring(0, csv.length - 1);
+        let dbName = StrCast(this.props.Document.title);
+        let res = await Gateway.Instance.PostSchema(csv, dbName);
+        if (self.props.CollectionView.props.addDocument) {
+            let schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document });
+            if (schemaDoc) {
+                //self.props.CollectionView.props.addDocument(schemaDoc, false);
+                self.props.Document.schemaDoc = schemaDoc;
+            }
+        }
     }
 
     render() {
+        if (this.props.isFocused(this.props.Document)) console.log(StrCast(this.props.Document.title), "IS FOCUSED");
+        // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
+        // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
         return (
-            <>
-            {this.schemaToolbar}
-            <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
-                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
+            <div className="collectionSchemaView-table" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
+                onDrop={(e: React.DragEvent) => this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} >
                 {this.reactTable}
-                {this.dividerDragger}
-                {!this.previewWidth() ? (null) : this.previewPanel}
-                {/* {this.tableOptionsPanel} */}
             </div>
-            </>
         );
     }
 }
-- 
cgit v1.2.3-70-g09d2


From 7d9958f23b2b69f59bb108b33ec014b52ad41c99 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Tue, 23 Jul 2019 19:11:17 -0400
Subject: merge

---
 .../collections/CollectionSchemaMovableTableHOC.tsx | 10 ++++++----
 .../views/collections/CollectionSchemaView.tsx      | 21 +++++++++++++++++----
 2 files changed, 23 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index db60e657a..6fc04849c 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -5,7 +5,7 @@ import { Transform } from "../../util/Transform";
 import { Doc } from "../../../new_fields/Doc";
 import { DragManager, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
-import { Cast, FieldValue } from "../../../new_fields/Types";
+import { Cast, FieldValue, StrCast } from "../../../new_fields/Types";
 
 
 export interface MovableColumnProps {
@@ -152,15 +152,17 @@ export class MovableRow extends React.Component<MovableRowProps> {
         let rect = this._header!.current!.getBoundingClientRect();
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
         let before = x[1] < bounds[1];
+
         if (de.data instanceof DragManager.DocumentDragData) {
             e.stopPropagation();
             if (de.data.draggedDocuments[0] === rowDoc) return true;
             let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before);
             let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
-            return (de.data.dropAction || de.data.userDropAction) ?
+            return (de.data.dropAction || de.data.userDropAction) ? 
                 de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
                 : (de.data.moveDocument) ?
-                    movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false)
+                    movedDocs.reduce((added: boolean, d) =>  de.data.moveDocument(d, rowDoc, addDocument) || added, false)
+                    // movedDocs.reduce((added: boolean, d) => this.props.moveDoc(d, rowDoc, addDocument) || added, false)
                     : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false);
         }
         return false;
@@ -177,7 +179,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
         if (!doc) return <></>;
 
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc);
+        let onItemDown = SetupDrag(reference, () => doc);
 
         return (
             <div className={this.props.rowFocused ? "collectionSchema-row row-focused" : "collectionSchema-row"} ref={this.createRowDropTarget}>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 5546feb95..6d71823c2 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -95,6 +95,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this._focusedTable = doc;
     }
 
+    @action
+    setPreviewDoc = (doc: Doc): void => {
+        this.previewDoc = doc;
+    }
 
     //toggles preview side-panel of schema
     @action
@@ -384,6 +388,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         document.removeEventListener("keydown", this.onKeyDown);
     }
 
+    tableAddDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
+        console.log("table add doc");
+        return Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
+    }
+
+    tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => {
+        console.log("SCHEMA MOVE"); 
+        this.props.moveDocument(d, target, addDoc);
+    }
+
     private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
         const that = this;
         if (!rowInfo) {
@@ -391,8 +405,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         }
         return {
             ScreenToLocalTransform: this.props.ScreenToLocalTransform,
-            addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before),
-            moveDoc: (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc),
+            addDoc: this.tableAddDoc,
+            moveDoc: this.tableMoveDoc,
             rowInfo, 
             rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document)
         };
@@ -654,7 +668,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     render() {
-        if (this.props.isFocused(this.props.Document)) console.log(StrCast(this.props.Document.title), "IS FOCUSED");
         // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
         // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
         return (
@@ -669,7 +682,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
 interface CollectionSchemaPreviewProps {
     Document?: Doc;
-    DataDocument?: Doc;
+    DataDocument?: Doc; 
     childDocs?: Doc[];
     renderDepth: number;
     fitToBox?: boolean;
-- 
cgit v1.2.3-70-g09d2


From 40b7197fb9b4748a63845bb664fa9ab02ad6915a Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Tue, 23 Jul 2019 22:07:55 -0400
Subject: minor styling

---
 src/client/views/EditableView.tsx                  | 13 ++--
 .../views/collections/CollectionSchemaHeaders.tsx  | 38 +++++------
 .../views/collections/CollectionSchemaView.scss    | 29 ++++++--
 .../views/collections/CollectionSchemaView.tsx     | 79 +++++++++++-----------
 4 files changed, 92 insertions(+), 67 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 5cbecf2c9..31e4557be 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -39,7 +39,7 @@ export interface EditableProps {
     oneLine?: boolean;
     editing?: boolean;
     onClick?: (e: React.MouseEvent) => boolean;
-    isEditingCallback?:  (isEditing: boolean) => void;
+    isEditingCallback?: (isEditing: boolean) => void;
 }
 
 /**
@@ -58,7 +58,12 @@ export class EditableView extends React.Component<EditableProps> {
 
     @action
     componentWillReceiveProps(nextProps: EditableProps) {
-        this._editing = nextProps.editing ? true : false;
+        // this is done because when autosuggest is turned on, the suggestions are passed in as a prop,
+        // so when the suggestions are passed in, and no editing prop is passed in, it used to set it
+        // to false. this will no longer do so -syip
+        if (nextProps.editing && nextProps.editing !== this._editing) {
+            this._editing = nextProps.editing;
+        }
     }
 
     @action
@@ -88,7 +93,7 @@ export class EditableView extends React.Component<EditableProps> {
         if (!this.props.onClick || !this.props.onClick(e)) {
             this._editing = true;
             this.props.isEditingCallback && this.props.isEditingCallback(true);
-        } 
+        }
         e.stopPropagation();
     }
 
@@ -119,7 +124,7 @@ export class EditableView extends React.Component<EditableProps> {
                     }}
                 />
                 : <input className="editableView-input" defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus
-                    onBlur={action(() => {this._editing = false; this.props.isEditingCallback && this.props.isEditingCallback(false);})} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
+                    onBlur={action(() => { this._editing = false; this.props.isEditingCallback && this.props.isEditingCallback(false); })} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
                     style={{ display: this.props.display, fontSize: this.props.fontSize }} />;
         } else {
             if (this.props.autosuggestProps) this.props.autosuggestProps.resetValue();
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 3a57cd306..d1d0674c4 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -30,7 +30,7 @@ export interface HeaderProps {
 export class CollectionSchemaHeader extends React.Component<HeaderProps> {
     render() {
         let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" :
-            this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType ===  ColumnType.Doc ? "file" : "align-justify";
+            this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify";
 
         return (
             <div className="collectionSchemaView-header" >
@@ -64,7 +64,7 @@ export interface AddColumnHeaderProps {
 export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHeaderProps> {
     render() {
         return (
-            <button onClick={() => this.props.createColumn()}><FontAwesomeIcon icon="plus" size="sm" /></button>
+            <button className="add-column" onClick={() => this.props.createColumn()}><FontAwesomeIcon icon="plus" size="sm" /></button>
         );
     }
 }
@@ -91,7 +91,7 @@ export interface ColumnMenuProps {
 @observer
 export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> {
     @observable private _isOpen: boolean = false;
-    @observable private _node : HTMLDivElement | null = null;
+    @observable private _node: HTMLDivElement | null = null;
 
     componentDidMount() {
         document.addEventListener("pointerdown", this.detectClick);
@@ -109,7 +109,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         }
     }
 
-    @action 
+    @action
     toggleIsOpen = (): void => {
         this._isOpen = !this._isOpen;
         this.props.setIsEditing(this._isOpen);
@@ -133,19 +133,19 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         return (
             <div className="collectionSchema-headerMenu-group">
                 <label>Column type:</label>
-                <div className="columnMenu-types"> 
+                <div className="columnMenu-types">
                     <button title="Any" className={this.props.keyType === ColumnType.Any ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Any)}>
                         <FontAwesomeIcon icon={"align-justify"} size="sm" />
-                        </button>
+                    </button>
                     <button title="Number" className={this.props.keyType === ColumnType.Number ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Number)}>
                         <FontAwesomeIcon icon={"hashtag"} size="sm" />
-                        </button>
+                    </button>
                     <button title="String" className={this.props.keyType === ColumnType.String ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.String)}>
                         <FontAwesomeIcon icon={"font"} size="sm" />
-                        </button>
+                    </button>
                     <button title="Checkbox" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}>
                         <FontAwesomeIcon icon={"check-square"} size="sm" />
-                        </button>
+                    </button>
                     <button title="Document" className={this.props.keyType === ColumnType.Doc ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Doc)}>
                         <FontAwesomeIcon icon={"file"} size="sm" />
                     </button>
@@ -183,13 +183,13 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                     />
                 </div>
                 {this.props.onlyShowOptions ? <></> :
-                <>
-                    {this.renderTypes()}
-                    {this.renderSorting()}
-                    <div className="collectionSchema-headerMenu-group">
-                        <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button>
-                    </div>
-                </>
+                    <>
+                        {this.renderTypes()}
+                        {this.renderSorting()}
+                        <div className="collectionSchema-headerMenu-group">
+                            <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button>
+                        </div>
+                    </>
                 }
             </div>
         );
@@ -225,7 +225,7 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
 
     @action setSearchTerm = (value: string): void => { this._searchTerm = value; };
     @action setKey = (key: string): void => { this._key = key; };
-    @action setIsOpen = (isOpen: boolean): void => {this._isOpen = isOpen;};
+    @action setIsOpen = (isOpen: boolean): void => { this._isOpen = isOpen; };
 
     @action
     onSelect = (key: string): void => {
@@ -253,7 +253,7 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
         }
     }
 
-    @action 
+    @action
     onPointerEnter = (e: React.PointerEvent): void => {
         this._canClose = false;
     }
@@ -278,7 +278,7 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
         if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) {
             options.push(<div key={""} className="key-option"
                 onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}>
-                    Create "{this._searchTerm}" key</div>);
+                Create "{this._searchTerm}" key</div>);
         }
 
         return options;
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 4b20e8241..38d14c2de 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -57,7 +57,7 @@
 .ReactTable {
     width: 100%;
     height: 100%;
-    background: $light-color;
+    background: white;
     box-sizing: border-box;
     border: none !important;
 
@@ -76,6 +76,7 @@
             font-size: 12px;
             height: 30px;
             border: 1px solid $intermediate-color;
+            box-shadow: none;
         }
 
         .rt-resizable-header {
@@ -101,6 +102,7 @@
         // max-height: $MAX_ROW_HEIGHT;
         font-size: 13px;
         text-align: center;
+        background-color: $light-color-secondary;
         
         &:last-child {
             overflow: visible;
@@ -114,6 +116,7 @@
     .rt-tr-group {
         direction: ltr;
         flex: 0 1 auto;
+        min-height: 30px;
         // max-height: $MAX_ROW_HEIGHT;
         // for sub comp
 
@@ -134,6 +137,7 @@
 
     .rt-tr {
         width: 100%;
+        min-height: 30px;
         // height: $MAX_ROW_HEIGHT;
     }
 
@@ -144,6 +148,7 @@
         padding: 0;
         font-size: 13px;
         text-align: center;
+        white-space: normal;
 
         .imageBox-cont {
             position: relative;
@@ -190,7 +195,9 @@
 
 .collectionSchemaView-header {
     height: 100%;
-    color: $intermediate-color;
+    color: gray;
+    letter-spacing: 2px;
+    text-transform: uppercase;
 
     .collectionSchema-header-menu {
         height: 100%;
@@ -204,9 +211,18 @@
                 margin-right: 4px;
             }
         }
+
+        div[class*="css"] {
+            width: 100%;
+            height: 100%;
+        }
     }
 }
 
+button.add-column {
+    width: 28px;
+}
+
 .collectionSchema-header-menuOptions {
     color: black;
     width: 175px;
@@ -265,6 +281,7 @@
 
 .collectionSchema-row {
     // height: $MAX_ROW_HEIGHT;
+    height: 100%;
 
     &.row-focused {
         background-color: $light-color-secondary;
@@ -317,7 +334,7 @@
     p {
         width: 100%;
         height: 100%;
-        word-wrap: break-word;
+        // word-wrap: break-word;
     }
 }
 
@@ -337,5 +354,9 @@
 
 .sub {
     padding: 20px;
-    background-color: red;
+    background-color: $intermediate-color;
+}
+
+.collectionSchemaView-expander {
+    height: 100%;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index febf95dc7..0e2d37a9e 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,6 +1,6 @@
 import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
+import { faCog, faPlus, faSortUp, faSortDown } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
@@ -40,8 +40,7 @@ import { ImageBox } from "../nodes/ImageBox";
 import { ComputedField } from "../../../new_fields/ScriptField";
 
 
-library.add(faCog);
-library.add(faPlus);
+library.add(faCog, faPlus, faSortUp, faSortDown);
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
 
 export enum ColumnType {
@@ -67,7 +66,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @observable previewScript: string = "";
     @observable previewDoc: Doc | undefined = this.childDocs.length ? this.childDocs[0] : undefined;
-    @observable private _node : HTMLDivElement | null = null;
+    @observable private _node: HTMLDivElement | null = null;
     @observable private _focusedTable: Doc = this.props.Document;
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
@@ -192,7 +191,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed
     get schemaTable() {
         return (
-            <SchemaTable 
+            <SchemaTable
                 Document={this.props.Document} // child doc
                 PanelHeight={this.props.PanelHeight}
                 PanelWidth={this.props.PanelWidth}
@@ -253,7 +252,7 @@ export interface SchemaTableProps {
     ScreenToLocalTransform: () => Transform;
     // CreateDropTarget: (ele: HTMLDivElement)=> void; // super createdriotarget
     active: () => boolean;
-    onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined)=> void;
+    onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined) => void;
     addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
     isSelected: () => boolean;
     isFocused: (document: Doc) => boolean;
@@ -267,16 +266,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @observable _headerIsEditing: boolean = false;
     @observable _cellIsEditing: boolean = false;
-    @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0};
-    @observable _sortedColumns: Map<string, {id: string, desc: boolean}> = new Map();
+    @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 };
+    @observable _sortedColumns: Map<string, { id: string, desc: boolean }> = new Map();
     @observable _openCollections: Array<Doc> = [];
-    @observable private _node : HTMLDivElement | null = null;
+    @observable private _node: HTMLDivElement | null = null;
 
     @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(); }
     @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); }
-    set columns(columns: string[]) {this.props.Document.schemaColumns = new List<string>(columns); }
+    set columns(columns: string[]) { this.props.Document.schemaColumns = new List<string>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
@@ -294,8 +293,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                     width: 45,
                     Expander: (rowInfo) => {
                         if (rowInfo.original.type === "collection") {
-                            if (rowInfo.isExpanded) return <div onClick={() => this.onCloseCollection(rowInfo.original)}>-</div>;
-                            if (!rowInfo.isExpanded) return <div onClick={() => this.onExpandCollection(rowInfo.original)}>+</div>;
+                            if (rowInfo.isExpanded) return <div className="collectionSchemaView-expander" onClick={() => this.onCloseCollection(rowInfo.original)}><FontAwesomeIcon icon={"sort-up"} size="sm" /></div>;
+                            if (!rowInfo.isExpanded) return <div className="collectionSchemaView-expander" onClick={() => this.onExpandCollection(rowInfo.original)}><FontAwesomeIcon icon={"sort-down"} size="sm" /></div>;
                         } else {
                             return null;
                         }
@@ -303,10 +302,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 }
             );
         }
-        
+
         let cols = this.columns.map(col => {
 
-            let header = <CollectionSchemaHeader 
+            let header = <CollectionSchemaHeader
                 keyValue={col}
                 possibleKeys={possibleKeys}
                 existingKeys={this.columns}
@@ -339,7 +338,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         ContainingCollection: this.props.ContainingCollectionView,
                         Document: this.props.Document,
                         fieldKey: this.props.fieldKey,
-                        renderDepth: this.props.renderDepth, 
+                        renderDepth: this.props.renderDepth,
                         addDocTab: this.props.addDocTab,
                         moveDocument: this.props.moveDocument,
                         setIsEditing: this.setCellIsEditing,
@@ -347,11 +346,11 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                     };
 
                     let colType = this.getColumnType(col);
-                    if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/>;
-                    if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/>;
+                    if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props} />;
+                    if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props} />;
                     if (colType === ColumnType.Boolean) return <CollectionSchemaCheckboxCell {...props} />;
                     if (colType === ColumnType.Doc) return <CollectionSchemaDocCell {...props} />;
-                    return <CollectionSchemaCell {...props}/>;
+                    return <CollectionSchemaCell {...props} />;
                 },
                 minWidth: 200,
             };
@@ -363,7 +362,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             accessor: (doc: Doc) => 0,
             id: "add",
             Cell: (rowProps: CellInfo) => <></>,
-            width: 45,
+            width: 28,
             resizable: false
         });
         return columns;
@@ -397,7 +396,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => {
-        console.log("SCHEMA MOVE"); 
+        console.log("SCHEMA MOVE");
         this.props.moveDocument(d, target, addDoc);
     }
 
@@ -410,7 +409,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             ScreenToLocalTransform: this.props.ScreenToLocalTransform,
             addDoc: this.tableAddDoc,
             moveDoc: this.tableMoveDoc,
-            rowInfo, 
+            rowInfo,
             rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document)
         };
     }
@@ -505,7 +504,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @action
-    createColumn = () => {  
+    createColumn = () => {
         let index = 0;
         let found = this.columns.findIndex(col => col.toUpperCase() === "New field".toUpperCase()) > -1;
         if (!found) {
@@ -513,7 +512,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             return;
         }
         while (found) {
-            index ++;
+            index++;
             found = this.columns.findIndex(col => col.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
         }
         this.columns.push("New field (" + index + ")");
@@ -562,7 +561,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         if (!typesDoc) {
             let newTypesDoc = new Doc();
             newTypesDoc[key] = type;
-            this.props.Document.schemaColumnTypes  = newTypesDoc;
+            this.props.Document.schemaColumnTypes = newTypesDoc;
             return;
         } else {
             typesDoc[key] = type;
@@ -588,13 +587,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     setColumnSort = (column: string, descending: boolean) => {
-        this._sortedColumns.set(column, {id: column, desc: descending});
+        this._sortedColumns.set(column, { id: column, desc: descending });
     }
 
     @action
     removeColumnSort = (column: string) => {
         this._sortedColumns.delete(column);
-    } 
+    }
 
     get documentKeys() {
         const docs = DocListCast(this.props.Document[this.props.fieldKey]);
@@ -619,27 +618,27 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let expanded = {};
         expandedRowsList.forEach(row => expanded[row] = true);
 
-        return <ReactTable 
-            style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} 
-            data={this.props.childDocs} 
-            page={0} 
-            pageSize={this.props.childDocs.length} 
+        return <ReactTable
+            style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
+            data={this.props.childDocs}
+            page={0}
+            pageSize={this.props.childDocs.length}
             showPagination={false}
             columns={this.tableColumns}
             getTrProps={this.getTrProps}
             sortable={false}
             TrComponent={MovableRow}
-            sorted={Array.from(this._sortedColumns.values())}    
-            expanded={expanded}       
-            SubComponent={hasCollectionChild ? 
+            sorted={Array.from(this._sortedColumns.values())}
+            expanded={expanded}
+            SubComponent={hasCollectionChild ?
                 row => {
-                    if (row.original.type === "collection") { 
+                    if (row.original.type === "collection") {
                         let childDocs = DocListCast(row.original[this.props.fieldKey]);
-                        return <div className="sub"><SchemaTable {...this.props} Document={row.original} childDocs={childDocs}/></div>;
+                        return <div className="sub"><SchemaTable {...this.props} Document={row.original} childDocs={childDocs} /></div>;
                     }
                 }
-             : undefined}
-            
+                : undefined}
+
         />;
     }
 
@@ -685,7 +684,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
 interface CollectionSchemaPreviewProps {
     Document?: Doc;
-    DataDocument?: Doc; 
+    DataDocument?: Doc;
     childDocs?: Doc[];
     renderDepth: number;
     fitToBox?: boolean;
@@ -762,7 +761,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
         return undefined;
     }
 
-    
+
     render() {
         let input = this.props.previewScript === undefined ? (null) :
             <div ref={this.createTarget}><input className="collectionSchemaView-input" value={this.props.previewScript} onChange={this.onPreviewScriptChange}
-- 
cgit v1.2.3-70-g09d2


From 07e4ad670134213afc019bf84f765cdfc00a510a Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Wed, 24 Jul 2019 12:28:17 -0400
Subject: can text wrap row via context menu

---
 .../CollectionSchemaMovableTableHOC.tsx            | 34 +++++++++++++++-------
 .../views/collections/CollectionSchemaView.scss    |  8 ++++-
 .../views/collections/CollectionSchemaView.tsx     | 28 ++++++++++++++----
 3 files changed, 53 insertions(+), 17 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 6fc04849c..beae739ec 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -1,11 +1,12 @@
 import React = require("react");
-import { ReactTableDefaults, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0 } from "react-table";
+import { ReactTableDefaults, TableCellRenderer, ComponentPropsGetterR, ComponentPropsGetter0, RowInfo } from "react-table";
 import "./CollectionSchemaView.scss";
 import { Transform } from "../../util/Transform";
 import { Doc } from "../../../new_fields/Doc";
 import { DragManager, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Cast, FieldValue, StrCast } from "../../../new_fields/Types";
+import { ContextMenu } from "../ContextMenu";
 
 
 export interface MovableColumnProps {
@@ -60,7 +61,7 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
         return false;
     }
 
-    setupDrag (ref: React.RefObject<HTMLElement>) {
+    setupDrag(ref: React.RefObject<HTMLElement>) {
         let onRowMove = (e: PointerEvent) => {
             e.stopPropagation();
             e.preventDefault();
@@ -102,10 +103,13 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
 }
 
 export interface MovableRowProps {
+    rowInfo: RowInfo;
     ScreenToLocalTransform: () => Transform;
     addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
     moveDoc: DragManager.MoveFunction;
     rowFocused: boolean;
+    textWrapRow: (doc: Doc) => void;
+    rowWrapped: boolean;
 }
 
 export class MovableRow extends React.Component<MovableRowProps> {
@@ -141,11 +145,10 @@ export class MovableRow extends React.Component<MovableRowProps> {
     }
 
     rowDrop = (e: Event, de: DragManager.DropEvent) => {
-        const { children = null, rowInfo } = this.props;
-        if (!rowInfo) return false;
+        // const { children = null, rowInfo } = this.props;
+        // if (!rowInfo) return false;
 
-        const { original } = rowInfo;
-        const rowDoc = FieldValue(Cast(original, Doc));
+        const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc));
         if (!rowDoc) return false;
 
         let x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
@@ -158,16 +161,23 @@ export class MovableRow extends React.Component<MovableRowProps> {
             if (de.data.draggedDocuments[0] === rowDoc) return true;
             let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before);
             let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
-            return (de.data.dropAction || de.data.userDropAction) ? 
+            return (de.data.dropAction || de.data.userDropAction) ?
                 de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
                 : (de.data.moveDocument) ?
-                    movedDocs.reduce((added: boolean, d) =>  de.data.moveDocument(d, rowDoc, addDocument) || added, false)
+                    movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false)
                     // movedDocs.reduce((added: boolean, d) => this.props.moveDoc(d, rowDoc, addDocument) || added, false)
                     : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false);
         }
         return false;
     }
 
+    onRowContextMenu = (e: React.MouseEvent): void => {
+        // const { rowInfo } = this.props;
+        // const { textWrapRow, original } = rowInfo;
+        let description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row";
+        ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original) });
+    }
+
     render() {
         const { children = null, rowInfo } = this.props;
         if (!rowInfo) {
@@ -179,10 +189,14 @@ export class MovableRow extends React.Component<MovableRowProps> {
         if (!doc) return <></>;
 
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => doc);
+        let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc);
+
+        let className = "collectionSchema-row";
+        if (this.props.rowFocused) className += " row-focused";
+        if (this.props.rowWrapped) className += " row-wrapped";
 
         return (
-            <div className={this.props.rowFocused ? "collectionSchema-row row-focused" : "collectionSchema-row"} ref={this.createRowDropTarget}>
+            <div className={className} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}>
                 <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
                     <div className="row-dragger" ref={reference} onPointerDown={onItemDown}>
                         <ReactTableDefaults.TrComponent>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 38d14c2de..410790197 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -148,7 +148,7 @@
         padding: 0;
         font-size: 13px;
         text-align: center;
-        white-space: normal;
+        // white-space: normal;
 
         .imageBox-cont {
             position: relative;
@@ -287,6 +287,12 @@ button.add-column {
         background-color: $light-color-secondary;
     }
 
+    &.row-wrapped {
+        .rt-td {
+            white-space: normal;
+        }
+    }
+
     .row-dragger {
         // height: $MAX_ROW_HEIGHT;
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0e2d37a9e..62e4ceb54 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -53,6 +53,7 @@ export enum ColumnType {
 }
 // this map should be used for keys that should have a const type of value
 const columnTypes: Map<string, ColumnType> = new Map([
+    ["title", ColumnType.String],
     ["x", ColumnType.Number], ["y", ColumnType.Number], ["width", ColumnType.Number], ["height", ColumnType.Number],
     ["nativeWidth", ColumnType.Number], ["nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean],
     ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number]
@@ -268,7 +269,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @observable _cellIsEditing: boolean = false;
     @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 };
     @observable _sortedColumns: Map<string, { id: string, desc: boolean }> = new Map();
-    @observable _openCollections: Array<Doc> = [];
+    @observable _openCollections: Array<string> = [];
+    @observable _textWrappedRows: Array<string> = [];
     @observable private _node: HTMLDivElement | null = null;
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
@@ -396,7 +398,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => {
-        console.log("SCHEMA MOVE");
+        console.log("SCHEMA MOVE", StrCast(d.title), StrCast(target.title));
         this.props.moveDocument(d, target, addDoc);
     }
 
@@ -410,7 +412,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             addDoc: this.tableAddDoc,
             moveDoc: this.tableMoveDoc,
             rowInfo,
-            rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document)
+            rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document),
+            textWrapRow: this.textWrapRow,
+            rowWrapped: this._textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1
         };
     }
 
@@ -429,12 +433,12 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     onExpandCollection = (collection: Doc): void => {
-        this._openCollections.push(collection);
+        this._openCollections.push(collection[Id]);
     }
 
     @action
     onCloseCollection = (collection: Doc): void => {
-        let index = this._openCollections.findIndex(col => col === collection);
+        let index = this._openCollections.findIndex(col => col === collection[Id]);
         if (index > -1) this._openCollections.splice(index, 1);
     }
 
@@ -610,13 +614,25 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         return Array.from(Object.keys(keys));
     }
 
+    @action
+    textWrapRow = (doc: Doc): void => {
+        let index = this._textWrappedRows.findIndex(id => doc[Id] === id);
+        if (index > -1) {
+            this._textWrappedRows.splice(index, 1);
+        } else {
+            this._textWrappedRows.push(doc[Id]);
+        }
+
+    }
+
     @computed
     get reactTable() {
         let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false);
-        let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc === col).toString());
+        let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc[Id] === col).toString());
         let expanded = {};
         expandedRowsList.forEach(row => expanded[row] = true);
+        console.log(...[...this._textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :((((
 
         return <ReactTable
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
-- 
cgit v1.2.3-70-g09d2


From 75070c4c2188823ed9a09816861d4f873574c9db Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Wed, 24 Jul 2019 17:48:11 -0400
Subject: can move rows within expanded collection

---
 src/client/util/DragManager.ts                     |  4 +--
 .../views/collections/CollectionSchemaCells.tsx    | 42 ++++++++++++----------
 .../CollectionSchemaMovableTableHOC.tsx            | 18 +++++-----
 .../views/collections/CollectionSchemaView.scss    | 24 ++++++-------
 .../views/collections/CollectionSchemaView.tsx     | 17 +++++----
 src/new_fields/Doc.ts                              |  9 ++++-
 6 files changed, 64 insertions(+), 50 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index f9f6b05c0..0299b1d90 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,6 +1,6 @@
 import { action, runInAction } from "mobx";
 import { Doc } from "../../new_fields/Doc";
-import { Cast } from "../../new_fields/Types";
+import { Cast, StrCast } from "../../new_fields/Types";
 import { URLField } from "../../new_fields/URLField";
 import { emptyFunction } from "../../Utils";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
@@ -305,7 +305,7 @@ export namespace DragManager {
         StartDrag([ele], dragData, downX, downY, options);
     }
 
-    export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?:DragOptions) {
+    export function StartColumnDrag(ele: HTMLElement, dragData: ColumnDragData, downX: number, downY: number, options?: DragOptions) {
         StartDrag([ele], dragData, downX, downY, options);
     }
 
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index abb2203a0..bc84da140 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -34,7 +34,7 @@ export interface CellProps {
     renderDepth: number;
     addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
     moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
-    isFocused: boolean; 
+    isFocused: boolean;
     changeFocusedCellByIndex: (row: number, col: number) => void;
     setIsEditing: (isEditing: boolean) => void;
     isEditable: boolean;
@@ -42,22 +42,22 @@ export interface CellProps {
 
 @observer
 export class CollectionSchemaCell extends React.Component<CellProps> {
-    @observable protected _isEditing: boolean = false;
+    @observable protected _isEditing: boolean = this.props.isEditing ? true : false;
     protected _focusRef = React.createRef<HTMLDivElement>();
     protected _document = this.props.rowProps.original;
     private _dropDisposer?: DragManager.DragDropDisposer;
 
     componentDidMount() {
-        if (this._focusRef.current) {
-            if (this.props.isFocused) {
-                this._focusRef.current.className += " focused";
-                if (!this.props.isEditable) {
-                    this._focusRef.current.className += " inactive";
-                }
-            } else {
-                this._focusRef.current.className = "collectionSchemaView-cellWrapper";
-            }
-        }
+        // if (this._focusRef.current) {
+        //     if (this.props.isFocused) {
+        //         this._focusRef.current.className += " focused";
+        //         if (!this.props.isEditable) {
+        //             this._focusRef.current.className += " inactive";
+        //         }
+        //     } else {
+        //         this._focusRef.current.className = "collectionSchemaView-cellWrapper";
+        //     }
+        // }
 
         document.addEventListener("keydown", this.onKeyDown);
 
@@ -69,6 +69,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
 
     @action
     onKeyDown = (e: KeyboardEvent): void => {
+        console.log("CELL keydown");
         if (this.props.isFocused && this.props.isEditable) {
             document.removeEventListener("keydown", this.onKeyDown);
             this._isEditing = true;
@@ -139,10 +140,10 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             addDocTab: this.props.addDocTab,
         };
 
-        let onItemDown = (e: React.PointerEvent) => {
-            SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
-                this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
-        };
+        // let onItemDown = (e: React.PointerEvent) => {
+        //     SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
+        //         this._document[props.fieldKey] instanceof Doc ? (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc) : this.props.moveDocument, this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
+        // };
         let onPointerEnter = (e: React.PointerEvent): void => {
             if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) {
                 dragRef!.current!.className = "doc-drag-over";
@@ -163,10 +164,15 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             contents = typeof field === "object" ? doc ? StrCast(doc.title) === "" ? "--" : StrCast(doc.title) : `--${typeof field}--` : `--${typeof field}--`;
         }
 
+        let className = "collectionSchemaView-cellWrapper";
+        if (this._isEditing) className += " editing";
+        if (this.props.isFocused && this.props.isEditable) className += " focused";
+        if (this.props.isFocused && !this.props.isEditable) className += " inactive";
+
         return (
             <div className="" ref={dragRef} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
-                <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
-                    <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef: null} onPointerDown={onItemDown} key={props.Document[Id]}>
+                <div className={className} ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+                    <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef : null} key={props.Document[Id]}>
                         <EditableView
                             editing={this._isEditing}
                             isEditingCallback={this.isEditingCallback}
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index beae739ec..6d388bb40 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -7,6 +7,7 @@ import { DragManager, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Cast, FieldValue, StrCast } from "../../../new_fields/Types";
 import { ContextMenu } from "../ContextMenu";
+import { action } from "mobx";
 
 
 export interface MovableColumnProps {
@@ -106,7 +107,7 @@ export interface MovableRowProps {
     rowInfo: RowInfo;
     ScreenToLocalTransform: () => Transform;
     addDoc: (doc: Doc, relativeTo?: Doc, before?: boolean) => boolean;
-    moveDoc: DragManager.MoveFunction;
+    removeDoc: (doc: Doc) => boolean;
     rowFocused: boolean;
     textWrapRow: (doc: Doc) => void;
     rowWrapped: boolean;
@@ -145,9 +146,6 @@ export class MovableRow extends React.Component<MovableRowProps> {
     }
 
     rowDrop = (e: Event, de: DragManager.DropEvent) => {
-        // const { children = null, rowInfo } = this.props;
-        // if (!rowInfo) return false;
-
         const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc));
         if (!rowDoc) return false;
 
@@ -160,24 +158,26 @@ export class MovableRow extends React.Component<MovableRowProps> {
             e.stopPropagation();
             if (de.data.draggedDocuments[0] === rowDoc) return true;
             let addDocument = (doc: Doc) => this.props.addDoc(doc, rowDoc, before);
-            let movedDocs = de.data.draggedDocuments; //(de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
+            let movedDocs = de.data.draggedDocuments;
             return (de.data.dropAction || de.data.userDropAction) ?
                 de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
                 : (de.data.moveDocument) ?
                     movedDocs.reduce((added: boolean, d) => de.data.moveDocument(d, rowDoc, addDocument) || added, false)
-                    // movedDocs.reduce((added: boolean, d) => this.props.moveDoc(d, rowDoc, addDocument) || added, false)
                     : de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false);
         }
         return false;
     }
 
     onRowContextMenu = (e: React.MouseEvent): void => {
-        // const { rowInfo } = this.props;
-        // const { textWrapRow, original } = rowInfo;
         let description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row";
         ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original) });
     }
 
+    @action
+    move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => {
+        return doc !== target && this.props.removeDoc(doc) && addDoc(doc);
+    }
+
     render() {
         const { children = null, rowInfo } = this.props;
         if (!rowInfo) {
@@ -189,7 +189,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
         if (!doc) return <></>;
 
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => doc, this.props.moveDoc);
+        let onItemDown = SetupDrag(reference, () => doc, this.move);
 
         let className = "collectionSchema-row";
         if (this.props.rowFocused) className += " row-focused";
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 410790197..c2b0d8f42 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -148,7 +148,7 @@
         padding: 0;
         font-size: 13px;
         text-align: center;
-        // white-space: normal;
+        white-space: normal;
 
         .imageBox-cont {
             position: relative;
@@ -196,8 +196,6 @@
 .collectionSchemaView-header {
     height: 100%;
     color: gray;
-    letter-spacing: 2px;
-    text-transform: uppercase;
 
     .collectionSchema-header-menu {
         height: 100%;
@@ -206,16 +204,18 @@
             width: 100%;
             height: 100%;
             padding: 4px;
+            letter-spacing: 2px;
+            text-transform: uppercase;
 
             svg {
                 margin-right: 4px;
             }
         }
 
-        div[class*="css"] {
-            width: 100%;
-            height: 100%;
-        }
+        // div[class*="css"] {
+        //     width: 100%;
+        //     height: 100%;
+        // }
     }
 }
 
@@ -287,12 +287,6 @@ button.add-column {
         background-color: $light-color-secondary;
     }
 
-    &.row-wrapped {
-        .rt-td {
-            white-space: normal;
-        }
-    }
-
     .row-dragger {
         // height: $MAX_ROW_HEIGHT;
     }
@@ -309,6 +303,10 @@ button.add-column {
         &.row-inside {
             border: 1px solid red;
         }
+
+        .row-dragging {
+            background-color: blue;
+        }
     }
 }
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 62e4ceb54..a7e435ac6 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -344,7 +344,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         addDocTab: this.props.addDocTab,
                         moveDocument: this.props.moveDocument,
                         setIsEditing: this.setCellIsEditing,
-                        isEditable: isEditable
+                        isEditable: isEditable,
                     };
 
                     let colType = this.getColumnType(col);
@@ -393,13 +393,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     tableAddDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
-        console.log("table add doc");
         return Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
     }
 
-    tableMoveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => {
-        console.log("SCHEMA MOVE", StrCast(d.title), StrCast(target.title));
-        this.props.moveDocument(d, target, addDoc);
+    tableRemoveDoc = (document: Doc): boolean => {
+        let index = this.props.childDocs.findIndex(d => d === document);
+        if (index !== -1) {
+            this.props.childDocs.splice(index, 1);
+            return true;
+        }
+        return false;
     }
 
     private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
@@ -410,7 +413,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         return {
             ScreenToLocalTransform: this.props.ScreenToLocalTransform,
             addDoc: this.tableAddDoc,
-            moveDoc: this.tableMoveDoc,
+            removeDoc: this.tableRemoveDoc,
             rowInfo,
             rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document),
             textWrapRow: this.textWrapRow,
@@ -467,6 +470,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     onKeyDown = (e: KeyboardEvent): void => {
+        console.log("schema keydown", !this._cellIsEditing, !this._headerIsEditing, this.props.isFocused(this.props.Document));
         if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected()) {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
@@ -504,7 +508,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     changeFocusedCellByIndex = (row: number, col: number): void => {
         this._focusedCell = { row: row, col: col };
         this.props.setFocused(this.props.Document);
-        // console.log("changed cell by index", StrCast(this.props.Document.title));
     }
 
     @action
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 5ae0753d8..eba1d4f04 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -267,21 +267,28 @@ export namespace Doc {
 
     export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean) {
         if (target[key] === undefined) {
+            console.log("target key undefined");
             Doc.GetProto(target)[key] = new List<Doc>();
         }
         let list = Cast(target[key], listSpec(Doc));
         if (list) {
+            console.log("has list");
             if (allowDuplicates !== true) {
                 let pind = list.reduce((l, d, i) => d instanceof Doc && Doc.AreProtosEqual(d, doc) ? i : l, -1);
                 if (pind !== -1) {
                     list.splice(pind, 1);
                 }
             }
-            if (first) list.splice(0, 0, doc);
+            if (first) {
+                console.log("is first");
+                list.splice(0, 0, doc);
+            }
             else {
+                console.log("not first");
                 let ind = relativeTo ? list.indexOf(relativeTo) : -1;
                 if (ind === -1) list.push(doc);
                 else list.splice(before ? ind : ind + 1, 0, doc);
+                console.log("index", ind);
             }
         }
         return true;
-- 
cgit v1.2.3-70-g09d2


From 779938dd613d81bfb773f14cd4e43362f0aa8b24 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Wed, 24 Jul 2019 22:08:31 -0400
Subject: minor schema stylign

---
 .../views/collections/CollectionSchemaCells.tsx    | 20 +++------------
 .../views/collections/CollectionSchemaView.scss    | 29 ++++++++++++++++------
 .../views/collections/CollectionSchemaView.tsx     | 24 +++++++++++++++---
 3 files changed, 46 insertions(+), 27 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index bc84da140..d453fed47 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -42,23 +42,12 @@ export interface CellProps {
 
 @observer
 export class CollectionSchemaCell extends React.Component<CellProps> {
-    @observable protected _isEditing: boolean = this.props.isEditing ? true : false;
+    @observable protected _isEditing: boolean = false;
     protected _focusRef = React.createRef<HTMLDivElement>();
     protected _document = this.props.rowProps.original;
     private _dropDisposer?: DragManager.DragDropDisposer;
 
     componentDidMount() {
-        // if (this._focusRef.current) {
-        //     if (this.props.isFocused) {
-        //         this._focusRef.current.className += " focused";
-        //         if (!this.props.isEditable) {
-        //             this._focusRef.current.className += " inactive";
-        //         }
-        //     } else {
-        //         this._focusRef.current.className = "collectionSchemaView-cellWrapper";
-        //     }
-        // }
-
         document.addEventListener("keydown", this.onKeyDown);
 
     }
@@ -69,7 +58,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
 
     @action
     onKeyDown = (e: KeyboardEvent): void => {
-        console.log("CELL keydown");
         if (this.props.isFocused && this.props.isEditable) {
             document.removeEventListener("keydown", this.onKeyDown);
             this._isEditing = true;
@@ -146,11 +134,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         // };
         let onPointerEnter = (e: React.PointerEvent): void => {
             if (e.buttons === 1 && SelectionManager.GetIsDragging() && (type === "document" || type === undefined)) {
-                dragRef!.current!.className = "doc-drag-over";
+                dragRef!.current!.className = "collectionSchemaView-cellContainer doc-drag-over";
             }
         };
         let onPointerLeave = (e: React.PointerEvent): void => {
-            dragRef!.current!.className = "";
+            dragRef!.current!.className = "collectionSchemaView-cellContainer";
         };
 
         let field = props.Document[props.fieldKey];
@@ -170,7 +158,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         if (this.props.isFocused && !this.props.isEditable) className += " inactive";
 
         return (
-            <div className="" ref={dragRef} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
+            <div className="collectionSchemaView-cellContainer" ref={dragRef} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
                 <div className={className} ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
                     <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef : null} key={props.Document[Id]}>
                         <EditableView
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index c2b0d8f42..3bc1bc060 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -75,7 +75,7 @@
             // color: $light-color;
             font-size: 12px;
             height: 30px;
-            border: 1px solid $intermediate-color;
+            // border: 1px solid $intermediate-color;
             box-shadow: none;
         }
 
@@ -95,6 +95,8 @@
 
         .rt-th {
             padding: 0;
+            border: solid lightgray;
+            border-width: 0 1px;
         }
     }
 
@@ -117,6 +119,10 @@
         direction: ltr;
         flex: 0 1 auto;
         min-height: 30px;
+        border: 0 !important;
+        // border: solid lightgray;
+        // border-width: 1px 0;
+        // border-left: 1px solid lightgray;
         // max-height: $MAX_ROW_HEIGHT;
         // for sub comp
 
@@ -128,10 +134,11 @@
         //     background-color: $light-color-secondary;
         // }
 
+        &:first-child {
+            border-top: 1px solid $light-color-secondary !important;
+        }
         &:last-child {
-            border-bottom: $intermediate-color;
-            border-bottom-style: solid;
-            border-bottom-width: 1;
+            border-bottom: 1px solid $light-color-secondary !important;
         }
     }
 
@@ -142,8 +149,10 @@
     }
 
     .rt-td {
-        border-width: 1px;
-        border-right-color: $intermediate-color;
+        // border: 1px solid $light-color-secondary !important;
+        // border-width: 0 1px;
+        // border-width: 1px;
+        // border-right-color: $intermediate-color;
         // max-height: $MAX_ROW_HEIGHT;
         padding: 0;
         font-size: 13px;
@@ -284,7 +293,7 @@ button.add-column {
     height: 100%;
 
     &.row-focused {
-        background-color: $light-color-secondary;
+        background-color: rgb(253, 191, 191);//$light-color-secondary;
     }
 
     .row-dragger {
@@ -310,6 +319,10 @@ button.add-column {
     }
 }
 
+.collectionSchemaView-cellContainer {
+    width: 100%;
+    height: 100%;
+}
 
 .collectionSchemaView-cellWrapper {
     height: 100%;
@@ -321,7 +334,7 @@ button.add-column {
 
     &.focused {
         // background-color: yellowgreen;
-        border: 2px solid yellowgreen;
+        // border: 2px solid yellowgreen;
 
         input {
             outline: 0;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a7e435ac6..87a4a0c6a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -292,7 +292,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 {
                     expander: true,
                     Header: "",
-                    width: 45,
+                    width: 30,
                     Expander: (rowInfo) => {
                         if (rowInfo.original.type === "collection") {
                             if (rowInfo.isExpanded) return <div className="collectionSchemaView-expander" onClick={() => this.onCloseCollection(rowInfo.original)}><FontAwesomeIcon icon={"sort-up"} size="sm" /></div>;
@@ -421,6 +421,25 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         };
     }
 
+    private getTdProps: ComponentPropsGetterR = (state, rowInfo, column, instance) => {
+        if (!rowInfo) return {};
+        if (!column) return {};
+
+        let row = rowInfo.index;
+        let col = this.columns.indexOf(column.id);
+        // let col = column ? this.columns.indexOf(column!) : -1;
+        let isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document);
+        // let column = this.columns.indexOf(column.id!);
+
+        console.log("td style", row, col, this._focusedCell.row, this._focusedCell.col);
+
+        return {
+            style: {
+                border: !this._headerIsEditing && isFocused ? "2px solid black" : "1px solid #f1efeb"
+            }
+        };
+    }
+
     // private createTarget = (ele: HTMLDivElement) => {
     //     this._mainCont = ele;
     //     this.props.CreateDropTarget(ele);
@@ -456,7 +475,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     onPointerDown = (e: React.PointerEvent): void => {
-        // console.log("pointer down", StrCast(this.props.Document.title));
         this.props.setFocused(this.props.Document);
         if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
             if (this.props.isSelected()) e.stopPropagation();
@@ -470,7 +488,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     onKeyDown = (e: KeyboardEvent): void => {
-        console.log("schema keydown", !this._cellIsEditing, !this._headerIsEditing, this.props.isFocused(this.props.Document));
         if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected()) {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
@@ -645,6 +662,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             showPagination={false}
             columns={this.tableColumns}
             getTrProps={this.getTrProps}
+            getTdProps={this.getTdProps}
             sortable={false}
             TrComponent={MovableRow}
             sorted={Array.from(this._sortedColumns.values())}
-- 
cgit v1.2.3-70-g09d2


From 2d62ca0060c9ef7d3932e8681deb09cc3acf6d48 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Thu, 25 Jul 2019 11:47:23 -0400
Subject: schema stylign

---
 .../CollectionSchemaMovableTableHOC.tsx            | 10 +--
 .../views/collections/CollectionSchemaView.scss    | 82 +++++++++++++++++-----
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 src/client/views/collections/CollectionView.tsx    |  2 +-
 4 files changed, 73 insertions(+), 23 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 290958cd0..70d6fbc7b 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -9,10 +9,10 @@ import { Cast, FieldValue, StrCast } from "../../../new_fields/Types";
 import { ContextMenu } from "../ContextMenu";
 import { action } from "mobx";
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faGripVertical } from '@fortawesome/free-solid-svg-icons';
+import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 
-library.add(faGripVertical);
+library.add(faGripVertical, faTrash);
 
 export interface MovableColumnProps {
     columnRenderer: TableCellRenderer;
@@ -198,13 +198,15 @@ export class MovableRow extends React.Component<MovableRowProps> {
         let className = "collectionSchema-row";
         if (this.props.rowFocused) className += " row-focused";
         if (this.props.rowWrapped) className += " row-wrapped";
+        // if (!this.props.rowWrapped) className += " row-unwrapped";
 
         return (
             <div className={className} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}>
                 <div className="collectionSchema-row-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
                     <ReactTableDefaults.TrComponent>
-                        <div className="row-dragger" ref={reference} onPointerDown={onItemDown}>
-                            <FontAwesomeIcon icon={"grip-vertical"} size="sm" />
+                        <div className="row-dragger">
+                            <div className="row-option" onClick={() => this.props.removeDoc(this.props.rowInfo.original)}><FontAwesomeIcon icon="trash" size="sm" /></div>
+                            <div className="row-option" style={{ cursor: "grab" }} ref={reference} onPointerDown={onItemDown}><FontAwesomeIcon icon="grip-vertical" size="sm" /></div>
                         </div>
                         {children}
                     </ReactTableDefaults.TrComponent>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 22d8a5cb6..9ad52db4c 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -8,7 +8,7 @@
     box-sizing: border-box;
     // position: absolute;
     width: 100%;
-    // height: calc(100% - 25px);
+    height: calc(100% - 50px);
     // overflow: hidden;
     overflow-x: scroll;
     border: none;
@@ -55,7 +55,7 @@
 }
 
 .ReactTable {
-    width: 100%;
+    width: 100% !important;
     height: 100%;
     background: white;
     box-sizing: border-box;
@@ -70,8 +70,8 @@
     }
 
     .rt-thead {
-        width: calc(100% - 30px);
-        margin-left: 30px;
+        width: calc(100% - 50px);
+        margin-left: 50px;
 
         &.-header {
             // background: $intermediate-color;
@@ -118,6 +118,7 @@
 
     .rt-tbody {
         direction: rtl;
+        overflow: visible;
     }
 
     .rt-tr-group {
@@ -139,12 +140,12 @@
         //     background-color: $light-color-secondary;
         // }
 
-        &:first-child {
-            border-top: 1px solid $light-color-secondary !important;
-        }
-        &:last-child {
-            border-bottom: 1px solid $light-color-secondary !important;
-        }
+        // &:first-child {
+        //     border-top: 1px solid $light-color-secondary !important;
+        // }
+        // &:last-child {
+        //     border-bottom: 1px solid $light-color-secondary !important;
+        // }
     }
 
     .rt-tr {
@@ -162,7 +163,8 @@
         padding: 0;
         font-size: 13px;
         text-align: center;
-        white-space: normal;
+        
+        // white-space: normal;
 
         .imageBox-cont {
             position: relative;
@@ -296,17 +298,46 @@ button.add-column {
 .collectionSchema-row {
     // height: $MAX_ROW_HEIGHT;
     height: 100%;
+    background-color: white;
 
     &.row-focused {
-        background-color: rgb(253, 191, 191);//$light-color-secondary;
+        background-color: rgb(255, 246, 246);//$light-color-secondary;
+    }
+
+    &.row-wrapped {
+        white-space: normal;
     }
 
     .row-dragger {
+        display: flex;
+        justify-content: space-evenly;
         // height: $MAX_ROW_HEIGHT;
-        width: 30px;
+        flex: 50 0 auto;
+        width: 50px;
+        max-width: 50px;
         height: 100%;
-        padding: 10px;
-        color: gray;
+        min-height: 30px;
+        // padding: 5px 5px 5px 0;
+        color: lightgray;
+        background-color: white;
+        transition: color 0.1s ease;
+
+        // &:hover {
+        //     color: lightgray;
+        // }
+
+        .row-option {
+            // padding: 5px;
+            cursor: pointer;
+            transition: color 0.1s ease;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+
+            &:hover {
+                color: gray;
+            }
+        }
     }
 
     .collectionSchema-row-wrapper {
@@ -369,6 +400,7 @@ button.add-column {
 }
 
 .collectionSchemaView-toolbar {
+    height: 50px;
     display: flex;
     justify-content: flex-end;
 }
@@ -379,8 +411,24 @@ button.add-column {
 }
 
 .sub {
-    padding: 20px;
-    background-color: $intermediate-color;
+    padding: 10px 30px;
+    // padding-left: 80px;
+    background-color: rgb(252, 252, 252);
+    width: calc(100% - 50px);
+    margin-left: 50px;
+
+    .rt-table {
+        overflow-x: hidden; // todo; this shouldnt be like this :((
+        overflow-y: visible;
+    } // TODO fix
+
+    .row-dragger {
+        background-color: rgb(252, 252, 252);
+    }
+
+    .rt-table {
+        background-color: rgb(252, 252, 252);
+    }
 }
 
 .collectionSchemaView-expander {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 87a4a0c6a..a8692ee95 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -435,7 +435,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         return {
             style: {
-                border: !this._headerIsEditing && isFocused ? "2px solid black" : "1px solid #f1efeb"
+                border: !this._headerIsEditing && isFocused ? "2px solid rgb(255, 160, 160)" : "1px solid #f1efeb"
             }
         };
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 62d721868..df8a1ebc1 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -62,7 +62,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
         }
         else {
             return [
-                (<CollectionViewBaseChrome CollectionView={this} type={type} collapse={this.collapse} />),
+                // (<CollectionViewBaseChrome CollectionView={this} type={type} collapse={this.collapse} />),
                 this.SubViewHelper(type, renderProps)
             ];
         }
-- 
cgit v1.2.3-70-g09d2


From d583b473181c9e97b4626c302dc9a167fa64a17c Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Thu, 25 Jul 2019 12:43:24 -0400
Subject: some preview stuff

---
 .../views/collections/CollectionSchemaView.scss    | 32 ++++++++++++++++------
 .../views/collections/CollectionSchemaView.tsx     | 19 +++++++++----
 2 files changed, 37 insertions(+), 14 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 9ad52db4c..98ec971ef 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -40,22 +40,23 @@
 
     .collectionSchemaView-dividerDragger {
         position: relative;
-        background: black;
         float: left;
-        height: 37px;
+        height: 100%;
         width: 20px;
         z-index: 20;
         right: 0;
         top: 0;
-        background: $main-accent;
-        box-sizing: border-box;
-        border-left: 1px solid $intermediate-color;
-        border-right: 1px solid $intermediate-color;
+        background: gray;
+        cursor: col-resize;
+        // background: $main-accent;
+        // box-sizing: border-box;
+        // border-left: 1px solid $intermediate-color;
+        // border-right: 1px solid $intermediate-color;
     }
 }
 
 .ReactTable {
-    width: 100% !important;
+    width: 100%;
     height: 100%;
     background: white;
     box-sizing: border-box;
@@ -400,9 +401,16 @@ button.add-column {
 }
 
 .collectionSchemaView-toolbar {
-    height: 50px;
+    height: 30px;
     display: flex;
     justify-content: flex-end;
+    padding: 0 10px;
+
+    .collectionSchemaView-toolbar-item {
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
 }
 
 #preview-schema-checkbox-div {
@@ -410,6 +418,10 @@ button.add-column {
     font-size: 12px;
 }
 
+.collectionSchemaView-table {
+    width: calc(100% - 7px);
+}
+
 .sub {
     padding: 10px 30px;
     // padding-left: 80px;
@@ -429,6 +441,10 @@ button.add-column {
     .rt-table {
         background-color: rgb(252, 252, 252);
     }
+
+    .collectionSchemaView-table {
+        width: 100%;
+    }
 }
 
 .collectionSchemaView-expander {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a8692ee95..ed2c88f19 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -66,7 +66,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     private DIVIDER_WIDTH = 4;
 
     @observable previewScript: string = "";
-    @observable previewDoc: Doc | undefined = this.childDocs.length ? this.childDocs[0] : undefined;
+    @observable previewDoc: Doc | undefined = undefined;
     @observable private _node: HTMLDivElement | null = null;
     @observable private _focusedTable: Doc = this.props.Document;
 
@@ -100,6 +100,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @action
     setPreviewDoc = (doc: Doc): void => {
+        console.log("set");
         this.previewDoc = doc;
     }
 
@@ -147,6 +148,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     get previewDocument(): Doc | undefined {
         let selected = this.previewDoc;
         let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
+        console.log("preview document", pdc);
         return pdc;
     }
 
@@ -209,6 +211,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 isSelected={this.props.isSelected}
                 isFocused={this.isFocused}
                 setFocused={this.setFocused}
+                setPreviewDoc={this.setPreviewDoc}
             />
         );
     }
@@ -217,7 +220,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     get schemaToolbar() {
         return (
             <div className="collectionSchemaView-toolbar">
-                <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />Show Preview</div>
+                <div className="collectionSchemaView-toolbar-item">
+                    <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />Show Preview</div>
+                </div>
             </div>
         );
     }
@@ -258,6 +263,7 @@ export interface SchemaTableProps {
     isSelected: () => boolean;
     isFocused: (document: Doc) => boolean;
     setFocused: (document: Doc) => void;
+    setPreviewDoc: (document: Doc) => void;
 }
 
 @observer
@@ -430,9 +436,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         // let col = column ? this.columns.indexOf(column!) : -1;
         let isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document);
         // let column = this.columns.indexOf(column.id!);
-
-        console.log("td style", row, col, this._focusedCell.row, this._focusedCell.col);
-
         return {
             style: {
                 border: !this._headerIsEditing && isFocused ? "2px solid rgb(255, 160, 160)" : "1px solid #f1efeb"
@@ -519,12 +522,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 this._focusedCell = { row: this._focusedCell.row + 1 === this.props.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
                 break;
         }
+        let doc = this.props.childDocs[this._focusedCell.row];
+        this.props.setPreviewDoc(doc);
     }
 
     @action
     changeFocusedCellByIndex = (row: number, col: number): void => {
         this._focusedCell = { row: row, col: col };
         this.props.setFocused(this.props.Document);
+        let doc = this.props.childDocs[this._focusedCell.row];
+        this.props.setPreviewDoc(doc);
     }
 
     @action
@@ -647,7 +654,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @computed
     get reactTable() {
-        let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
+        let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false);
         let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc[Id] === col).toString());
         let expanded = {};
-- 
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/CollectionSchemaView.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 bf5911a4de0b6f7e3d73b91b747bfeec89ff4b94 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Thu, 25 Jul 2019 12:58:26 -0400
Subject: minor updates

---
 src/client/views/collections/CollectionSchemaMovableTableHOC.tsx | 6 +++++-
 src/client/views/collections/CollectionSchemaView.tsx            | 2 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 70d6fbc7b..f45575143 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -90,6 +90,10 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
         return onItemDown;
     }
 
+    // onColDrag = (e: React.DragEvent, ref: React.RefObject<HTMLDivElement>) => {
+    //     this.setupDrag(reference);
+    // }
+
 
     render() {
         let reference = React.createRef<HTMLDivElement>();
@@ -98,7 +102,7 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
         return (
             <div className="collectionSchema-col" ref={this.createColDropTarget}>
                 <div className="collectionSchema-col-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
-                    <div className="col-dragger" ref={reference} onPointerDown={onItemDown}>
+                    <div className="col-dragger" ref={reference} onPointerDown={onItemDown} >
                         {this.props.columnRenderer}
                     </div>
                 </div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ed2c88f19..ab1c85416 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -212,6 +212,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 isFocused={this.isFocused}
                 setFocused={this.setFocused}
                 setPreviewDoc={this.setPreviewDoc}
+                deleteDocument={this.props.removeDocument}
             />
         );
     }
@@ -254,6 +255,7 @@ export interface SchemaTableProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     fieldKey: string;
     renderDepth: number;
+    deleteDocument: (document: Doc) => boolean;
     moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
     ScreenToLocalTransform: () => Transform;
     // CreateDropTarget: (ele: HTMLDivElement)=> void; // super createdriotarget
-- 
cgit v1.2.3-70-g09d2


From 344e2563477fc4524cb287b55a9d5f29d64d4e14 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Thu, 25 Jul 2019 15:56:18 -0400
Subject: deletign docs is fine in schema

---
 .../views/collections/CollectionSchemaView.tsx     | 52 ++++++++++++++--------
 1 file changed, 34 insertions(+), 18 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ab1c85416..aa36b8584 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -198,7 +198,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 Document={this.props.Document} // child doc
                 PanelHeight={this.props.PanelHeight}
                 PanelWidth={this.props.PanelWidth}
-                childDocs={this.childDocs}
+                // childDocs={this.childDocs}
                 CollectionView={this.props.CollectionView}
                 ContainingCollectionView={this.props.ContainingCollectionView}
                 fieldKey={this.props.fieldKey} // might just be this.
@@ -213,6 +213,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 setFocused={this.setFocused}
                 setPreviewDoc={this.setPreviewDoc}
                 deleteDocument={this.props.removeDocument}
+                dataDoc={this.props.DataDoc}
             />
         );
     }
@@ -248,9 +249,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
 export interface SchemaTableProps {
     Document: Doc; // child doc
+    dataDoc?: Doc;
     PanelHeight: () => number;
     PanelWidth: () => number;
-    childDocs: Doc[];
+    // childDocs: Doc[];
     CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     fieldKey: string;
@@ -295,7 +297,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let focusedCol = this._focusedCell.col;
         let isEditable = !this._headerIsEditing;// && this.props.isSelected();
 
-        if (this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) {
+        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = DocListCast(cdoc[this.props.fieldKey]);
+
+        if (children.reduce((found, doc) => found || doc.type === "collection", false)) {
             columns.push(
                 {
                     expander: true,
@@ -405,9 +410,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     tableRemoveDoc = (document: Doc): boolean => {
-        let index = this.props.childDocs.findIndex(d => d === document);
-        if (index !== -1) {
-            this.props.childDocs.splice(index, 1);
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        if (children.indexOf(document) !== -1) {
+            children.splice(children.indexOf(document), 1);
             return true;
         }
         return false;
@@ -422,6 +428,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             ScreenToLocalTransform: this.props.ScreenToLocalTransform,
             addDoc: this.tableAddDoc,
             removeDoc: this.tableRemoveDoc,
+            // removeDoc: this.props.deleteDocument,
             rowInfo,
             rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document),
             textWrapRow: this.textWrapRow,
@@ -501,9 +508,11 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeFocusedCellByDirection = (direction: string): void => {
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
         switch (direction) {
             case "tab":
-                if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.props.childDocs.length) {
+                if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) {
                     this._focusedCell = { row: 0, col: 0 };
                 } else if (this._focusedCell.col + 1 === this.columns.length) {
                     this._focusedCell = { row: this._focusedCell.row + 1, col: 0 };
@@ -521,19 +530,23 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col };
                 break;
             case "down":
-                this._focusedCell = { row: this._focusedCell.row + 1 === this.props.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
+                this._focusedCell = { row: this._focusedCell.row + 1 === children.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
                 break;
         }
-        let doc = this.props.childDocs[this._focusedCell.row];
-        this.props.setPreviewDoc(doc);
+        const pdoc = FieldValue(children[this._focusedCell.row]);
+        pdoc && this.props.setPreviewDoc(pdoc);
     }
 
     @action
     changeFocusedCellByIndex = (row: number, col: number): void => {
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+
         this._focusedCell = { row: row, col: col };
         this.props.setFocused(this.props.Document);
-        let doc = this.props.childDocs[this._focusedCell.row];
-        this.props.setPreviewDoc(doc);
+
+        const fdoc = FieldValue(children[this._focusedCell.row]);
+        fdoc && this.props.setPreviewDoc(fdoc);
     }
 
     @action
@@ -656,18 +669,21 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @computed
     get reactTable() {
+        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = DocListCast(cdoc[this.props.fieldKey]);
+
         let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
-        let hasCollectionChild = this.props.childDocs.reduce((found, doc) => found || doc.type === "collection", false);
-        let expandedRowsList = this._openCollections.map(col => this.props.childDocs.findIndex(doc => doc[Id] === col).toString());
+        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 = {};
         expandedRowsList.forEach(row => expanded[row] = true);
         console.log(...[...this._textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :((((
 
         return <ReactTable
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
-            data={this.props.childDocs}
+            data={children}
             page={0}
-            pageSize={this.props.childDocs.length}
+            pageSize={children.length}
             showPagination={false}
             columns={this.tableColumns}
             getTrProps={this.getTrProps}
@@ -679,8 +695,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             SubComponent={hasCollectionChild ?
                 row => {
                     if (row.original.type === "collection") {
-                        let childDocs = DocListCast(row.original[this.props.fieldKey]);
-                        return <div className="sub"><SchemaTable {...this.props} Document={row.original} childDocs={childDocs} /></div>;
+                        // let childDocs = DocListCast(row.original[this.props.fieldKey]);
+                        return <div className="sub"><SchemaTable {...this.props} Document={row.original} /></div>;
                     }
                 }
                 : undefined}
-- 
cgit v1.2.3-70-g09d2


From d7444d7de920a0081a54042db32702273c91865e Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Fri, 26 Jul 2019 17:58:11 -0400
Subject: clicking cell will focus table

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

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 60644b741..c6550560a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -101,7 +101,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @action
     setPreviewDoc = (doc: Doc): void => {
-        console.log("set");
         this.previewDoc = doc;
     }
 
@@ -136,6 +135,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     onPointerDown = (e: React.PointerEvent): void => {
         if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
             if (this.props.isSelected()) e.stopPropagation();
+            else {
+                this.props.select(false);
+            }
         }
     }
 
@@ -149,7 +151,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     get previewDocument(): Doc | undefined {
         let selected = this.previewDoc;
         let pdc = selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
-        console.log("preview document", pdc);
         return pdc;
     }
 
@@ -231,7 +232,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
 
     render() {
-
         // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
         // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
         return (
@@ -549,7 +549,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     createRow = () => {
-        console.log("creating row");
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
 
@@ -679,6 +678,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @computed
     get reactTable() {
+
         let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         let children = DocListCast(cdoc[this.props.fieldKey]);
 
-- 
cgit v1.2.3-70-g09d2


From eb24b07405b902f34f9b335ef86f5ec2c6d7d062 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Fri, 26 Jul 2019 22:16:57 -0400
Subject: ui improvements

---
 src/client/views/ContextMenu.scss                  | 48 +++++++++++++++++-----
 src/client/views/ContextMenu.tsx                   |  4 +-
 src/client/views/ContextMenuItem.tsx               |  6 +--
 src/client/views/MainView.tsx                      |  2 +-
 .../views/collections/CollectionSchemaView.tsx     |  6 +--
 .../views/collections/CollectionTreeView.tsx       |  8 ++--
 src/client/views/collections/CollectionView.tsx    |  5 ++-
 src/client/views/nodes/DocumentView.tsx            | 23 +++++++----
 src/client/views/nodes/FormattedTextBox.tsx        |  6 +--
 src/client/views/nodes/IconBox.tsx                 | 10 +++--
 src/client/views/nodes/VideoBox.tsx                |  6 ++-
 src/client/views/search/SearchItem.tsx             |  7 ++--
 12 files changed, 85 insertions(+), 46 deletions(-)

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

diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 254163b53..195304b2c 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -6,6 +6,9 @@
     z-index: $contextMenu-zindex;
     box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
     flex-direction: column;
+    background: whitesmoke;
+    padding-bottom: 10px;
+    border-radius: 15px;
 }
 
 // .contextMenu-item:first-child {
@@ -33,7 +36,7 @@
 .contextMenu-item {
     // width: 11vw; //10vw
     height: 30px; //2vh
-    background: #DDDDDD;
+    background: whitesmoke;
     display: flex; //comment out to allow search icon to be inline with search text
     justify-content: left;
     align-items: center;
@@ -44,13 +47,22 @@
     -ms-user-select: none;
     user-select: none;
     transition: all .1s;
+    border-style: none;
+    // padding: 10px 0px 10px 0px;
+    white-space: nowrap;
+    font-size: 13px;
+    color: grey;
+    letter-spacing: 2px;
+    text-transform: uppercase;
+    padding-right: 10px;
+}
+
+.contextMenu-item:hover {
     border-width: .11px;
     border-style: none;
     border-color: $intermediate-color; //  rgb(187, 186, 186);
     border-bottom-style: solid;
-    // padding: 10px 0px 10px 0px;
-    white-space: nowrap;
-    font-size: 20px;
+    border-top-style: solid;
 }
 
 .contextMenu-itemSelected {
@@ -60,7 +72,7 @@
 .contextMenu-group {
     // width: 11vw; //10vw
     height: 30px; //2vh
-    background: rgb(200, 200, 200);
+    background: lightgoldenrodyellow;
     display: flex; //comment out to allow search icon to be inline with search text
     justify-content: left;
     align-items: center;
@@ -74,27 +86,41 @@
     border-width: .11px;
     border-style: none;
     border-color: $intermediate-color; //  rgb(187, 186, 186);
-    border-bottom-style: solid;
     // padding: 10px 0px 10px 0px;
     white-space: nowrap;
-    font-size: 20px;
+    font-size: 13px;
+    text-transform: uppercase;
+    letter-spacing: 2px;
+    padding-left: 5px;
 }
 
 .contextMenu-item:hover {
-    transition: all 0.1s;
+    transition: all 0.1s ease;
     background: $lighter-alt-accent;
 }
 
 .contextMenu-description {
-    font-size: 20px;
+    margin-left: 5px;
     text-align: left;
     display: inline; //need this?
 }
 
+.search-icon {
+    margin: 10px;
+}
+
+.search {
+    margin-left: 10px;
+    padding-left: 10px;
+    border: solid black 1px;
+    border-radius: 5px;
+}
+
 .icon-background {
     pointer-events: none;
-    background-color: #DDDDDD;
+    background-color: transparent;
     width: 35px;
     text-align: center;
-    font-size: 22px;
+    font-size: 20px;
+    margin-left: 5px;
 }
\ No newline at end of file
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index c163c56a0..5caf27327 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -165,11 +165,11 @@ export class ContextMenu extends React.Component {
 
         const contents = (
             <>
-                <span>
+                <span className={"search-icon"}>
                     <span className="icon-background">
                         <FontAwesomeIcon icon="search" size="lg" />
                     </span>
-                    <input className="contextMenu-item contextMenu-description" type="text" placeholder="Search . . ." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
+                    <input className="contextMenu-item contextMenu-description search" type="text" placeholder="Search . . ." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
                 </span>
                 {this.menuItems}
             </>
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 9bbb97d7e..4a7cd309d 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -10,14 +10,14 @@ library.add(faAngleRight);
 export interface OriginalMenuProps {
     description: string;
     event: () => void;
-    icon?: IconProp; //maybe should be optional (icon?)
+    icon: IconProp; //maybe should be optional (icon?)
     closeMenu?: () => void;
 }
 
 export interface SubmenuProps {
     description: string;
     subitems: ContextMenuProps[];
-    icon?: IconProp; //maybe should be optional (icon?)
+    icon: IconProp; //maybe should be optional (icon?)
     closeMenu?: () => void;
 }
 
@@ -94,7 +94,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
                     ) : null}
                     <div className="contextMenu-description">
                         {this.props.description}
-                        <FontAwesomeIcon icon={faAngleRight} size="lg" style={{ position: "absolute", right: "5px" }} />
+                        <FontAwesomeIcon icon={faAngleRight} size="lg" style={{ position: "absolute", right: "10px" }} />
                     </div>
                     {submenu}
                 </div>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 61a013963..8606b52b3 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -390,7 +390,7 @@ export class MainView extends React.Component {
         ];
         if (!ClientUtils.RELEASE) btns.unshift([React.createRef<HTMLDivElement>(), "cat", "Add Cat Image", addImageNode]);
 
-        return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 5 }} >
+        return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} >
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
             <label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Add Node"><p>+</p></label>
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 119aa7c19..91137f841 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,6 +1,6 @@
 import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
+import { faCog, faPlus, faTable } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
@@ -34,7 +34,7 @@ import { ComputedField } from "../../../new_fields/ScriptField";
 
 
 library.add(faCog);
-library.add(faPlus);
+library.add(faPlus, faTable);
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
 
 
@@ -321,7 +321,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     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 });
+            ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB, icon: "table" });
         }
     }
 
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index a1697f9b4..1c7fe4bee 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,5 +1,5 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faArrowsAltH, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
+import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faArrowsAltH, faCaretSquareDown, faCaretSquareRight, faTrashAlt, faPlus, faMinus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
@@ -61,7 +61,7 @@ library.add(faCaretRight);
 library.add(faCaretSquareDown);
 library.add(faCaretSquareRight);
 library.add(faArrowsAltH);
-
+library.add(faPlus, faMinus);
 @observer
 /**
  * Component that takes in a document prop and a boolean whether it's collapsed or not.
@@ -520,8 +520,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
     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() && this.props.Document.workspaceLibrary) { // excludeFromLibrary means this is the user document
-            ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()) });
-            ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)) });
+            ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()), icon: "plus" });
+            ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)), icon: "minus" });
             e.stopPropagation();
             e.preventDefault();
             ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 7781b26d9..0695029c7 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -17,6 +17,7 @@ import { CollectionStackingView } from './CollectionStackingView';
 import { CollectionTreeView } from "./CollectionTreeView";
 import { StrCast, PromiseValue } from '../../../new_fields/Types';
 import { DocumentType } from '../../documents/Documents';
+import { faEye } from '@fortawesome/free-regular-svg-icons';
 export const COLLECTION_BORDER_WIDTH = 2;
 
 library.add(faTh);
@@ -28,7 +29,7 @@ library.add(faThList);
 library.add(faFingerprint);
 library.add(faColumns);
 library.add(faEllipsisV);
-library.add(faImage);
+library.add(faImage, faEye);
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
@@ -68,7 +69,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
                     break;
                 }
             }
-            ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems });
+            ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" });
             ContextMenu.Instance.addItem({ description: "Apply Template", event: undoBatch(() => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight")), icon: "project-diagram" });
         }
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bae0b5b96..da72f212c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -39,6 +39,7 @@ import { OverlayView } from '../OverlayView';
 import { ScriptingRepl } from '../ScriptingRepl';
 import { ClientUtils } from '../../util/ClientUtils';
 import { EditableView } from '../EditableView';
+import { faHandPointer, faHandPointRight } from '@fortawesome/free-regular-svg-icons';
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 library.add(fa.faTrash);
@@ -60,7 +61,7 @@ library.add(fa.faCrosshairs);
 library.add(fa.faDesktop);
 library.add(fa.faUnlock);
 library.add(fa.faLock);
-library.add(fa.faLaptopCode);
+library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, faHandPointRight);
 
 
 // const linkSchema = createSchema({
@@ -547,11 +548,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         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: "edit" });
-        cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
-        cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Pos" : "Lock Pos", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
-        cm.addItem({ description: "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
-        cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" });
-        cm.addItem({
+        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" });
+        let makes: ContextMenuProps[] = [];
+        makes.push({ description: "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: "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" });
                 Doc.GetProto(this.props.Document).subBulletDocs = new List<Doc>([portal]);
@@ -562,6 +564,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 this.props.removeDocument && this.props.removeDocument(this.props.Document);
             }, icon: "window-restore"
         });
+        cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" });
         // cm.addItem({
         //     description: "Find aliases", event: async () => {
         //         const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
@@ -575,8 +578,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" });
         cm.addItem({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" });
         if (!ClientUtils.RELEASE) {
-            cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
-            cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
+            let copies: ContextMenuProps[] = [];
+            copies.push({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
+            copies.push({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
+            cm.addItem({ description: "Copy...", subitems: copies, icon: "copy" });
         }
         cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
         type User = { email: string, userDocumentId: string };
@@ -600,7 +605,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                             notifDoc.data = new List([sharedDoc]);
                         }
                     }
-                }
+                }, icon: "male"
             }));
         } catch {
 
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 0a79677e2..febb567e1 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,5 +1,5 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faEdit, faSmile } from '@fortawesome/free-solid-svg-icons';
+import { faEdit, faSmile, faTextHeight } from '@fortawesome/free-solid-svg-icons';
 import { action, IReactionDisposer, observable, reaction, runInAction, computed, trace } from "mobx";
 import { observer } from "mobx-react";
 import { baseKeymap } from "prosemirror-commands";
@@ -38,7 +38,7 @@ import { thisExpression } from 'babel-types';
 import { Utils } from '../../../Utils';
 
 library.add(faEdit);
-library.add(faSmile);
+library.add(faSmile, faTextHeight);
 
 // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
 //
@@ -462,7 +462,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             description: BoolCast(this.props.Document.autoHeight, false) ? "Manual Height" : "Auto Height",
             event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight, false)), icon: "expand-arrows-alt"
         });
-        ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems });
+        ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems, icon: "text-height" });
     }
     render() {
         let self = this;
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
index d6ab2a34a..64d869ecf 100644
--- a/src/client/views/nodes/IconBox.tsx
+++ b/src/client/views/nodes/IconBox.tsx
@@ -1,6 +1,6 @@
 import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTag, faTextHeight } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
@@ -18,7 +18,7 @@ library.add(faCaretUp);
 library.add(faObjectGroup);
 library.add(faStickyNote);
 library.add(faFilePdf);
-library.add(faFilm);
+library.add(faFilm, faTag, faTextHeight);
 
 @observer
 export class IconBox extends React.Component<FieldViewProps> {
@@ -47,13 +47,15 @@ export class IconBox extends React.Component<FieldViewProps> {
     specificContextMenu = (): void => {
         ContextMenu.Instance.addItem({
             description: BoolCast(this.props.Document.hideLabel) ? "Show label with icon" : "Remove label from icon",
-            event: this.setLabelField
+            event: this.setLabelField,
+            icon: "tag"
         });
         let maxDocs = DocListCast(this.props.Document.maximizedDocs);
         if (maxDocs.length === 1 && !BoolCast(this.props.Document.hideLabel)) {
             ContextMenu.Instance.addItem({
                 description: BoolCast(this.props.Document.useOwnTitle) ? "Use target title for label" : "Use own title label",
-                event: this.setUseOwnTitleField
+                event: this.setUseOwnTitleField,
+                icon: "text-height"
             });
         }
     }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 30ad75000..34cb47b20 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -19,10 +19,14 @@ import { positionSchema } from "./DocumentView";
 import { FieldView, FieldViewProps } from './FieldView';
 import { pageSchema } from "./ImageBox";
 import "./VideoBox.scss";
+import { library } from "@fortawesome/fontawesome-svg-core";
+import { faVideo } from "@fortawesome/free-solid-svg-icons";
 
 type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
 const VideoDocument = makeInterface(positionSchema, pageSchema);
 
+library.add(faVideo);
+
 @observer
 export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoDocument) {
     private _reactionDisposer?: IReactionDisposer;
@@ -179,7 +183,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
                 },
                 icon: "expand-arrows-alt"
             });
-            ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems });
+            ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems, icon: "video" });
         }
     }
 
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 5c2ced2eb..562594210 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -1,6 +1,6 @@
 import React = require("react");
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote, faFingerprint } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
@@ -38,7 +38,7 @@ library.add(faFilm);
 library.add(faMusic);
 library.add(faLink);
 library.add(faChartBar);
-library.add(faGlobeAsia);
+library.add(faGlobeAsia, faFingerprint);
 
 @observer
 export class SelectorContextMenu extends React.Component<SearchItemProps> {
@@ -223,7 +223,8 @@ export class SearchItem extends React.Component<SearchItemProps> {
         ContextMenu.Instance.addItem({
             description: "Copy ID", event: () => {
                 Utils.CopyText(this.props.doc[Id]);
-            }
+            },
+            icon: "fingerprint"
         });
         ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
     }
-- 
cgit v1.2.3-70-g09d2


From cc806ebbe8d48d1c5a4c3c49231a5d38d6f39943 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 27 Jul 2019 04:12:07 -0400
Subject: fixed a bunch of template and stacking view issues among others.

---
 src/client/views/DocumentDecorations.tsx           |  4 +-
 src/client/views/GlobalKeyHandler.ts               |  1 +
 src/client/views/MainView.tsx                      |  2 +-
 .../views/collections/CollectionDockingView.tsx    | 39 +++++--------
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../views/collections/CollectionStackingView.tsx   | 68 +++++++++-------------
 src/client/views/collections/CollectionView.tsx    |  2 -
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 22 +++----
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 16 +----
 src/client/views/nodes/DocumentView.tsx            | 14 +++--
 src/new_fields/Doc.ts                              | 13 ++++-
 11 files changed, 75 insertions(+), 108 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 255855b45..c08a84742 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -533,7 +533,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     proto.nativeHeight = nheight = doc.height || 0;
                     proto.ignoreAspect = true;
                 }
-                if (nwidth > 0 && nheight > 0) {
+                if (nwidth > 0 && nheight > 0 && !BoolCast(proto.ignoreAspect)) {
                     if (Math.abs(dW) > Math.abs(dH)) {
                         if (!fixedAspect) {
                             Doc.SetInPlace(element.props.Document, "nativeWidth", actualdW / (doc.width || 1) * (doc.nativeWidth || 0), true);
@@ -553,7 +553,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 } else {
                     dW && (doc.width = actualdW);
                     dH && (doc.height = actualdH);
-                    Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true);
+                    dH && Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true);
                 }
             }
         });
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 7477c5b4f..5050f34ab 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -67,6 +67,7 @@ export default class KeyManager {
                     }
                 }
                 MainView.Instance.toggleColorPicker(true);
+                SelectionManager.DeselectAll();
                 break;
             case "delete":
             case "backspace":
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 61a013963..bfb50bc75 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -407,7 +407,7 @@ export class MainView extends React.Component {
                             </button>
                         </div></li>)}
                     <li key="undoTest"><button className="add-button round-button" title="Click if undo isn't working" onClick={() => UndoManager.TraceOpenBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
-                    <li key="color"><button className="add-button round-button" title="Select Color" onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
+                    <li key="color"><button className="add-button round-button" title="Select Color" style={{ zIndex: 1000 }} onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
                         <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
                             <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
                         </div>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index ba7903419..0865058be 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -539,17 +539,17 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         }
     }
 
+    panelWidth = () => Math.min(this._panelWidth, Math.max(NumCast(this._document!.width), this.nativeWidth()));
+    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 = () => NumCast(this._document!.nativeWidth, this._panelWidth);
-    nativeHeight = () => {
-        let nh = NumCast(this._document!.nativeHeight, this._panelHeight);
-        let res = BoolCast(this._document!.ignoreAspect) ? this._panelHeight : nh;
-        return res;
-    }
     contentScaling = () => {
         const nativeH = this.nativeHeight();
         const nativeW = this.nativeWidth();
-        let wscale = this._panelWidth / nativeW;
+        if (!nativeW || !nativeH) return 1;
+        let wscale = this.panelWidth() / nativeW;
         return wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale;
     }
 
@@ -561,18 +561,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         }
         return Transform.Identity();
     }
-    get scaleToFitMultiplier() {
-        let docWidth = NumCast(this._document!.width);
-        let docHeight = NumCast(this._document!.height);
-        if (NumCast(this._document!.nativeWidth) || !docWidth || !this._panelWidth || !this._panelHeight) return 1;
-        if (StrCast(this._document!.layout).indexOf("Collection") === -1 ||
-            !BoolCast(this._document!.fitToContents, false) ||
-            NumCast(this._document!.viewType) !== CollectionViewType.Freeform) return 1;
-        let scaling = Math.max(1, this._panelWidth / docWidth * docHeight > this._panelHeight ?
-            this._panelHeight / docHeight : this._panelWidth / docWidth);
-        return scaling;
-    }
-    get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; }
+    get previewPanelCenteringOffset() { return this.nativeWidth && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
 
     addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => {
         if (doc.dockingConfig) {
@@ -588,6 +577,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
             return (null);
         }
         let resolvedDataDoc = this._document.layout instanceof Doc ? this._document : this._dataDoc;
+        console.log("pw = " + this.panelWidth() + "," + this.panelHeight() + " " + this.contentScaling());
         return <DocumentView key={this._document[Id]}
             Document={this._document}
             DataDoc={resolvedDataDoc}
@@ -595,8 +585,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
             addDocument={undefined}
             removeDocument={undefined}
             ContentScaling={this.contentScaling}
-            PanelWidth={this.nativeWidth}
-            PanelHeight={this.nativeHeight}
+            PanelWidth={this.panelWidth}
+            PanelHeight={this.panelHeight}
             ScreenToLocalTransform={this.ScreenToLocalTransform}
             renderDepth={0}
             selectOnLoad={false}
@@ -610,18 +600,15 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     }
 
     @computed get content() {
-        if (!this._document) {
-            return (null);
-        }
         return (
             <div className="collectionDockingView-content" ref={this._mainCont}
-                style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px) scale(${this.scaleToFitMultiplier})` }}>
+                style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
                 {this.docView}
             </div >);
     }
 
     render() {
-        if (!this._isActive) return null;
+        if (!this._isActive || !this._document) return null;
         let theContent = this.content;
         return !this._document ? (null) :
             <Measure offset onResize={action((r: any) => { this._panelWidth = r.offset.width; this._panelHeight = r.offset.height; })}>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 119aa7c19..8ce3b40e5 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -563,7 +563,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         height: "100%"
                     }}>
                     <DocumentView
-                        DataDoc={this.props.Document.layout instanceof Doc ? this.props.Document : this.props.DataDocument}
+                        DataDoc={this.props.DataDocument}
                         Document={this.props.Document}
                         fitToBox={this.props.fitToBox}
                         renderDepth={this.props.renderDepth + 1}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 5a123bf65..3da13bff5 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -46,14 +46,14 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return fields;
     }
     componentDidMount() {
-        this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])],
+        this._heightDisposer = reaction(() => [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) {
+                if (this.singleColumn && BoolCast(this.props.Document.autoHeight)) {
                     let hgt = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => {
                         let xhgt = height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap);
                         return xhgt;
                     }, this.yMargin);
-                    this.layoutDoc.height = hgt;
+                    this.layoutDoc.height = hgt * (this.props as any).ContentScaling();
                 }
             }, { fireImmediately: true });
     }
@@ -74,14 +74,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return doc.type === DocumentType.IMG || doc.type === DocumentType.VID ? { title: "title", caption: "caption" } : {};
     }
 
-    getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) {
-        let resolvedDataDoc = !this.layoutDoc.isTemplate && this.props.DataDoc !== this.layoutDoc ? this.props.DataDoc : undefined;
-        let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth;
+    getDisplayDoc(layoutDoc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) {
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
         return <CollectionSchemaPreview
             Document={layoutDoc}
-            DataDocument={resolvedDataDoc}
+            DataDocument={dataDoc}
             showOverlays={this.overlays}
             renderDepth={this.props.renderDepth}
             fitToBox={true}
@@ -102,51 +100,37 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     getDocHeight(d: Doc) {
         let nw = NumCast(d.nativeWidth);
         let nh = NumCast(d.nativeHeight);
-        let aspect = nw && nh ? nh / nw : 1;
-        let wid = Math.min(d[WidthSym](), this.columnWidth);
-        return (nw && nh) ? wid * aspect : d[HeightSym]();
+        if (!BoolCast(d.ignoreAspect) && nw && nh) {
+            let aspect = nw && nh ? nh / nw : 1;
+            let wid = Math.min(d[WidthSym](), this.columnWidth);
+            return wid * aspect;
+        }
+        return d[HeightSym]();
     }
 
-    offsetTransform(doc: Doc, translateX: number, translateY: number) {
+    getDocTransform(doc: Doc, dref: HTMLDivElement) {
+        let { scale, translateX, translateY } = Utils.GetScreenTransform(dref);
         let outerXf = Utils.GetScreenTransform(this._masonryGridRef!);
         let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
         return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.columnWidth);
     }
-    getDocTransform(doc: Doc, dref: HTMLDivElement) {
-        let { scale, translateX, translateY } = Utils.GetScreenTransform(dref);
-        return this.offsetTransform(doc, translateX, translateY);
-    }
-
-    getSingleDocTransform(doc: Doc, ind: number, width: number) {
-        let localY = this.filteredChildren.reduce((height, d, i) =>
-            height + (i < ind ? this.getDocHeight(Doc.expandTemplateLayout(d, this.props.DataDoc)) + this.gridGap : 0), this.yMargin);
-        let translate = this.props.ScreenToLocalTransform().inverse().transformPoint((this.props.PanelWidth() - width) / 2, localY);
-        return this.offsetTransform(doc, translate[0], translate[1]);
-    }
 
     children(docs: Doc[]) {
         this._docXfs.length = 0;
         return docs.map((d, i) => {
-            let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc);
-            let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth;
-            let height = () => this.getDocHeight(layoutDoc);
-            if (this.singleColumn) {
-                //have to add the height of all previous single column sections or the doc decorations will be in the wrong place.
-                let dxf = () => this.getSingleDocTransform(layoutDoc, i, width());
-                let rowHgtPcnt = height();
-                this._docXfs.push({ dxf: dxf, width: width, height: height });
-                return <div className="collectionStackingView-columnDoc" key={d[Id]} style={{ width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: `${rowHgtPcnt}` }} >
-                    {this.getDisplayDoc(layoutDoc, d, dxf)}
-                </div>;
-            } else {
-                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 });
-                return <div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} style={{ gridRowEnd: `span ${rowSpan}` }} >
-                    {this.getDisplayDoc(layoutDoc, d, dxf)}
-                </div>;
-            }
+            let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d)
+            let width = () => d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), this.columnWidth) : this.columnWidth;
+            let height = () => this.getDocHeight(pair.layout);
+            let dref = React.createRef<HTMLDivElement>();
+            let dxf = () => this.getDocTransform(pair.layout, dref.current!);
+            this._docXfs.push({ dxf: dxf, width: width, height: height });
+            let rowHgtPcnt = height();
+            let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
+            let style = this.singleColumn ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: `${rowHgtPcnt}` } : { gridRowEnd: `span ${rowSpan}` };
+
+            return <div className={`collectionStackingView-${this.singleColumn ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} >
+                {this.getDisplayDoc(pair.layout, pair.data, dxf, width)}
+            </div>;
         });
     }
 
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 7781b26d9..cd137cd60 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -15,8 +15,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionSchemaView } from "./CollectionSchemaView";
 import { CollectionStackingView } from './CollectionStackingView';
 import { CollectionTreeView } from "./CollectionTreeView";
-import { StrCast, PromiseValue } from '../../../new_fields/Types';
-import { DocumentType } from '../../documents/Documents';
 export const COLLECTION_BORDER_WIDTH = 2;
 
 library.add(faTh);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 5d61aefc7..f83d02271 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -61,11 +61,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private inkKey = "ink";
 
     get parentScaling() {
-        return (this.props as any).ContentScaling && this.Document.nativeWidth && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1;
+        return (this.props as any).ContentScaling && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1;
     }
 
     @computed get contentBounds() {
-        let bounds = this.fitToBox && !this.nativeWidth && !this.isAnnotationOverlay ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined;
+        let bounds = this.fitToBox && !this.isAnnotationOverlay ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined;
         return {
             panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0,
             panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0,
@@ -370,24 +370,18 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     getChildDocumentViewProps(childDocLayout: Doc): DocumentViewProps {
         let self = this;
-        let resolvedDataDoc = !this.props.Document.isTemplate && this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined;
-        let layoutDoc = childDocLayout;
-        if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) {
-            Doc.UpdateDocumentExtensionForField(resolvedDataDoc, this.props.fieldKey);
-            let fieldExtensionDoc = Doc.resolvedFieldDataDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title)), "dummy");
-            layoutDoc = Doc.expandTemplateLayout(childDocLayout, fieldExtensionDoc !== resolvedDataDoc ? fieldExtensionDoc : undefined);
-        } else layoutDoc = Doc.expandTemplateLayout(childDocLayout, resolvedDataDoc);
+        let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, childDocLayout);
         return {
-            DataDoc: resolvedDataDoc !== layoutDoc && resolvedDataDoc ? resolvedDataDoc : undefined,
-            Document: layoutDoc,
+            DataDoc: pair.data,
+            Document: pair.layout,
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
             moveDocument: this.props.moveDocument,
             ScreenToLocalTransform: this.getTransform,
             renderDepth: this.props.renderDepth + 1,
-            selectOnLoad: layoutDoc[Id] === this._selectOnLoaded,
-            PanelWidth: layoutDoc[WidthSym],
-            PanelHeight: layoutDoc[HeightSym],
+            selectOnLoad: pair.layout[Id] === this._selectOnLoaded,
+            PanelWidth: pair.layout[WidthSym],
+            PanelHeight: pair.layout[HeightSym],
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
             focus: this.focusDocument,
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 389b9f68b..7ffd760e0 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -35,21 +35,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     @computed get zoom(): number { return 1 / FieldValue(this.Document.zoomBasis, 1); }
     @computed get nativeWidth(): number { return FieldValue(this.Document.nativeWidth, 0); }
     @computed get nativeHeight(): number { return FieldValue(this.Document.nativeHeight, 0); }
-
-    set width(w: number) {
-        this.Document.width = w;
-        if (this.nativeWidth && this.nativeHeight) {
-            this.Document.height = this.nativeHeight / this.nativeWidth * w;
-        }
-    }
-    set height(h: number) {
-        this.Document.height = h;
-        if (this.nativeWidth && this.nativeHeight) {
-            this.Document.width = this.nativeWidth / this.nativeHeight * h;
-        }
-    }
     @computed get scaleToOverridingWidth() { return this.width / NumCast(this.props.Document.width, this.width); }
-    contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
+
+    contentScaling = () => this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? this.width / this.nativeWidth : 1;
     panelWidth = () => this.props.PanelWidth();
     panelHeight = () => this.props.PanelHeight();
     getTransform = (): Transform => this.props.ScreenToLocalTransform()
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bae0b5b96..3152d6a2a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -507,12 +507,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @action
     freezeNativeDimensions = (): void => {
         let proto = this.props.Document.isTemplate ? this.props.Document : Doc.GetProto(this.props.Document);
-        if (proto.ignoreAspect === undefined && !proto.nativeWidth) {
+        this.props.Document.autoHeight = proto.autoHeight = false;
+        proto.ignoreAspect = !BoolCast(proto.ignoreAspect);
+        if (!BoolCast(proto.ignoreAspect) && !proto.nativeWidth) {
             proto.nativeWidth = this.props.PanelWidth();
             proto.nativeHeight = this.props.PanelHeight();
-            proto.ignoreAspect = true;
         }
-        proto.ignoreAspect = !BoolCast(proto.ignoreAspect, false);
     }
     @undoBatch
     @action
@@ -546,7 +546,7 @@ 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: "edit" });
+        cm.addItem({ description: !BoolCast(this.props.Document.ignoreAspect) && this.props.Document.nativeWidth && this.props.Document.nativeHeight ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" });
         cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
         cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Pos" : "Lock Pos", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
         cm.addItem({ description: "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
@@ -642,7 +642,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         let self = this;
         let backgroundColor = StrCast(this.layoutDoc.backgroundColor);
         let foregroundColor = StrCast(this.layoutDoc.color);
-        var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%";
+        var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%";
         var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
         let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined;
         let showTitle = showOverlays && showOverlays.title !== "undefined" ? showOverlays.title : StrCast(this.layoutDoc.showTitle);
@@ -665,6 +665,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     outlineStyle: "dashed",
                     outlineWidth: BoolCast(this.layoutDoc.libraryBrush) && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
                         `${this.props.ScreenToLocalTransform().Scale}px` : "0px",
+                    marginLeft: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
+                        `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined,
+                    marginTop: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
+                        `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined,
                     border: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
                         `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined,
                     borderRadius: "inherit",
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 1a00db1c1..dbb0dc505 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -389,11 +389,22 @@ export namespace Doc {
         }
         if (expandedTemplateLayout === undefined) {
             setTimeout(() =>
-                dataDoc[expandedLayoutFieldKey] = Doc.MakeDelegate(templateLayoutDoc, undefined, "["+templateLayoutDoc.title + "]"), 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.
     }
 
+    export function GetLayoutDataDocPair(doc: Doc, dataDoc: Doc | undefined, fieldKey: string, childDocLayout: Doc) {
+        let layoutDoc = childDocLayout;
+        let resolvedDataDoc = !doc.isTemplate && dataDoc !== doc ? dataDoc : undefined;
+        if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) {
+            Doc.UpdateDocumentExtensionForField(resolvedDataDoc, fieldKey);
+            let fieldExtensionDoc = Doc.resolvedFieldDataDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title)), "dummy");
+            layoutDoc = Doc.expandTemplateLayout(childDocLayout, fieldExtensionDoc !== resolvedDataDoc ? fieldExtensionDoc : undefined);
+        } else layoutDoc = Doc.expandTemplateLayout(childDocLayout, resolvedDataDoc);
+        return { layout: layoutDoc, data: resolvedDataDoc };
+    }
+
     export function MakeCopy(doc: Doc, copyProto: boolean = false): Doc {
         const copy = new Doc;
         Object.keys(doc).forEach(key => {
-- 
cgit v1.2.3-70-g09d2


From c360dc0adb468ae3aaa1c2d943606993d01a5a52 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 27 Jul 2019 11:08:44 -0400
Subject: fixed handling of keyboard events to avoid triggering global key
 events. made BoolCast default to false. fixed templating to deal with
 conflict between field fields and template fields

---
 src/client/util/DocumentManager.ts                 | 16 +++++++--------
 src/client/views/EditableView.tsx                  |  3 +++
 src/client/views/MainView.tsx                      |  1 -
 src/client/views/MetadataEntryMenu.tsx             |  1 +
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../views/collections/CollectionStackingView.tsx   |  3 ++-
 .../CollectionFreeFormLinkView.tsx                 |  8 ++++----
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  8 ++++----
 src/client/views/nodes/FormattedTextBox.tsx        |  4 ++--
 src/client/views/nodes/IconBox.tsx                 |  2 +-
 src/client/views/nodes/KeyValueBox.tsx             |  3 ++-
 src/client/views/nodes/LinkMenuItem.tsx            |  2 +-
 src/client/views/pdf/Page.tsx                      | 22 ++++++++------------
 .../views/presentationview/PresentationElement.tsx | 24 ++++++++++------------
 .../views/presentationview/PresentationView.tsx    |  2 +-
 src/new_fields/Doc.ts                              | 19 +++++++++--------
 src/new_fields/Types.ts                            |  2 +-
 18 files changed, 62 insertions(+), 62 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 262194a40..32f728c71 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,16 +1,14 @@
-import { computed, observable, action } from 'mobx';
-import { DocumentView } from '../views/nodes/DocumentView';
-import { Doc, DocListCast, Opt } from '../../new_fields/Doc';
-import { FieldValue, Cast, NumCast, BoolCast, StrCast } from '../../new_fields/Types';
-import { listSpec } from '../../new_fields/Schema';
-import { undoBatch, UndoManager } from './UndoManager';
+import { action, computed, observable } from 'mobx';
+import { Doc } from '../../new_fields/Doc';
+import { Id } from '../../new_fields/FieldSymbols';
+import { BoolCast, Cast, NumCast } from '../../new_fields/Types';
 import { CollectionDockingView } from '../views/collections/CollectionDockingView';
-import { CollectionView } from '../views/collections/CollectionView';
 import { CollectionPDFView } from '../views/collections/CollectionPDFView';
 import { CollectionVideoView } from '../views/collections/CollectionVideoView';
-import { Id } from '../../new_fields/FieldSymbols';
+import { CollectionView } from '../views/collections/CollectionView';
+import { DocumentView } from '../views/nodes/DocumentView';
 import { LinkManager } from './LinkManager';
-import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
+import { undoBatch, UndoManager } from './UndoManager';
 
 
 export class DocumentManager {
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index c66a92f48..7cabebddd 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -50,8 +50,10 @@ export class EditableView extends React.Component<EditableProps> {
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
         if (e.key === "Tab") {
+            e.stopPropagation();
             this.props.OnTab && this.props.OnTab();
         } else if (e.key === "Enter") {
+            e.stopPropagation();
             if (!e.ctrlKey) {
                 if (this.props.SetValue(e.currentTarget.value, e.shiftKey)) {
                     this._editing = false;
@@ -61,6 +63,7 @@ export class EditableView extends React.Component<EditableProps> {
                 this._editing = false;
             }
         } else if (e.key === "Escape") {
+            e.stopPropagation();
             this._editing = false;
         }
     }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index bfb50bc75..8b7eb8856 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -7,7 +7,6 @@ import "normalize.css";
 import * as React from 'react';
 import { SketchPicker } from 'react-color';
 import Measure from 'react-measure';
-import * as request from 'request';
 import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc';
 import { Id } from '../../new_fields/FieldSymbols';
 import { InkTool } from '../../new_fields/InkField';
diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx
index bd5a307b3..c50e02f0d 100644
--- a/src/client/views/MetadataEntryMenu.tsx
+++ b/src/client/views/MetadataEntryMenu.tsx
@@ -76,6 +76,7 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
 
     onValueKeyDown = async (e: React.KeyboardEvent) => {
         if (e.key === "Enter") {
+            e.stopPropagation();
             const script = KeyValueBox.CompileKVPScript(this._currentValue);
             if (!script) return;
             let doc = this.props.docs;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 8ce3b40e5..0f67c47aa 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -11,7 +11,7 @@ import { Doc, DocListCast, DocListCastAsync, Field } from "../../../new_fields/D
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
-import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
+import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { Docs } from "../../documents/Documents";
 import { Gateway } from "../../northstar/manager/Gateway";
 import { SetupDrag, DragManager } from "../../util/DragManager";
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 3da13bff5..d5a7b90da 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -53,7 +53,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                         let xhgt = height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap);
                         return xhgt;
                     }, this.yMargin);
-                    this.layoutDoc.height = hgt * (this.props as any).ContentScaling();
+                    (this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc)
+                        .height = hgt * (this.props as any).ContentScaling();
                 }
             }, { fireImmediately: true });
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index b546d1b78..6af87b138 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -21,10 +21,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
         if (e.button === 0 && !InkingControl.Instance.selectedTool) {
             let a = this.props.A;
             let b = this.props.B;
-            let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2);
-            let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2);
-            let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2);
-            let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2);
+            let x1 = NumCast(a.x) + (BoolCast(a.isMinimized) ? 5 : a[WidthSym]() / 2);
+            let y1 = NumCast(a.y) + (BoolCast(a.isMinimized) ? 5 : a[HeightSym]() / 2);
+            let x2 = NumCast(b.x) + (BoolCast(b.isMinimized) ? 5 : b[WidthSym]() / 2);
+            let y2 = NumCast(b.y) + (BoolCast(b.isMinimized) ? 5 : b[HeightSym]() / 2);
             // this.props.LinkDocs.map(l => {
             //     let width = l[WidthSym]();
             //     l.x = (x1 + x2) / 2 - width / 2;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f83d02271..eaad43c10 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -471,7 +471,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             if (!(doc instanceof Doc)) return prev;
             var page = NumCast(doc.page, -1);
             if ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1) {
-                let minim = BoolCast(doc.isMinimized, false);
+                let minim = BoolCast(doc.isMinimized);
                 if (minim === undefined || !minim) {
                     const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) : {};
                     state = pos.state === undefined ? state : pos.state;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3152d6a2a..bc2af2ae8 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -275,7 +275,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 let iconAnimating = Cast(maximizedDoc.isIconAnimating, List);
                 if (!iconAnimating || (Date.now() - iconAnimating[2] > 1000)) {
                     if (isMinimized === undefined) {
-                        isMinimized = BoolCast(maximizedDoc.isMinimized, false);
+                        isMinimized = BoolCast(maximizedDoc.isMinimized);
                     }
                     maximizedDoc.willMaximize = isMinimized;
                     maximizedDoc.isMinimized = false;
@@ -308,7 +308,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
             SelectionManager.SelectDoc(this, e.ctrlKey);
             let isExpander = (e.target as any).id === "isExpander";
-            if (BoolCast(this.props.Document.isButton, false) || isExpander) {
+            if (BoolCast(this.props.Document.isButton) || isExpander) {
                 SelectionManager.DeselectAll();
                 let subBulletDocs = await DocListCastAsync(this.props.Document.subBulletDocs);
                 let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs);
@@ -326,7 +326,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                         maxLocation = this.props.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace"));
                         if (!maxLocation || maxLocation === "inPlace") {
                             let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
-                            let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized, false), false);
+                            let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized), false);
                             expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false);
                             let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
                             if (!hasView) {
@@ -409,7 +409,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @undoBatch
     makeBtnClicked = (): void => {
         let doc = Doc.GetProto(this.props.Document);
-        doc.isButton = !BoolCast(doc.isButton, false);
+        doc.isButton = !BoolCast(doc.isButton);
         if (doc.isButton) {
             if (!doc.nativeWidth) {
                 doc.nativeWidth = this.props.Document[WidthSym]();
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 0a79677e2..bd0fd8301 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -459,8 +459,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     specificContextMenu = (e: React.MouseEvent): void => {
         let subitems: ContextMenuProps[] = [];
         subitems.push({
-            description: BoolCast(this.props.Document.autoHeight, false) ? "Manual Height" : "Auto Height",
-            event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight, false)), icon: "expand-arrows-alt"
+            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 });
     }
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
index d6ab2a34a..6f50033a4 100644
--- a/src/client/views/nodes/IconBox.tsx
+++ b/src/client/views/nodes/IconBox.tsx
@@ -64,7 +64,7 @@ export class IconBox extends React.Component<FieldViewProps> {
         let hideLabel = BoolCast(this.props.Document.hideLabel);
         let maxDocs = DocListCast(this.props.Document.maximizedDocs);
         let firstDoc = maxDocs.length ? maxDocs[0] : undefined;
-        let label = hideLabel ? "" : (firstDoc && labelField && !BoolCast(this.props.Document.useOwnTitle, false) ? firstDoc[labelField] : this.props.Document.title);
+        let label = hideLabel ? "" : (firstDoc && labelField && !BoolCast(this.props.Document.useOwnTitle) ? firstDoc[labelField] : this.props.Document.title);
         return (
             <div className="iconBox-container" onContextMenu={this.specificContextMenu}>
                 {this.minimizedIcon}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 9fc0f2080..77824b4ff 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -46,6 +46,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     @action
     onEnterKey = (e: React.KeyboardEvent): void => {
         if (e.key === 'Enter') {
+            e.stopPropagation();
             if (this._keyInput && this._valueInput && this.fieldDocToLayout) {
                 if (KeyValueBox.SetField(this.fieldDocToLayout, this._keyInput, this._valueInput)) {
                     this._keyInput = "";
@@ -153,7 +154,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
                     <input style={{ width: "100%" }} type="text" value={this._keyInput} placeholder="Key" onChange={this.keyChanged} />
                 </td>
                 <td className="keyValueBox-td-value" style={{ width: `${this.splitPercentage}%` }}>
-                    <input style={{ width: "100%" }} type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyPress={this.onEnterKey} />
+                    <input style={{ width: "100%" }} type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyDown={this.onEnterKey} />
                 </td>
             </tr>
         )
diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx
index a0c37a719..d4c92c9f2 100644
--- a/src/client/views/nodes/LinkMenuItem.tsx
+++ b/src/client/views/nodes/LinkMenuItem.tsx
@@ -7,7 +7,7 @@ import { undoBatch } from "../../util/UndoManager";
 import './LinkMenu.scss';
 import React = require("react");
 import { Doc } from '../../../new_fields/Doc';
-import { StrCast, Cast, BoolCast, FieldValue, NumCast } from '../../../new_fields/Types';
+import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types';
 import { observable, action } from 'mobx';
 import { LinkManager } from '../../util/LinkManager';
 import { DragLinkAsDocument } from '../../util/DragManager';
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index c9d442fe5..a6864e0f3 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -1,22 +1,18 @@
+import { action, IReactionDisposer, observable } from "mobx";
 import { observer } from "mobx-react";
-import React = require("react");
-import { observable, action, runInAction, IReactionDisposer, reaction } from "mobx";
 import * as Pdfjs from "pdfjs-dist";
-import { Opt, Doc, FieldResult, Field, DocListCast, WidthSym, HeightSym, DocListCastAsync } from "../../../new_fields/Doc";
-import "./PDFViewer.scss";
 import "pdfjs-dist/web/pdf_viewer.css";
-import { PDFBox } from "../nodes/PDFBox";
-import { DragManager } from "../../util/DragManager";
-import { Docs, DocUtils } from "../../documents/Documents";
+import { Doc, DocListCastAsync, Opt, WidthSym } from "../../../new_fields/Doc";
 import { List } from "../../../new_fields/List";
-import { emptyFunction } from "../../../Utils";
-import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { listSpec } from "../../../new_fields/Schema";
-import { menuBar } from "prosemirror-menu";
-import { AnnotationTypes, PDFViewer, scale } from "./PDFViewer";
+import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { Docs, DocUtils } from "../../documents/Documents";
+import { DragManager } from "../../util/DragManager";
+import { PDFBox } from "../nodes/PDFBox";
 import PDFMenu from "./PDFMenu";
-import { UndoManager } from "../../util/UndoManager";
-import { copy } from "typescript-collections/dist/lib/arrays";
+import { scale } from "./PDFViewer";
+import "./PDFViewer.scss";
+import React = require("react");
 
 
 interface IPageProps {
diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx
index 329630875..36f1178f1 100644
--- a/src/client/views/presentationview/PresentationElement.tsx
+++ b/src/client/views/presentationview/PresentationElement.tsx
@@ -1,21 +1,19 @@
-import { observer } from "mobx-react";
-import React = require("react");
-import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
-import { NumCast, BoolCast, StrCast, Cast } from "../../../new_fields/Types";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { observable, action, computed, runInAction } from "mobx";
-import "./PresentationView.scss";
-import { Utils } from "../../../Utils";
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faFile as fileSolid, faFileDownload, faLocationArrow, faArrowUp, faSearch } from '@fortawesome/free-solid-svg-icons';
 import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons';
+import { faArrowUp, faFile as fileSolid, faFileDownload, faLocationArrow, faSearch } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, computed, observable, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import { Doc } from "../../../new_fields/Doc";
+import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
-import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager";
+import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { Utils } from "../../../Utils";
+import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
-import { indexOf } from "typescript-collections/dist/lib/arrays";
-import { map } from "bluebird";
+import "./PresentationView.scss";
+import React = require("react");
 
 library.add(faArrowUp);
 library.add(fileSolid);
diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx
index f2fef7f16..e25725275 100644
--- a/src/client/views/presentationview/PresentationView.tsx
+++ b/src/client/views/presentationview/PresentationView.tsx
@@ -171,7 +171,7 @@ export class PresentationView extends React.Component<PresViewProps>  {
 
 
         //storing the presentation status,ie. whether it was stopped or playing
-        let presStatusBackUp = BoolCast(this.curPresentation.presStatus, null);
+        let presStatusBackUp = BoolCast(this.curPresentation.presStatus);
         runInAction(() => this.presStatus = presStatusBackUp);
     }
 
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index dbb0dc505..b5708e97b 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -455,7 +455,7 @@ export namespace Doc {
         return otherdoc;
     }
 
-    export function MakeTemplate(fieldTemplate: Doc, metaKey: string, proto: Doc) {
+    export function MakeTemplate(fieldTemplate: Doc, metaKey: string, templateDataDoc: Doc) {
         // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??)
         let backgroundLayout = StrCast(fieldTemplate.backgroundLayout);
         let fieldLayoutDoc = fieldTemplate;
@@ -466,21 +466,24 @@ export namespace Doc {
         if (backgroundLayout) {
             backgroundLayout = backgroundLayout.replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`);
         }
-        let nw = Cast(fieldTemplate.nativeWidth, "number");
-        let nh = Cast(fieldTemplate.nativeHeight, "number");
 
         let layoutDelegate = fieldTemplate.layout instanceof Doc ? fieldLayoutDoc : fieldTemplate;
         layoutDelegate.layout = layout;
 
-        fieldTemplate.title = metaKey;
         fieldTemplate.templateField = metaKey;
+        fieldTemplate.title = metaKey;
+        fieldTemplate.isTemplate = true;
         fieldTemplate.layout = layoutDelegate !== fieldTemplate ? layoutDelegate : layout;
         fieldTemplate.backgroundLayout = backgroundLayout;
-        fieldTemplate.nativeWidth = nw;
-        fieldTemplate.nativeHeight = nh;
-        fieldTemplate.isTemplate = true;
+        /* move certain layout properties from the original data doc to the template layout to avoid
+           inheriting them from the template's data doc which may also define these fields for its own use.
+        */
+        fieldTemplate.ignoreAspect = BoolCast(fieldTemplate.ignoreAspect);
+        fieldTemplate.singleColumn = BoolCast(fieldTemplate.singleColumn);
+        fieldTemplate.nativeWidth = Cast(fieldTemplate.nativeWidth, "number");
+        fieldTemplate.nativeHeight = Cast(fieldTemplate.nativeHeight, "number");
         fieldTemplate.showTitle = "title";
-        setTimeout(() => fieldTemplate.proto = proto);
+        setTimeout(() => fieldTemplate.proto = templateDataDoc);
     }
 
     export async function ToggleDetailLayout(d: Doc) {
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index f8a4a30b4..565ae2ee3 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -78,7 +78,7 @@ export function StrCast(field: FieldResult, defaultVal: string | null = "") {
     return Cast(field, "string", defaultVal);
 }
 
-export function BoolCast(field: FieldResult, defaultVal: boolean | null = null) {
+export function BoolCast(field: FieldResult, defaultVal: boolean | null = false) {
     return Cast(field, "boolean", defaultVal);
 }
 export function DateCast(field: FieldResult) {
-- 
cgit v1.2.3-70-g09d2


From 905d77804bf9a810822e5e43f0cd06019aef7620 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Sat, 27 Jul 2019 17:03:20 -0400
Subject: schema headers changed to schemaheaderfields, a bug with udpating the
 headers (in CollectionSchemaView>ChangeColumn)

---
 src/client/documents/Documents.ts                  |  13 +--
 src/client/util/DragManager.ts                     |   5 +-
 src/client/views/MainView.tsx                      |   3 +-
 .../views/collections/CollectionSchemaCells.tsx    |  30 +++++-
 .../views/collections/CollectionSchemaHeaders.tsx  |   9 +-
 .../CollectionSchemaMovableTableHOC.tsx            |   7 +-
 .../views/collections/CollectionSchemaView.scss    |  15 +++
 .../views/collections/CollectionSchemaView.tsx     | 103 +++++++++++++--------
 .../views/collections/CollectionStackingView.tsx   |   2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |   3 +-
 src/client/views/nodes/LinkEditor.tsx              |   3 +-
 src/client/views/nodes/LinkMenuGroup.tsx           |   3 +-
 src/new_fields/SchemaHeaderField.ts                |  55 +++++++++--
 13 files changed, 186 insertions(+), 65 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 76ac34d85..e6fe1b8b3 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -39,6 +39,7 @@ import { DocumentManager } from "../util/DocumentManager";
 import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox";
 import { Scripting } from "../util/Scripting";
 import { ButtonBox } from "../views/nodes/ButtonBox";
+import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField";
 var requestImageSize = require('../util/request-image-size');
 var path = require('path');
 
@@ -84,7 +85,7 @@ export interface DocumentOptions {
     curPage?: number;
     documentText?: string;
     borderRounding?: string;
-    schemaColumns?: List<string>;
+    schemaColumns?: List<SchemaHeaderField>;
     dockingConfig?: string;
     dbDoc?: Doc;
     // [key: string]: Opt<Field>;
@@ -403,23 +404,23 @@ export namespace Docs {
         }
 
         export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform });
         }
 
-        export function SchemaDocument(schemaColumns: string[], documents: Array<Doc>, options: DocumentOptions) {
+        export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema });
         }
 
         export function TreeDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree });
         }
 
         export function StackingDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking });
         }
 
         export function MasonryDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Masonry });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry });
         }
 
         export function ButtonDocument(options?: DocumentOptions) {
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 0299b1d90..47d3c313d 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -8,6 +8,7 @@ import * as globalCssVariables from "../views/globalCssVariables.scss";
 import { DocumentManager } from "./DocumentManager";
 import { LinkManager } from "./LinkManager";
 import { SelectionManager } from "./SelectionManager";
+import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField";
 
 export type dropActionType = "alias" | "copy" | undefined;
 export function SetupDrag(
@@ -290,10 +291,10 @@ export namespace DragManager {
 
     // for column dragging in schema view
     export class ColumnDragData {
-        constructor(colKey: string) {
+        constructor(colKey: SchemaHeaderField) {
             this.colKey = colKey;
         }
-        colKey: string;
+        colKey: SchemaHeaderField;
         [id: string]: any;
     }
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 0e04b5e7e..282db244e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -39,6 +39,7 @@ import { PreviewCursor } from './PreviewCursor';
 import { FilterBox } from './search/FilterBox';
 import { CollectionTreeView } from './collections/CollectionTreeView';
 import { ClientUtils } from '../util/ClientUtils';
+import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField';
 
 @observer
 export class MainView extends React.Component {
@@ -375,7 +376,7 @@ export class MainView extends React.Component {
         let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
 
         // let addDockingNode = action(() => Docs.Create.StandardCollectionDockingDocument([{ doc: addColNode(), initialWidth: 200 }], { width: 200, height: 200, title: "a nested docking freeform collection" }));
-        let addSchemaNode = action(() => Docs.Create.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" }));
+        let addSchemaNode = action(() => Docs.Create.SchemaDocument([new SchemaHeaderField("title")], [], { width: 200, height: 200, title: "a schema collection" }));
         //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
         // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy"  }));
         let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 4a618a436..c91f1017b 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -21,7 +21,12 @@ import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_field
 import { Docs } from "../../documents/Documents";
 import { DocumentContentsView } from "../nodes/DocumentContentsView";
 import { SelectionManager } from "../../util/SelectionManager";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { faExpand } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
 
+library.add(faExpand);
 
 export interface CellProps {
     row: number;
@@ -38,6 +43,7 @@ export interface CellProps {
     changeFocusedCellByIndex: (row: number, col: number) => void;
     setIsEditing: (isEditing: boolean) => void;
     isEditable: boolean;
+    setPreviewDoc: (doc: Doc) => void;
 }
 
 @observer
@@ -92,7 +98,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                 this._document[fieldKey] = de.data.draggedDocuments[0];
             }
             else {
-                let coll = Docs.Create.SchemaDocument(["title"], de.data.draggedDocuments, {});
+                let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title")], de.data.draggedDocuments, {});
                 this._document[fieldKey] = coll;
             }
             e.stopPropagation();
@@ -106,6 +112,18 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         }
     }
 
+    expandDoc = (e: React.PointerEvent) => {
+        let field = this.props.rowProps.original[this.props.rowProps.column.id as string];
+        let doc = FieldValue(Cast(field, Doc));
+
+        console.log("Expanding doc", StrCast(doc!.title));
+        this.props.setPreviewDoc(doc!);
+
+        // this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
+
+        e.stopPropagation();
+    }
+
     renderCellWithType(type: string | undefined) {
         let dragRef: React.RefObject<HTMLDivElement> = React.createRef();
 
@@ -157,6 +175,15 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         if (this.props.isFocused && this.props.isEditable) className += " focused";
         if (this.props.isFocused && !this.props.isEditable) className += " inactive";
 
+        let doc = FieldValue(Cast(field, Doc));
+        if (type === "document") console.log("doc", typeof field);
+        let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc);
+        let docExpander = (
+            <div className="collectionSchemaView-cellContents-docExpander" onPointerDown={this.expandDoc} >
+                <FontAwesomeIcon icon="expand" size="sm" />
+            </div>
+        );
+
         return (
             <div className="collectionSchemaView-cellContainer" ref={dragRef} onPointerDown={this.onPointerDown} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
                 <div className={className} ref={this._focusRef} tabIndex={-1}>
@@ -193,6 +220,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                                 val && val.forEach(doc => this.applyToDoc(doc, run));
                             }} />
                     </div >
+                    {fieldIsDoc ? docExpander : null}
                 </div>
             </div>
         );
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index d1d0674c4..9fc28eafa 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -10,11 +10,12 @@ import { ColumnType } from "./CollectionSchemaView";
 import { emptyFunction } from "../../../Utils";
 import { contains } from "typescript-collections/dist/lib/arrays";
 import { faFile } from "@fortawesome/free-regular-svg-icons";
+import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 
 library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile);
 
 export interface HeaderProps {
-    keyValue: string;
+    keyValue: SchemaHeaderField;
     possibleKeys: string[];
     existingKeys: string[];
     keyType: ColumnType;
@@ -33,14 +34,14 @@ export class CollectionSchemaHeader extends React.Component<HeaderProps> {
             this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify";
 
         return (
-            <div className="collectionSchemaView-header" >
+            <div className="collectionSchemaView-header" style={{ background: this.props.keyValue.color }}>
                 <CollectionSchemaColumnMenu
-                    keyValue={this.props.keyValue}
+                    keyValue={this.props.keyValue.heading}
                     possibleKeys={this.props.possibleKeys}
                     existingKeys={this.props.existingKeys}
                     keyType={this.props.keyType}
                     typeConst={this.props.typeConst}
-                    menuButtonContent={<div><FontAwesomeIcon icon={icon} size="sm" />{this.props.keyValue}</div>}
+                    menuButtonContent={<div><FontAwesomeIcon icon={icon} size="sm" />{this.props.keyValue.heading}</div>}
                     addNew={false}
                     onSelect={this.props.onSelect}
                     setIsEditing={this.props.setIsEditing}
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 0ddd56180..2349e42ca 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -12,14 +12,15 @@ import { library } from '@fortawesome/fontawesome-svg-core';
 import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { DocumentManager } from "../../util/DocumentManager";
+import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 
 library.add(faGripVertical, faTrash);
 
 export interface MovableColumnProps {
     columnRenderer: TableCellRenderer;
-    columnValue: string;
-    allColumns: string[];
-    reorderColumns: (toMove: string, relativeTo: string, before: boolean, columns: string[]) => void;
+    columnValue: SchemaHeaderField;
+    allColumns: SchemaHeaderField[];
+    reorderColumns: (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columns: SchemaHeaderField[]) => void;
     ScreenToLocalTransform: () => Transform;
 }
 export class MovableColumn extends React.Component<MovableColumnProps> {
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 91c6e8b3c..e0de76247 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -379,6 +379,7 @@ button.add-column {
 .collectionSchemaView-cellWrapper {
     height: 100%;
     padding: 4px;
+    position: relative;
 
     &:focus {
         outline: none;
@@ -405,6 +406,20 @@ button.add-column {
         height: 100%;
         // word-wrap: break-word;
     }
+
+    &:hover .collectionSchemaView-cellContents-docExpander {
+        display: block;
+    }
+}
+
+.collectionSchemaView-cellContents-docExpander {
+    height: 30px;
+    width: 30px;
+    display: none;
+    position: absolute;
+    top: 0;
+    right: 0;
+    background-color: lightgray;
 }
 
 .doc-drag-over {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index c6550560a..176872503 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -38,6 +38,7 @@ 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";
 
 
 library.add(faCog, faPlus, faSortUp, faSortDown);
@@ -284,11 +285,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @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(); }
-    @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); }
-    set columns(columns: string[]) { this.props.Document.schemaColumns = new List<string>(columns); }
+    @computed get columns() {
+        return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []);
+    }
+    set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
-        let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1);
+        let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1);
         let columns: Column<Doc>[] = [];
         let tableIsFocused = this.props.isFocused(this.props.Document);
         let focusedRow = this._focusedCell.row;
@@ -321,9 +324,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             let header = <CollectionSchemaHeader
                 keyValue={col}
                 possibleKeys={possibleKeys}
-                existingKeys={this.columns}
+                existingKeys={this.columns.map(c => c.heading)}
                 keyType={this.getColumnType(col)}
-                typeConst={columnTypes.get(col) !== undefined}
+                typeConst={col.type !== undefined || columnTypes.get(col.heading) !== undefined}
                 onSelect={this.changeColumns}
                 setIsEditing={this.setHeaderIsEditing}
                 deleteColumn={this.deleteColumn}
@@ -334,16 +337,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
             return {
                 Header: <MovableColumn columnRenderer={header} columnValue={col} allColumns={this.columns} reorderColumns={this.reorderColumns} ScreenToLocalTransform={this.props.ScreenToLocalTransform} />,
-                accessor: (doc: Doc) => doc ? doc[col] : 0,
-                id: col,
+                accessor: (doc: Doc) => doc ? doc[col.heading] : 0,
+                id: col.heading,
                 Cell: (rowProps: CellInfo) => {
-                    let row = rowProps.index;
-                    let column = this.columns.indexOf(rowProps.column.id!);
-                    let isFocused = focusedRow === row && focusedCol === column && tableIsFocused;
+                    let rowIndex = rowProps.index;
+                    let columnIndex = this.columns.map(c => c.heading).indexOf(rowProps.column.id!);
+                    let isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused;
 
                     let props: CellProps = {
-                        row: row,
-                        col: column,
+                        row: rowIndex,
+                        col: columnIndex,
                         rowProps: rowProps,
                         isFocused: isFocused,
                         changeFocusedCellByIndex: this.changeFocusedCellByIndex,
@@ -356,6 +359,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         moveDocument: this.props.moveDocument,
                         setIsEditing: this.setCellIsEditing,
                         isEditable: isEditable,
+                        setPreviewDoc: this.props.setPreviewDoc
                     };
 
                     let colType = this.getColumnType(col);
@@ -394,6 +398,15 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     //     }
     //     return this.props.Document;  
     // }
+    constructor(props: SchemaTableProps) {
+        super(props);
+        // convert old schema columns (list of strings) into new schema columns (list of schema header fields)
+        let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []);
+        if (oldSchemaColumns && oldSchemaColumns.length) {
+            let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i) : i);
+            this.props.Document.schemaColumns = new List<SchemaHeaderField>(newSchemaColumns);
+        }
+    }
 
     componentDidMount() {
         document.addEventListener("keydown", this.onKeyDown);
@@ -440,7 +453,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         let row = rowInfo.index;
         //@ts-ignore
-        let col = this.columns.indexOf(column!.id);
+        let col = this.columns.map(c => c.heading).indexOf(column!.id);
         // let col = column ? this.columns.indexOf(column!) : -1;
         let isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document);
         // let column = this.columns.indexOf(column.id!);
@@ -502,6 +515,11 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         if (!this._cellIsEditing && !this._headerIsEditing && this.props.isFocused(this.props.Document)) {// && this.props.isSelected()) {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
+
+            let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+            let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+            const pdoc = FieldValue(children[this._focusedCell.row]);
+            pdoc && this.props.setPreviewDoc(pdoc);
         }
     }
 
@@ -532,8 +550,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 this._focusedCell = { row: this._focusedCell.row + 1 === children.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col };
                 break;
         }
-        const pdoc = FieldValue(children[this._focusedCell.row]);
-        pdoc && this.props.setPreviewDoc(pdoc);
+        // const pdoc = FieldValue(children[this._focusedCell.row]);
+        // pdoc && this.props.setPreviewDoc(pdoc);
     }
 
     @action
@@ -544,8 +562,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this._focusedCell = { row: row, col: col };
         this.props.setFocused(this.props.Document);
 
-        const fdoc = FieldValue(children[this._focusedCell.row]);
-        fdoc && this.props.setPreviewDoc(fdoc);
+        // const fdoc = FieldValue(children[this._focusedCell.row]);
+        // fdoc && this.props.setPreviewDoc(fdoc);
     }
 
     createRow = () => {
@@ -561,25 +579,25 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @action
     createColumn = () => {
         let index = 0;
-        let found = this.columns.findIndex(col => col.toUpperCase() === "New field".toUpperCase()) > -1;
+        let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1;
         if (!found) {
-            this.columns.push("New field");
+            this.columns.push(new SchemaHeaderField("New field"));
             return;
         }
         while (found) {
             index++;
-            found = this.columns.findIndex(col => col.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
+            found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
         }
-        this.columns.push("New field (" + index + ")");
+        this.columns.push(new SchemaHeaderField("New field (" + index + ")"));
     }
 
     @action
     deleteColumn = (key: string) => {
-        let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
+        let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
-            this.props.Document.schemaColumns = list = new List<string>([]);
+            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([]);
         } else {
-            const index = list.indexOf(key);
+            const index = list.map(c => c.heading).indexOf(key);
             if (index > -1) {
                 list.splice(index, 1);
             }
@@ -588,26 +606,37 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeColumns = (oldKey: string, newKey: string, addNew: boolean) => {
-        let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
+        let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
-            this.props.Document.schemaColumns = list = new List<string>([newKey]);
+            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey)]);
         } else {
             if (addNew) {
-                this.columns.push(newKey);
+                this.columns.push(new SchemaHeaderField(newKey));
             } else {
-                const index = list.indexOf(oldKey);
+                const index = list.map(c => c.heading).indexOf(oldKey);
                 if (index > -1) {
-                    list[index] = newKey;
+                    list[index] = new SchemaHeaderField(newKey);
                 }
             }
         }
     }
 
-    getColumnType = (key: string): ColumnType => {
-        if (columnTypes.get(key)) return columnTypes.get(key)!;
+    getColumnType = (column: SchemaHeaderField): ColumnType => {
+        // added functionality to convert old column type stuff to new column type stuff -syip
+        if (column.type && column.type !== 0) {
+            return column.type;
+        }
+        if (columnTypes.get(column.heading)) {
+            column.type = columnTypes.get(column.heading)!;
+            return columnTypes.get(column.heading)!;
+        }
         const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc));
-        if (!typesDoc) return ColumnType.Any;
-        return NumCast(typesDoc[key]);
+        if (!typesDoc) {
+            column.type = ColumnType.Any;
+            return ColumnType.Any;
+        }
+        column.type = NumCast(typesDoc[column.heading]);
+        return NumCast(typesDoc[column.heading]);
     }
 
     setColumnType = (key: string, type: ColumnType): void => {
@@ -624,11 +653,11 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @action
-    setColumns = (columns: string[]) => {
+    setColumns = (columns: SchemaHeaderField[]) => {
         this.columns = columns;
     }
 
-    reorderColumns = (toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) => {
+    reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => {
         let columns = [...columnsValues];
         let oldIndex = columns.indexOf(toMove);
         let relIndex = columns.indexOf(relativeTo);
@@ -661,7 +690,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         //TODO Types
         untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false))));
 
-        this.columns.forEach(key => keys[key] = true);
+        this.columns.forEach(key => keys[key.heading] = true);
         return Array.from(Object.keys(keys));
     }
 
@@ -727,7 +756,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         csv = csv.substr(0, csv.length - 1) + "\n";
         let self = this;
         DocListCast(this.props.Document.data).map(doc => {
-            csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "0") + ",", "");
+            csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", "");
             csv = csv.substr(0, csv.length - 1) + "\n";
         });
         csv.substring(0, csv.length - 1);
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 7677f53c1..e897c5676 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -16,7 +16,7 @@ import { Transform } from "../../util/Transform";
 import { CursorProperty } from "csstype";
 import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
 import { listSpec } from "../../../new_fields/Schema";
-import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
 import { List } from "../../../new_fields/List";
 import { EditableView } from "../EditableView";
 import { CollectionViewProps } from "./CollectionBaseView";
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b765517a2..2e54a9736 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -19,6 +19,7 @@ import { CollectionViewType } from "../CollectionBaseView";
 import { CollectionFreeFormView } from "./CollectionFreeFormView";
 import "./MarqueeView.scss";
 import React = require("react");
+import { SchemaHeaderField, RandomPastel } from "../../../../new_fields/SchemaHeaderField";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -134,7 +135,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 doc.width = 200;
                 docList.push(doc);
             }
-            let newCol = Docs.Create.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
+            let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
 
             this.props.addDocument(newCol, false);
         }
diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx
index afde85b69..0ea948c81 100644
--- a/src/client/views/nodes/LinkEditor.tsx
+++ b/src/client/views/nodes/LinkEditor.tsx
@@ -11,6 +11,7 @@ import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTim
 import { library } from "@fortawesome/fontawesome-svg-core";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { SetupDrag } from "../../util/DragManager";
+import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
 
 library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus);
 
@@ -289,7 +290,7 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
         let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
         let index = keys.indexOf("");
         if (index > -1) keys.splice(index, 1);
-        let cols = ["anchor1", "anchor2", ...[...keys]];
+        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c));
         let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
         let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
         let ref = React.createRef<HTMLDivElement>();
diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx
index ae97bed2f..3637807ad 100644
--- a/src/client/views/nodes/LinkMenuGroup.tsx
+++ b/src/client/views/nodes/LinkMenuGroup.tsx
@@ -14,6 +14,7 @@ import { Docs } from "../../documents/Documents";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { UndoManager } from "../../util/UndoManager";
 import { StrCast } from "../../../new_fields/Types";
+import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
 
 interface LinkMenuGroupProps {
     sourceDoc: Doc;
@@ -70,7 +71,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
         let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
         let index = keys.indexOf("");
         if (index > -1) keys.splice(index, 1);
-        let cols = ["anchor1", "anchor2", ...[...keys]];
+        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c));
         let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
         let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
         let ref = React.createRef<HTMLDivElement>();
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index 284de3023..a6df31e81 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -3,13 +3,42 @@ import { serializable, createSimpleSchema, primitive } from "serializr";
 import { ObjectField } from "./ObjectField";
 import { Copy, ToScriptString, OnUpdate } from "./FieldSymbols";
 import { scriptingGlobal, Scripting } from "../client/util/Scripting";
+import { ColumnType } from "../client/views/collections/CollectionSchemaView";
 
 export const PastelSchemaPalette = new Map<string, string>([
-    ["purple", "#f5b5fc"],
-    ["green", "#96F7D2"],
-    ["yellow", "#F0F696"],
-    ["red", "#FCB1B1"]
-])
+    ["pink1", "#FFB4E8"],
+    ["pink2", "#ff9cee"],
+    ["pink3", "#ffccf9"],
+    ["pink4", "#fcc2ff"],
+    ["pink5", "#f6a6ff"],
+    ["purple1", "#b28dff"],
+    ["purple2", "#c5a3ff"],
+    ["purple3", "#d5aaff"],
+    ["purple4", "#ecd4ff"],
+    ["purple5", "#fb34ff"],
+    ["purple6", "#dcd3ff"],
+    ["purple7", "#a79aff"],
+    ["purple8", "#b5b9ff"],
+    ["purple9", "#97a2ff"],
+    ["bluegreen1", "#afcbff"],
+    ["bluegreen2", "#aff8db"],
+    ["bluegreen3", "#c4faf8"],
+    ["bluegreen4", "#85e3ff"],
+    ["bluegreen5", "#ace7ff"],
+    ["bluegreen6", "#6eb5ff"],
+    ["bluegreen7", "#bffcc6"],
+    ["bluegreen8", "#dbffd6"],
+    ["yellow1", "#f3ffe3"],
+    ["yellow2", "#e7ffac"],
+    ["yellow3", "#ffffd1"],
+    ["yellow4", "#fff5ba"],
+    ["red1", "#ffc9de"],
+    ["red2", "#ffabab"],
+    ["red3", "#ffbebc"],
+    ["red4", "#ffcbc1"],
+]);
+
+export const RandomPastel = () => Array.from(PastelSchemaPalette.values())[Math.floor(Math.random() * PastelSchemaPalette.size)];
 
 @scriptingGlobal
 @Deserializable("schemaheader")
@@ -17,12 +46,19 @@ export class SchemaHeaderField extends ObjectField {
     @serializable(primitive())
     heading: string;
     color: string;
+    type: number;
 
-    constructor(heading: string = "", color: string = Array.from(PastelSchemaPalette.values())[Math.floor(Math.random() * 4)]) {
+    constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) {
         super();
 
         this.heading = heading;
         this.color = color;
+        if (type) {
+            this.type = type;
+        }
+        else {
+            this.type = 0;
+        }
     }
 
     setHeading(heading: string) {
@@ -35,8 +71,13 @@ export class SchemaHeaderField extends ObjectField {
         this[OnUpdate]();
     }
 
+    setType(type: ColumnType) {
+        this.type = type;
+        this[OnUpdate]();
+    }
+
     [Copy]() {
-        return new SchemaHeaderField(this.heading, this.color);
+        return new SchemaHeaderField(this.heading, this.color, this.type);
     }
 
     [ToScriptString]() {
-- 
cgit v1.2.3-70-g09d2


From 8f4e803171bbf355e584fad6daa40d498253087f Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Sat, 27 Jul 2019 22:27:23 -0400
Subject: can script in any schema cell

---
 src/client/views/EditableView.tsx                  |  2 +-
 .../views/collections/CollectionSchemaCells.tsx    | 26 ++++---
 .../views/collections/CollectionSchemaView.tsx     | 82 +++++++++++++++++++++-
 3 files changed, 96 insertions(+), 14 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 373b63282..c3612fee9 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -134,7 +134,7 @@ export class EditableView extends React.Component<EditableProps> {
             return (
                 <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`}
                     style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }}
-                    onClick={this.onClick} >
+                    onClick={this.onClick}>
                     <span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize }}>{this.props.contents}</span>
                 </div>
             );
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index c91f1017b..e00142c91 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -24,7 +24,7 @@ import { SelectionManager } from "../../util/SelectionManager";
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faExpand } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 
 library.add(faExpand);
 
@@ -44,6 +44,8 @@ export interface CellProps {
     setIsEditing: (isEditing: boolean) => void;
     isEditable: boolean;
     setPreviewDoc: (doc: Doc) => void;
+    setComputed: (script: string, doc: Doc, field: string, row: number, col: number) => boolean;
+    getField: (row: number, col?: number) => void;
 }
 
 @observer
@@ -84,9 +86,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
     }
 
-    applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
-        const res = run({ this: doc });
+    applyToDoc = (doc: Doc, row: number, col: number, run: (args?: { [name: string]: any }) => any) => {
+        const res = run({ this: doc, $r: row, $c: col, $: (r: number = 0, c: number = 0) => this.props.getField(r + row, c + col) });
         if (!res.success) return false;
+        // doc[this.props.fieldKey] = res.result;
+        // return true;
         doc[this.props.rowProps.column.id as string] = res.result;
         return true;
     }
@@ -176,7 +180,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         if (this.props.isFocused && !this.props.isEditable) className += " inactive";
 
         let doc = FieldValue(Cast(field, Doc));
-        if (type === "document") console.log("doc", typeof field);
         let fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc);
         let docExpander = (
             <div className="collectionSchemaView-cellContents-docExpander" onPointerDown={this.expandDoc} >
@@ -203,22 +206,25 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                             }
                             }
                             SetValue={(value: string) => {
-                                let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
+                                if (value.startsWith(":=")) {
+                                    return this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, this.props.row, this.props.col);
+                                }
+                                let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
                                 if (!script.compiled) {
                                     return false;
                                 }
-                                return this.applyToDoc(props.Document, script.run);
+                                return this.applyToDoc(props.Document, this.props.row, this.props.col, script.run);
                             }}
                             OnFillDown={async (value: string) => {
-                                let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name } });
+                                let script = CompileScript(value, { requiredType: type, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
                                 if (!script.compiled) {
                                     return;
                                 }
                                 const run = script.run;
-                                //TODO This should be able to be refactored to compile the script once
                                 const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-                                val && val.forEach(doc => this.applyToDoc(doc, run));
-                            }} />
+                                val && val.forEach((doc, i) => this.applyToDoc(doc, i, this.props.col, run));
+                            }}
+                        />
                     </div >
                     {fieldIsDoc ? docExpander : null}
                 </div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index d504f9799..42843ad30 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -321,13 +321,12 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         }
 
         let cols = this.columns.map(col => {
-
             let header = <CollectionSchemaHeader
                 keyValue={col}
                 possibleKeys={possibleKeys}
                 existingKeys={this.columns.map(c => c.heading)}
                 keyType={this.getColumnType(col)}
-                typeConst={col.type !== undefined || columnTypes.get(col.heading) !== undefined}
+                typeConst={columnTypes.get(col.heading) !== undefined}
                 onSelect={this.changeColumns}
                 setIsEditing={this.setHeaderIsEditing}
                 deleteColumn={this.deleteColumn}
@@ -360,7 +359,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         moveDocument: this.props.moveDocument,
                         setIsEditing: this.setCellIsEditing,
                         isEditable: isEditable,
-                        setPreviewDoc: this.props.setPreviewDoc
+                        setPreviewDoc: this.props.setPreviewDoc,
+                        setComputed: this.setComputed,
+                        getField: this.getField,
                     };
 
                     let colType = this.getColumnType(col);
@@ -772,6 +773,81 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         }
     }
 
+    getField = (row: number, col?: number) => {
+        // const docs = DocListCast(this.props.Document[this.props.fieldKey]);
+
+        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        const docs = DocListCast(cdoc[this.props.fieldKey]);
+
+        row = row % docs.length;
+        while (row < 0) row += docs.length;
+        const columns = this.columns;
+        const doc = docs[row];
+        if (col === undefined) {
+            return doc;
+        }
+        if (col >= 0 && col < columns.length) {
+            const column = this.columns[col].heading;
+            return doc[column];
+        }
+        return undefined;
+    }
+
+    createTransformer = (row: number, col: number): Transformer => {
+        const self = this;
+        const captures: { [name: string]: Field } = {};
+
+        const transformer: ts.TransformerFactory<ts.SourceFile> = context => {
+            return root => {
+                function visit(node: ts.Node) {
+                    node = ts.visitEachChild(node, visit, context);
+                    if (ts.isIdentifier(node)) {
+                        const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node;
+                        const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node;
+                        if (isntPropAccess && isntPropAssign) {
+                            if (node.text === "$r") {
+                                return ts.createNumericLiteral(row.toString());
+                            } else if (node.text === "$c") {
+                                return ts.createNumericLiteral(col.toString());
+                            } else if (node.text === "$") {
+                                if (ts.isCallExpression(node.parent)) {
+                                    // captures.doc = self.props.Document;
+                                    // captures.key = self.props.fieldKey;
+                                }
+                            }
+                        }
+                    }
+
+                    return node;
+                }
+                return ts.visitNode(root, visit);
+            };
+        };
+
+        // const getVars = () => {
+        //     return { capturedVariables: captures };
+        // };
+
+        return { transformer, /*getVars*/ };
+    }
+
+    setComputed = (script: string, doc: Doc, field: string, row: number, col: number): boolean => {
+        script =
+            `const $ = (row:number, col?:number) => {
+                if(col === undefined) {
+                    return (doc as any)[key][row + ${row}];
+                }
+                return (doc as any)[key][row + ${row}][(doc as any).schemaColumns[col + ${col}].heading];
+            }
+            return ${script}`;
+        const compiled = CompileScript(script, { params: { this: Doc.name }, capturedVariables: { doc: this.props.Document, key: this.props.fieldKey }, typecheck: true, transformer: this.createTransformer(row, col) });
+        if (compiled.compiled) {
+            doc[field] = new ComputedField(compiled);
+            return true;
+        }
+        return false;
+    }
+
     render() {
         // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
         // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
-- 
cgit v1.2.3-70-g09d2


From 239e8b0a354b68a700181af3c4e9deb77fc8c009 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Sun, 28 Jul 2019 14:22:41 -0400
Subject: schema view now uses child docs

---
 src/client/views/collections/CollectionSchemaView.tsx | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 42843ad30..7da5665f3 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -202,7 +202,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 Document={this.props.Document} // child doc
                 PanelHeight={this.props.PanelHeight}
                 PanelWidth={this.props.PanelWidth}
-                // childDocs={this.childDocs}
+                childDocs={this.childDocs}
                 CollectionView={this.props.CollectionView}
                 ContainingCollectionView={this.props.ContainingCollectionView}
                 fieldKey={this.props.fieldKey} // might just be this.
@@ -252,7 +252,7 @@ export interface SchemaTableProps {
     dataDoc?: Doc;
     PanelHeight: () => number;
     PanelWidth: () => number;
-    // childDocs: Doc[];
+    childDocs: Doc[];
     CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     fieldKey: string;
@@ -299,8 +299,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let focusedCol = this._focusedCell.col;
         let isEditable = !this._headerIsEditing;// && this.props.isSelected();
 
-        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = DocListCast(cdoc[this.props.fieldKey]);
+        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        // let children = DocListCast(cdoc[this.props.fieldKey]);
+        let children = this.props.childDocs;
 
         if (children.reduce((found, doc) => found || doc.type === "collection", false)) {
             columns.push(
-- 
cgit v1.2.3-70-g09d2


From 6b50ec0f33c30b6100165d50811f4fa72657b66e Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Sun, 28 Jul 2019 14:41:45 -0400
Subject: schemas now actually use view specs

---
 .../views/collections/CollectionSchemaView.tsx     | 25 ++++++++++++++--------
 1 file changed, 16 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7da5665f3..77ed2d8dc 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -425,7 +425,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     tableRemoveDoc = (document: Doc): boolean => {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        let children = this.props.childDocs;
         if (children.indexOf(document) !== -1) {
             children.splice(children.indexOf(document), 1);
             return true;
@@ -520,7 +521,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             this.changeFocusedCellByDirection(direction);
 
             let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-            let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+            // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+            let children = this.props.childDocs;
             const pdoc = FieldValue(children[this._focusedCell.row]);
             pdoc && this.props.setPreviewDoc(pdoc);
         }
@@ -529,7 +531,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @action
     changeFocusedCellByDirection = (direction: string): void => {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        let children = this.props.childDocs;
         switch (direction) {
             case "tab":
                 if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) {
@@ -560,7 +563,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @action
     changeFocusedCellByIndex = (row: number, col: number): void => {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
 
         this._focusedCell = { row: row, col: col };
         this.props.setFocused(this.props.Document);
@@ -571,7 +574,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     createRow = () => {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        let children = this.props.childDocs;
 
         let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 });
         let proto = Doc.GetProto(newDoc);
@@ -683,7 +687,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     get documentKeys() {
-        const docs = DocListCast(this.props.Document[this.props.fieldKey]);
+        // const docs = DocListCast(this.props.Document[this.props.fieldKey]);
+        let docs = this.props.childDocs;
         let keys: { [key: string]: boolean } = {};
         // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
         //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
@@ -712,7 +717,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     get reactTable() {
 
         let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = DocListCast(cdoc[this.props.fieldKey]);
+        // let children = DocListCast(cdoc[this.props.fieldKey]);
+        let children = this.props.childDocs;
 
         let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
@@ -758,7 +764,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
         csv = csv.substr(0, csv.length - 1) + "\n";
         let self = this;
-        DocListCast(this.props.Document.data).map(doc => {
+        this.props.childDocs.map(doc => {
             csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", "");
             csv = csv.substr(0, csv.length - 1) + "\n";
         });
@@ -778,7 +784,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         // const docs = DocListCast(this.props.Document[this.props.fieldKey]);
 
         let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        const docs = DocListCast(cdoc[this.props.fieldKey]);
+        // const docs = DocListCast(cdoc[this.props.fieldKey]);
+        let docs = this.props.childDocs;
 
         row = row % docs.length;
         while (row < 0) row += docs.length;
-- 
cgit v1.2.3-70-g09d2


From 7098f381f3f93e77880f3589427c81e61a5ee25a Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Sun, 28 Jul 2019 17:56:59 -0400
Subject: started fixing schemaheaderfield bug

---
 src/client/views/collections/CollectionSchemaView.scss |  9 +++++++--
 src/client/views/collections/CollectionSchemaView.tsx  | 13 +++++++++++--
 src/new_fields/SchemaHeaderField.ts                    |  1 +
 3 files changed, 19 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index e0de76247..2e0ec20db 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -161,7 +161,7 @@
     }
 
     .rt-tr {
-        width: 100%;
+        // width: 100%;
         min-height: 30px;
         // height: $MAX_ROW_HEIGHT;
     }
@@ -195,6 +195,11 @@
             height: 100%;
         }
     }
+
+    .rt-resizer {
+        width: 20px;
+        right: -10px;
+    }
 }
 
 .documentView-node-topmost {
@@ -312,7 +317,7 @@ button.add-column {
     height: 100%;
     background-color: white;
 
-    &.row-focused {
+    &.row-focused .rt-tr {
         background-color: rgb(255, 246, 246);//$light-color-secondary;
     }
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 42843ad30..31de4e146 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -287,9 +287,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @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(); }
     @computed get columns() {
+        console.log("columns");
         return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []);
     }
-    set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
+    set columns(columns: SchemaHeaderField[]) { console.log("setting columns"); this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
     @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);
@@ -404,7 +405,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         super(props);
         // convert old schema columns (list of strings) into new schema columns (list of schema header fields)
         let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []);
-        if (oldSchemaColumns && oldSchemaColumns.length) {
+        if (oldSchemaColumns && oldSchemaColumns.length && typeof oldSchemaColumns[0] !== "object") {
+            console.log("REMAKING COLUMNs");
             let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i) : i);
             this.props.Document.schemaColumns = new List<SchemaHeaderField>(newSchemaColumns);
         }
@@ -583,6 +585,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let index = 0;
         let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1;
         if (!found) {
+            console.log("create column found");
             this.columns.push(new SchemaHeaderField("New field"));
             return;
         }
@@ -590,13 +593,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             index++;
             found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
         }
+        console.log("create column new");
         this.columns.push(new SchemaHeaderField("New field (" + index + ")"));
     }
 
     @action
     deleteColumn = (key: string) => {
+        console.log("deleting columnnn");
         let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
+            console.log("delete column");
             this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([]);
         } else {
             const index = list.map(c => c.heading).indexOf(key);
@@ -608,10 +614,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeColumns = (oldKey: string, newKey: string, addNew: boolean) => {
+        console.log("changingin columnsdfhs");
         let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
+            console.log("change columns new");
             this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey)]);
         } else {
+            console.log("change column");
             if (addNew) {
                 this.columns.push(new SchemaHeaderField(newKey));
             } else {
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index a6df31e81..84d9ae20e 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -49,6 +49,7 @@ export class SchemaHeaderField extends ObjectField {
     type: number;
 
     constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) {
+        console.log("CREATING SCHEMA HEADER FIELD");
         super();
 
         this.heading = heading;
-- 
cgit v1.2.3-70-g09d2


From e70f996dc25d466a2e94535b14997146d60977ec Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Sun, 28 Jul 2019 18:27:52 -0400
Subject: fixed moving and deleting documents

---
 .../views/collections/CollectionSchemaView.tsx     | 23 +++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 77ed2d8dc..8436b22a4 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -289,6 +289,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @computed get columns() {
         return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []);
     }
+    @computed get childDocs() { return this.props.childDocs; }
     set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
@@ -301,7 +302,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         // let children = DocListCast(cdoc[this.props.fieldKey]);
-        let children = this.props.childDocs;
+        let children = this.childDocs;
 
         if (children.reduce((found, doc) => found || doc.type === "collection", false)) {
             columns.push(
@@ -425,8 +426,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     tableRemoveDoc = (document: Doc): boolean => {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        let children = this.props.childDocs;
+        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = this.childDocs;
         if (children.indexOf(document) !== -1) {
             children.splice(children.indexOf(document), 1);
             return true;
@@ -522,7 +523,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
             let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
             // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-            let children = this.props.childDocs;
+            let children = this.childDocs;
             const pdoc = FieldValue(children[this._focusedCell.row]);
             pdoc && this.props.setPreviewDoc(pdoc);
         }
@@ -532,7 +533,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     changeFocusedCellByDirection = (direction: string): void => {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        let children = this.props.childDocs;
+        let children = this.childDocs;
         switch (direction) {
             case "tab":
                 if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) {
@@ -575,7 +576,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     createRow = () => {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        let children = this.props.childDocs;
+        let children = this.childDocs;
 
         let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 });
         let proto = Doc.GetProto(newDoc);
@@ -688,7 +689,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     get documentKeys() {
         // const docs = DocListCast(this.props.Document[this.props.fieldKey]);
-        let docs = this.props.childDocs;
+        let docs = this.childDocs;
         let keys: { [key: string]: boolean } = {};
         // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
         //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
@@ -718,7 +719,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         // let children = DocListCast(cdoc[this.props.fieldKey]);
-        let children = this.props.childDocs;
+        let children = this.childDocs;
 
         let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
@@ -730,7 +731,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         return <ReactTable
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
-            data={children}
+            data={this.childDocs}
             page={0}
             pageSize={children.length}
             showPagination={false}
@@ -764,7 +765,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
         csv = csv.substr(0, csv.length - 1) + "\n";
         let self = this;
-        this.props.childDocs.map(doc => {
+        this.childDocs.map(doc => {
             csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", "");
             csv = csv.substr(0, csv.length - 1) + "\n";
         });
@@ -785,7 +786,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         // const docs = DocListCast(cdoc[this.props.fieldKey]);
-        let docs = this.props.childDocs;
+        let docs = this.childDocs;
 
         row = row % docs.length;
         while (row < 0) row += docs.length;
-- 
cgit v1.2.3-70-g09d2


From 39a6c99d8466bf64b01edb285d776f3db7bf9eb8 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 11:51:17 -0400
Subject: fixed schema view vertical overflow scrolling + collection chrome
 collapsing

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

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 3c3708a30..c1f53f159 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -8,7 +8,8 @@
     box-sizing: border-box;
     // position: absolute;
     width: 100%;
-    height: calc(100% - 70px);
+    transition: height .5s;
+    height: 100%;
     // overflow: hidden;
     // overflow-x: scroll;
     // border: none;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7bd0b5965..7463429e0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -237,8 +237,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
         // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
         return (
-            <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
-                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
+            <div className="collectionSchemaView-container" style={{ height: this.chromeCollapsed ? "100%" : "calc(100% - 70px" }}
+                onPointerDown={this.onPointerDown} onWheel={this.onWheel} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
                 {this.schemaTable}
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index 6525f3b07..f9f3ce473 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -4,7 +4,7 @@
 .collectionViewChrome-cont {
     position: relative;
     z-index: 9001;
-    transition: top .5s;
+    transition: margin-top .5s;
     background: lightslategray;
     padding: 10px;
 
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 9c751c4df..2bffe3cc0 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={{ top: this._collapsed ? -100 : 0 }}>
+            <div className="collectionViewChrome-cont" style={{ marginTop: this._collapsed ? -70 : 0, height: 70 }}>
                 <div className="collectionViewChrome">
                     <div className="collectionViewBaseChrome">
                         <button className="collectionViewBaseChrome-collapse"
-                            style={{ top: this._collapsed ? 90 : 10, transform: `rotate(${this._collapsed ? 180 : 0}deg)` }}
+                            style={{ marginTop: this._collapsed ? 60 : 0, 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 5aa5bded4e90ec29bccac221ec115f5cd2f30791 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 11:58:25 -0400
Subject: reverted schematable childdocs back since tables won't rerender on
 change otherwise

---
 .../views/collections/CollectionSchemaView.tsx     | 60 +++++++++++-----------
 1 file changed, 31 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7463429e0..bb620cd63 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -290,10 +290,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         console.log("columns");
         return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []);
     }
-    @computed get childDocs() {
-        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        return DocListCast(doc[this.props.fieldKey]);
-    }
+    // @computed get childDocs() {
+    //     let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+    //     return DocListCast(doc[this.props.fieldKey]);
+    // }
     set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
@@ -304,9 +304,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let focusedCol = this._focusedCell.col;
         let isEditable = !this._headerIsEditing;// && this.props.isSelected();
 
-        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = DocListCast(cdoc[this.props.fieldKey]);
-        let children = this.childDocs;
+        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = DocListCast(cdoc[this.props.fieldKey]);
 
         if (children.reduce((found, doc) => found || doc.type === "collection", false)) {
             columns.push(
@@ -430,9 +429,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     tableRemoveDoc = (document: Doc): boolean => {
-        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        let children = this.childDocs;
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = this.childDocs;
         if (children.indexOf(document) !== -1) {
             children.splice(children.indexOf(document), 1);
             return true;
@@ -526,9 +525,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
 
-            // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-            // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-            let children = this.childDocs;
+            let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+            let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+            // let children = this.childDocs;
             const pdoc = FieldValue(children[this._focusedCell.row]);
             pdoc && this.props.setPreviewDoc(pdoc);
         }
@@ -536,9 +535,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeFocusedCellByDirection = (direction: string): void => {
-        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        let children = this.childDocs;
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = this.childDocs;
         switch (direction) {
             case "tab":
                 if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) {
@@ -579,9 +578,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     createRow = () => {
-        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        let children = this.childDocs;
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        // let children = this.childDocs;
 
         let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 });
         let proto = Doc.GetProto(newDoc);
@@ -700,8 +699,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     get documentKeys() {
-        // const docs = DocListCast(this.props.Document[this.props.fieldKey]);
-        let docs = this.childDocs;
+        const docs = DocListCast(this.props.Document[this.props.fieldKey]);
+
+        // let docs = this.childDocs;
         let keys: { [key: string]: boolean } = {};
         // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
         //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
@@ -729,9 +729,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @computed
     get reactTable() {
 
-        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = DocListCast(cdoc[this.props.fieldKey]);
-        let children = this.childDocs;
+        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = DocListCast(cdoc[this.props.fieldKey]);
+        // let children = this.childDocs;
 
         let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
@@ -743,7 +743,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         return <ReactTable
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
-            data={this.childDocs}
+            data={children}
             page={0}
             pageSize={children.length}
             showPagination={false}
@@ -777,7 +777,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
         csv = csv.substr(0, csv.length - 1) + "\n";
         let self = this;
-        this.childDocs.map(doc => {
+        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        let children = DocListCast(cdoc[this.props.fieldKey]);
+        children.map(doc => {
             csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", "");
             csv = csv.substr(0, csv.length - 1) + "\n";
         });
@@ -796,9 +798,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     getField = (row: number, col?: number) => {
         // const docs = DocListCast(this.props.Document[this.props.fieldKey]);
 
-        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // const docs = DocListCast(cdoc[this.props.fieldKey]);
-        let docs = this.childDocs;
+        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        const docs = DocListCast(cdoc[this.props.fieldKey]);
+        // let docs = this.childDocs;
 
         row = row % docs.length;
         while (row < 0) row += docs.length;
-- 
cgit v1.2.3-70-g09d2


From c361a566b2a3ce134bbb7e5906c23492c7012c7b Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 13:00:59 -0400
Subject: really fixed childdocs on schema

---
 .../views/collections/CollectionSchemaHeaders.tsx  | 39 +++++++++++
 .../views/collections/CollectionSchemaView.scss    | 13 ++++
 .../views/collections/CollectionSchemaView.tsx     | 75 ++++++++++++----------
 src/new_fields/SchemaHeaderField.ts                |  4 +-
 4 files changed, 96 insertions(+), 35 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 9fc28eafa..387107c55 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -129,6 +129,10 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         }
     }
 
+    changeColumnColor = (color: string): void => {
+
+    }
+
     renderTypes = () => {
         if (this.props.typeConst) return <></>;
         return (
@@ -168,6 +172,40 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         );
     }
 
+    renderColors = () => {
+        return (
+            <div className="collectionSchema-headerMenu-group">
+                <label>Color:</label>
+                <div className="columnMenu-colors">
+                    <input type="radio" name="column-color" id="pink" value="#FFB4E8" onClick={() => this.changeColumnColor("#FFB4E8")} />
+                    <label htmlFor="pink">
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                    </label>
+                    <input type="radio" name="column-color" id="purple" value="#b28dff" onClick={() => this.changeColumnColor("#b28dff")} />
+                    <label htmlFor="purple">
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                    </label>
+                    <input type="radio" name="column-color" id="blue" value="#afcbff" onClick={() => this.changeColumnColor("#afcbff")} />
+                    <label htmlFor="blue">
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                    </label>
+                    <input type="radio" name="column-color" id="yellow" value="#f3ffe3" onClick={() => this.changeColumnColor("#f3ffe3")} />
+                    <label htmlFor="yellow">
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                    </label>
+                    <input type="radio" name="column-color" id="red" value="#ffc9de" onClick={() => this.changeColumnColor("#ffc9de")} />
+                    <label htmlFor="red">
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                    </label>
+                    <input type="radio" name="column=color" id="none" value="#f1efeb" onClick={() => this.changeColumnColor("#f1efeb")} />
+                    <label htmlFor="none">
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                    </label>
+                </div>
+            </div>
+        );
+    }
+
     renderContent = () => {
         return (
             <div className="collectionSchema-header-menuOptions">
@@ -187,6 +225,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                     <>
                         {this.renderTypes()}
                         {this.renderSorting()}
+                        {this.renderColors()}
                         <div className="collectionSchema-headerMenu-group">
                             <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button>
                         </div>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index c1f53f159..053d6452c 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -311,6 +311,19 @@ button.add-column {
             border-radius: 20px;
         }
     }
+
+    .columnMenu-colors {
+
+
+        input[type="radio"] {
+            display: none;
+        }
+        
+        .columnMenu-colorPicker {
+            width: 20px;
+            height: 20px;
+        }
+    }
 }
 
 .collectionSchema-row {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index bb620cd63..53dd9523b 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -202,7 +202,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 Document={this.props.Document}
                 PanelHeight={this.props.PanelHeight}
                 PanelWidth={this.props.PanelWidth}
-                // childDocs={this.childDocs}
+                childDocs={this.childDocs}
                 CollectionView={this.props.CollectionView}
                 ContainingCollectionView={this.props.ContainingCollectionView}
                 fieldKey={this.props.fieldKey}
@@ -252,7 +252,7 @@ export interface SchemaTableProps {
     dataDoc?: Doc;
     PanelHeight: () => number;
     PanelWidth: () => number;
-    // childDocs: Doc[];
+    childDocs?: Doc[];
     CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     fieldKey: string;
@@ -290,10 +290,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         console.log("columns");
         return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []);
     }
-    // @computed get childDocs() {
-    //     let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-    //     return DocListCast(doc[this.props.fieldKey]);
-    // }
+    @computed get childDocs() {
+        if (this.props.childDocs) return this.props.childDocs;
+
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        return DocListCast(doc[this.props.fieldKey]);
+    }
+    set childDocs(docs: Doc[]) {
+        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        doc[this.props.fieldKey] = new List<Doc>(docs);
+    }
     set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
@@ -304,8 +310,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let focusedCol = this._focusedCell.col;
         let isEditable = !this._headerIsEditing;// && this.props.isSelected();
 
-        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = DocListCast(cdoc[this.props.fieldKey]);
+        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        // let children = DocListCast(cdoc[this.props.fieldKey]);
+        let children = this.childDocs;
 
         if (children.reduce((found, doc) => found || doc.type === "collection", false)) {
             columns.push(
@@ -411,7 +418,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []);
         if (oldSchemaColumns && oldSchemaColumns.length && typeof oldSchemaColumns[0] !== "object") {
             console.log("REMAKING COLUMNs");
-            let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i) : i);
+            let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i);
             this.props.Document.schemaColumns = new List<SchemaHeaderField>(newSchemaColumns);
         }
     }
@@ -429,11 +436,12 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     tableRemoveDoc = (document: Doc): boolean => {
-        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        // let children = this.childDocs;
+        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        let children = this.childDocs;
         if (children.indexOf(document) !== -1) {
             children.splice(children.indexOf(document), 1);
+            this.childDocs = children;
             return true;
         }
         return false;
@@ -525,9 +533,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
 
-            let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-            let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-            // let children = this.childDocs;
+            // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+            // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+            let children = this.childDocs;
             const pdoc = FieldValue(children[this._focusedCell.row]);
             pdoc && this.props.setPreviewDoc(pdoc);
         }
@@ -535,9 +543,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeFocusedCellByDirection = (direction: string): void => {
-        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        // let children = this.childDocs;
+        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        let children = this.childDocs;
         switch (direction) {
             case "tab":
                 if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === children.length) {
@@ -567,7 +575,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeFocusedCellByIndex = (row: number, col: number): void => {
-        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
 
         this._focusedCell = { row: row, col: col };
@@ -578,14 +586,15 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     createRow = () => {
-        let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-        // let children = this.childDocs;
+        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+        let children = this.childDocs;
 
         let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 });
         let proto = Doc.GetProto(newDoc);
         proto.title = "";
         children.push(newDoc);
+        this.childDocs = children;
     }
 
     @action
@@ -594,7 +603,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1;
         if (!found) {
             console.log("create column found");
-            this.columns.push(new SchemaHeaderField("New field"));
+            this.columns.push(new SchemaHeaderField("New field", "#f1efeb"));
             return;
         }
         while (found) {
@@ -602,7 +611,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
         }
         console.log("create column new");
-        this.columns.push(new SchemaHeaderField("New field (" + index + ")"));
+        this.columns.push(new SchemaHeaderField("New field (" + index + ")", "#f1efeb"));
     }
 
     @action
@@ -626,15 +635,15 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
             console.log("change columns new");
-            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey)]);
+            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]);
         } else {
             console.log("change column");
             if (addNew) {
-                this.columns.push(new SchemaHeaderField(newKey));
+                this.columns.push(new SchemaHeaderField(newKey, "f1efeb"));
             } else {
                 const index = list.map(c => c.heading).indexOf(oldKey);
                 if (index > -1) {
-                    list[index] = new SchemaHeaderField(newKey);
+                    list[index] = new SchemaHeaderField(newKey, "f1efeb");
                 }
             }
         }
@@ -729,9 +738,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @computed
     get reactTable() {
 
-        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = DocListCast(cdoc[this.props.fieldKey]);
-        // let children = this.childDocs;
+        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+        // let children = DocListCast(cdoc[this.props.fieldKey]);
+        let children = this.childDocs;
 
         let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
@@ -758,7 +767,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 row => {
                     if (row.original.type === "collection") {
                         // let childDocs = DocListCast(row.original[this.props.fieldKey]);
-                        return <div className="sub"><SchemaTable {...this.props} Document={row.original} /></div>;
+                        return <div className="sub"><SchemaTable {...this.props} Document={row.original} childDocs={undefined} /></div>;
                     }
                 }
                 : undefined}
@@ -778,8 +787,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         csv = csv.substr(0, csv.length - 1) + "\n";
         let self = this;
         let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        let children = DocListCast(cdoc[this.props.fieldKey]);
-        children.map(doc => {
+        // let children = DocListCast(cdoc[this.props.fieldKey]);
+        this.childDocs.map(doc => {
             csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", "");
             csv = csv.substr(0, csv.length - 1) + "\n";
         });
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index 84d9ae20e..d124a3907 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -48,12 +48,12 @@ export class SchemaHeaderField extends ObjectField {
     color: string;
     type: number;
 
-    constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) {
+    constructor(heading: string = "", color?: string, type?: ColumnType) {
         console.log("CREATING SCHEMA HEADER FIELD");
         super();
 
         this.heading = heading;
-        this.color = color;
+        this.color = color === "" || color === undefined ? RandomPastel() : color;
         if (type) {
             this.type = type;
         }
-- 
cgit v1.2.3-70-g09d2


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

---
 .../views/collections/CollectionSchemaView.scss    | 27 +++++++++++++---------
 .../views/collections/CollectionSchemaView.tsx     |  1 -
 .../views/collections/CollectionStackingView.scss  |  1 +
 .../views/collections/CollectionStackingView.tsx   |  2 +-
 .../CollectionStackingViewFieldColumn.tsx          |  2 +-
 src/client/views/collections/CollectionView.tsx    | 21 ++++++++++++-----
 .../views/collections/CollectionViewChromes.scss   |  5 ++--
 7 files changed, 37 insertions(+), 22 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index e0de76247..2697b482f 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -6,14 +6,14 @@
     border-style: solid;
     border-radius: $border-radius;
     box-sizing: border-box;
-    // position: absolute;
+    position: absolute;
+    top: 0;
     width: 100%;
     height: calc(100% - 50px);
     // overflow: hidden;
     // overflow-x: scroll;
     // border: none;
     overflow: hidden;
-    transition: top 0.5s;
 
     // .collectionSchemaView-cellContents {
     //     height: $MAX_ROW_HEIGHT;
@@ -78,7 +78,7 @@
         overflow-x: auto;
         height: 100%;
         display: -webkit-inline-box;
-        direction: ltr; 
+        direction: ltr;
     }
 
     .rt-thead {
@@ -122,7 +122,7 @@
         font-size: 13px;
         text-align: center;
         background-color: $light-color-secondary;
-        
+
         &:last-child {
             overflow: visible;
         }
@@ -147,7 +147,7 @@
         // &:nth-child(even) {
         //     background-color: $light-color;
         // }
-    
+
         // &:nth-child(odd) {
         //     background-color: $light-color-secondary;
         // }
@@ -175,7 +175,7 @@
         padding: 0;
         font-size: 13px;
         text-align: center;
-        
+
         // white-space: normal;
 
         .imageBox-cont {
@@ -207,18 +207,19 @@
     background: $light-color;
 }
 
-.collectionSchema-col{
+.collectionSchema-col {
     height: 100%;
 
     .collectionSchema-col-wrapper {
         &.col-before {
             border-left: 2px solid red;
         }
+
         &.col-after {
             border-right: 2px solid red;
         }
     }
-}  
+}
 
 
 .collectionSchemaView-header {
@@ -285,7 +286,7 @@ button.add-column {
                 background-color: $light-color;
                 border: 1px solid $light-color-secondary;
                 padding: 2px 3px;
-                
+
                 &:not(:last-child) {
                     border-top: 0;
                 }
@@ -313,7 +314,7 @@ button.add-column {
     background-color: white;
 
     &.row-focused {
-        background-color: rgb(255, 246, 246);//$light-color-secondary;
+        background-color: rgb(255, 246, 246); //$light-color-secondary;
     }
 
     &.row-wrapped {
@@ -358,9 +359,11 @@ button.add-column {
         &.row-above {
             border-top: 1px solid red;
         }
+
         &.row-below {
             border-bottom: 1px solid red;
         }
+
         &.row-inside {
             border: 1px solid red;
         }
@@ -461,7 +464,9 @@ button.add-column {
     .rt-table {
         overflow-x: hidden; // todo; this shouldnt be like this :((
         overflow-y: visible;
-    } // TODO fix
+    }
+
+    // TODO fix
 
     .row-dragger {
         background-color: rgb(252, 252, 252);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 8436b22a4..8fe66a949 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -72,7 +72,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable private _node: HTMLDivElement | null = null;
     @observable private _focusedTable: Doc = this.props.Document;
 
-    @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(); }
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 9dbe4ccb8..004b57eff 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -5,6 +5,7 @@
     width: 100%;
     position: absolute;
     display: flex;
+    top: 0;
     overflow-y: auto;
     flex-wrap: wrap;
     transition: top .5s;
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index f647da8f0..287c8a461 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -278,7 +278,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         };
         // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
         return (
-            <div className="collectionStackingView" style={{ top: this.chromeCollapsed ? 0 : 100 }}
+            <div className="collectionStackingView"
                 ref={this.createRef} onDrop={this.onDrop.bind(this)} onWheel={(e: React.WheelEvent) => e.stopPropagation()} >
                 {/* {sectionFilter as boolean ? [
                     ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())],
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',
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 81c84852a..462e86aa2 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, action, runInAction } from 'mobx';
+import { observable, action, runInAction, IReactionDisposer, reaction } from 'mobx';
 import { faEye } from '@fortawesome/free-regular-svg-icons';
 export const COLLECTION_BORDER_WIDTH = 2;
 
@@ -37,14 +37,23 @@ library.add(faImage, faEye);
 export class CollectionView extends React.Component<FieldViewProps> {
     @observable private _collapsed = false;
 
+    private _reactionDisposer: IReactionDisposer | undefined;
+
     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);
-        }
+        this._reactionDisposer = reaction(() => StrCast(this.props.Document.chromeStatus),
+            () => {
+                // 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);
+                }
+            });
+    }
+
+    componentWillUnmount = () => {
+        this._reactionDisposer && this._reactionDisposer();
     }
 
     private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index 6525f3b07..731333ff5 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -3,16 +3,17 @@
 
 .collectionViewChrome-cont {
     position: relative;
+    opacity: 0.9;
     z-index: 9001;
     transition: top .5s;
-    background: lightslategray;
+    background: lightgrey;
     padding: 10px;
 
     .collectionViewChrome {
         display: grid;
         grid-template-columns: 1fr auto;
         padding-bottom: 10px;
-        border-bottom: .5px solid lightgrey;
+        border-bottom: .5px solid rgb(180, 180, 180);
 
         .collectionViewBaseChrome {
             display: flex;
-- 
cgit v1.2.3-70-g09d2

