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/CollectionSchemaCells.tsx    | 440 +++++++++++++++++++++
 1 file changed, 440 insertions(+)
 create mode 100644 src/client/views/collections/CollectionSchemaCells.tsx

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
new file mode 100644
index 000000000..f15734df6
--- /dev/null
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -0,0 +1,440 @@
+import React = require("react");
+import { action, computed, observable, trace, untracked, toJS } from "mobx";
+import { observer } from "mobx-react";
+import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, Column } from "react-table";
+import "react-table/react-table.css";
+import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils";
+import { Doc, DocListCast, DocListCastAsync, Field, Opt } from "../../../new_fields/Doc";
+import { Id } from "../../../new_fields/FieldSymbols";
+import { SetupDrag, DragManager } from "../../util/DragManager";
+import { CompileScript } from "../../util/Scripting";
+import { Transform } from "../../util/Transform";
+import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../globalCssVariables.scss';
+import '../DocumentDecorations.scss';
+import { EditableView } from "../EditableView";
+import { FieldView, FieldViewProps } from "../nodes/FieldView";
+import { CollectionPDFView } from "./CollectionPDFView";
+import "./CollectionSchemaView.scss";
+import { CollectionVideoView } from "./CollectionVideoView";
+import { CollectionView } from "./CollectionView";
+import { NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
+
+
+export interface CellProps {
+    row: number;
+    col: number;
+    rowProps: CellInfo;
+    CollectionView: CollectionView | CollectionPDFView | CollectionVideoView;
+    ContainingCollection: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
+    Document: Doc;
+    fieldKey: string;
+    renderDepth: number;
+    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;
+}
+
+@observer
+export class CollectionSchemaCell extends React.Component<CellProps> {
+    @observable protected _isEditing: boolean = false;
+    protected _focusRef = React.createRef<HTMLDivElement>();
+    protected _document = this.props.rowProps.original;
+
+    componentDidMount() {
+        if (this._focusRef.current) {
+            if (this.props.isFocused) {
+                this._focusRef.current.className += " focused";
+            } else {
+                this._focusRef.current.className = "collectionSchemaView-cellWrapper";
+            }
+        }
+
+        document.addEventListener("keydown", this.onKeyDown);
+    }
+
+    componentWillUnmount() {
+        document.removeEventListener("keydown", this.onKeyDown);
+    }
+
+    @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);
+        }
+    }
+
+    @action
+    isEditingCallback = (isEditing: boolean): void => {
+        document.addEventListener("keydown", this.onKeyDown);
+        this._isEditing = isEditing;
+        this.props.setIsEditing(isEditing);
+    }
+
+    @action
+    onPointerDown = (e: React.PointerEvent): void => {
+        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,
+            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 = 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";
+
+        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}>
+                    <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 >
+            </div>
+        );
+    }
+
+    render() {
+        return this.renderCell(this.props.rowProps);
+    }
+}
+
+@observer
+export class CollectionSchemaNumberCell extends CollectionSchemaCell {
+    render() {
+        return this.renderCellWithType("number");
+    }
+}
+
+@observer
+export class CollectionSchemaBooleanCell extends CollectionSchemaCell {
+    render() {
+        return this.renderCellWithType("boolean");
+    }
+}
+
+@observer
+export class CollectionSchemaStringCell extends CollectionSchemaCell {
+    render() {
+        return this.renderCellWithType("string");
+    }
+}
+
+@observer
+export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
+    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 >
+            </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
-- 
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/CollectionSchemaCells.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/CollectionSchemaCells.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/CollectionSchemaCells.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 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/CollectionSchemaCells.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 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/CollectionSchemaCells.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 5da4de27c45e4f40c88b710be64f0129e9be7088 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Fri, 19 Jul 2019 16:21:19 -0400
Subject: focused cell styling + click editable view changes focuses on that
 cell

---
 src/client/views/EditableView.tsx                  |  2 +-
 .../views/collections/CollectionSchemaCells.tsx    |  1 +
 .../views/collections/CollectionSchemaHeaders.tsx  | 29 ----------------------
 .../views/collections/CollectionSchemaView.scss    |  7 +++++-
 4 files changed, 8 insertions(+), 31 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 42faedf9d..9471ae98a 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -79,7 +79,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();
     }
 
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 0307bb83e..31a9baa11 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -74,6 +74,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         document.addEventListener("keydown", this.onKeyDown);
         this._isEditing = isEditing;
         this.props.setIsEditing(isEditing);
+        this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
     }
 
     @action
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 5f8037fbf..df078eca5 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -56,38 +56,14 @@ 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;
     createColumn: () => void;
 }
 
 @observer
 export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHeaderProps> {
     render() {
-        let addButton = <button><FontAwesomeIcon icon="plus" size="sm" /></button>;
         return (
             <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>
         );
     }
 }
@@ -115,8 +91,6 @@ export interface ColumnMenuProps {
 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 _test = "test";
 
     componentDidMount() {
         document.addEventListener("pointerdown", this.detectClick);
@@ -168,9 +142,6 @@ 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)}>
-                        <FontAwesomeIcon icon={"toggle-on"} size="sm" />
-                        </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>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 47947829e..045994751 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -126,13 +126,14 @@
 
     .rt-tr {
         width: 100%;
+        height: $MAX_ROW_HEIGHT;
     }
 
     .rt-td {
         border-width: 1px;
         border-right-color: $intermediate-color;
         max-height: $MAX_ROW_HEIGHT;
-        padding: 3px 7px;
+        padding: 0;
         font-size: 13px;
         text-align: center;
 
@@ -289,6 +290,10 @@
     height: 100%;
     padding: 4px;
 
+    &:focus {
+        outline: none;
+    }
+
     &.focused {
         // background-color: yellowgreen;
         border: 2px solid yellowgreen;
-- 
cgit v1.2.3-70-g09d2


From e4ef3a04e3bd0bb20ed70181d51a9c419a00613f Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Fri, 19 Jul 2019 16:57:09 -0400
Subject: documents are now droppable and draggable

---
 .../views/collections/CollectionSchemaCells.tsx    | 71 +++++++++++++++-------
 1 file changed, 50 insertions(+), 21 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 1bb661f88..72d993b5a 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -17,7 +17,9 @@ import { CollectionPDFView } from "./CollectionPDFView";
 import "./CollectionSchemaView.scss";
 import { CollectionVideoView } from "./CollectionVideoView";
 import { CollectionView } from "./CollectionView";
-import { NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
+import { NumCast, StrCast, BoolCast, FieldValue, Cast } from "../../../new_fields/Types";
+import { Docs } from "../../documents/Documents";
+import { DocumentContentsView } from "../nodes/DocumentContentsView";
 
 
 export interface CellProps {
@@ -43,6 +45,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
     @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) {
@@ -54,6 +57,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         }
 
         document.addEventListener("keydown", this.onKeyDown);
+
     }
 
     componentWillUnmount() {
@@ -88,6 +92,27 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         return true;
     }
 
+    private drop = (e: Event, de: DragManager.DropEvent) => {
+        if (de.data instanceof DragManager.DocumentDragData) {
+            let fieldKey = this.props.rowProps.column.id as string;
+            if (de.data.draggedDocuments.length === 1) {
+                this._document[fieldKey] = de.data.draggedDocuments[0];
+            }
+            else {
+                let coll = Docs.Create.SchemaDocument(["title"], de.data.draggedDocuments, {});
+                this._document[fieldKey] = coll;
+            }
+            e.stopPropagation();
+        }
+    }
+
+    private dropRef = (ele: HTMLElement) => {
+        this._dropDisposer && this._dropDisposer();
+        if (ele) {
+            this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
+        }
+    }
+
     renderCellWithType(type: string | undefined) {
         let props: FieldViewProps = {
             Document: this.props.rowProps.original,
@@ -107,22 +132,25 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             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));
+            SetupDrag(this._focusRef, () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
+                (doc: Doc, target: Doc, addDoc: (newDoc: Doc) => any) => addDoc(doc), this._document[props.fieldKey] instanceof Doc ? "alias" : undefined)(e);
         };
 
         let field = props.Document[props.fieldKey];
         let contents: any = "incorrect type";
-        if (type === undefined) contents =  <FieldView {...props} />;
+        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 + "--";
+        if (type === "document") {
+            let doc = FieldValue(Cast(field, Doc));
+            contents = typeof field === "object" ? doc ? StrCast(doc.title) === "" ? "--" : StrCast(doc.title) : `--${typeof field}--` : `--${typeof field}--`;
+        }
 
         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}>
+                <div className="collectionSchemaView-cellContents" ref={this.dropRef} onPointerDown={onItemDown} key={props.Document[Id]}>
                     <EditableView
                         editing={this._isEditing}
                         // isEditingCallback={this.isEditingCallback}
@@ -193,9 +221,9 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
     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._document, script.run);
-            }
+        if (script.compiled) {
+            this.applyToDoc(this._document, script.run);
+        }
     }
 
     render() {
@@ -207,7 +235,7 @@ 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._document[Id]} ref={reference}>
-                    <input type="checkbox" checked={this._isChecked} onChange={this.toggleChecked}/>
+                    <input type="checkbox" checked={this._isChecked} onChange={this.toggleChecked} />
                 </div >
             </div>
         );
@@ -217,16 +245,17 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
 @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>
-        );
+        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>
+        // );
     }
 }
\ No newline at end of file
-- 
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/CollectionSchemaCells.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/CollectionSchemaCells.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/CollectionSchemaCells.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 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/CollectionSchemaCells.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 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/CollectionSchemaCells.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/CollectionSchemaCells.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 1bedf9e23afe26a284ba4804672ad4f396402813 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Thu, 25 Jul 2019 19:44:40 -0400
Subject: merge

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

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index d453fed47..4a618a436 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -158,8 +158,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         if (this.props.isFocused && !this.props.isEditable) className += " inactive";
 
         return (
-            <div className="collectionSchemaView-cellContainer" ref={dragRef} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
-                <div className={className} ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+            <div className="collectionSchemaView-cellContainer" ref={dragRef} onPointerDown={this.onPointerDown} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
+                <div className={className} ref={this._focusRef} tabIndex={-1}>
                     <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef : null} key={props.Document[Id]}>
                         <EditableView
                             editing={this._isEditing}
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 98ec971ef..e56c705f0 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -311,7 +311,7 @@ button.add-column {
 
     .row-dragger {
         display: flex;
-        justify-content: space-evenly;
+        justify-content: space-around;
         // height: $MAX_ROW_HEIGHT;
         flex: 50 0 auto;
         width: 50px;
@@ -406,6 +406,9 @@ button.add-column {
     justify-content: flex-end;
     padding: 0 10px;
 
+    border-bottom: 2px solid gray;
+    // margin-bottom: 10px;
+
     .collectionSchemaView-toolbar-item {
         display: flex;
         flex-direction: column;
-- 
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/CollectionSchemaCells.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

